How to tell Stylus to not fail on missing #import - stylus

I have a project that can be packaged for 2 targets (mobile and desktop). Tho I still want to keep my source files in the same place since only a few of them are different, but the difference is too big tho to do it only with responsive method (pages missing on mobile, or totally different on desktop, ...) and I want to keep the packaged app as small as possible.
So I created a loader.mobile.styl and loader.desktop.styl, knowing that the packager will import one or the other depending on the target/platform it's building for:
TARGET='mobile' // or 'desktop' for loader.desktop.stylus
#import '_import' // my import helper
import('_application') // my application main stylus file requiring al others
and in _import.styl:
import(file)
#import file
#import file + '.' + TARGET
So the goal is, when you call import('_application') for example, to first import _application.styl and then _application.mobile.styl (or _application.desktop.styl if the target is desktop)
It is working great except that in most of the cases only the shared _application.styl or the specific _application.mobile.styl may exist and not the other.
So I am trying without success to find a way to do an import if exists with Stylus. If just something like fileExists or such was available I could do it, or a try...catch even without the catch block, so that if it fails it doesn't matter.

After some research I ended up writing a plugin which would replace #import directive by defining a custom import function. For those who it might help, here is how I did in my own case:
In file plugins.js:
var sysPath = require('path');
var fs = require('fs');
// here is where I defined some helper to know what is the currently building target
var conf = require('../config');
var plugin = function () {
return function (style) {
var nodes = this.nodes;
style.define('import', function (param) {
var target = conf.currentTarget(),
realPath = sysPath.dirname(conf.ROOT + sysPath.sep + param.filename),
baseName = param.string.replace(/\.styl$/, ''),
targetFile = baseName + '.' + target + '.styl',
file = baseName + '.styl',
res = new nodes.Root();
// first include the file (myFile.styl for example) if it exists
if (fs.existsSync(realPath + sysPath.sep + file)) {
res.push(new nodes.Import(new nodes.String(file)));
}
// then include the target specific file (myFile.mobile.styl for example) if it exists
if (fs.existsSync(realPath + sysPath.sep + targetFile)) {
res.push(new nodes.Import(new nodes.String(targetFile)));
}
return res;
});
};
};
module.exports = plugin;
in file loader.styl:
use('plugins.js')
import('application')
So then any import('xyz') would import xyz.styl if it exists and xyz.mobile.styl (or xyz.desktop.styl if desktop is the target) if it exists.

Related

Google script Type error when try to move files to folder

I'm trying to select multiple files depending on the mime type (JPG and Google Docs in this example) and move to specific folders for each type. So I tried the following:
function test() {
var srcfolderId = "abcdefghi";
var jpgFolderID=DriveApp.getFolderById(srcfolderId).createFolder("jpgfiles").getId();
var gdocFolderID=DriveApp.getFolderById(srcfolderId).createFolder("gdocfiles").getId();
var jpgfiles=DriveApp.getFolderById(srcfolderId).getFilesByType(MimeType.JPEG);
var gdocfiles=DriveApp.getFolderById(srcfolderId).getFilesByType(MimeType.GOOGLE_DOCS);
jpgfiles.moveTo(jpgFolderID);
gdocfiles.moveTo(gdocFolderID);
}
But this creates the error:
TypeError: jpgfiles.moveTo is not a function
What should I need to do to escape from this error? Should I use a different way to move multiple files to a specific folder?
Modification points:
The reason for your issue of TypeError: jpgfiles.moveTo is not a function is due to that the argument of moveTo is the folder object. In your script, the folder ID is used.
DriveApp.getFolderById(srcfolderId) can be declared as one variable.
getFilesByType returns FileIterator.
When these points are reflected in your script, it becomes as follows.
Modified script:
function test() {
var srcfolderId = "abcdefghi";
var folder = DriveApp.getFolderById(srcfolderId);
var jpgFolder = folder.createFolder("jpgfiles");
var gdocFolder = folder.createFolder("gdocfiles");
var jpgfiles = folder.getFilesByType(MimeType.JPEG);
while (jpgfiles.hasNext()) {
jpgfiles.next().moveTo(jpgFolder);
}
var gdocfiles = folder.getFilesByType(MimeType.GOOGLE_DOCS);
while (gdocfiles.hasNext()) {
gdocfiles.next().moveTo(gdocFolder);
}
}
References:
getFilesByType(mimeType)
moveTo(destination)
Try adding something like this:
while(jpgfiles.hasNext()) {
let file = jpgfiles.next();
file.mmoveTo()....

how to code the utility functions in React without cluttering the component it'self

I have build this small react app with 3 components showing weatherforcaset from an api.
I am not sure how I have handled the utils functions in a separate node module is the correct way as it's pretty adhoc, mainly to do with the date handling and creating another 5 arrays with the data received from the api.
https://github.com/c-science1/weatherForecastReact/
Please can someone advise me if there is a better way if doing the same?
Many Thanks!
It looks like you can minimize the code in the function while keeping the DRY principle. You should refactor the following method:
this.createNewLists = function (dayName, itemP){
let itemDate = new Date(itemP.dt_txt);
let currentDate = new Date();
let nextDate = new Date(); ;
if (itemDate.getDate() == currentDate.getDate() ){
this.day1.push(itemP);
this.day1Name = dayName;
}
nextDate.setDate(nextDate.getDate() + 1);
if (itemDate.getDate() === nextDate.getDate()){
this.day2.push(itemP);
this.day2Name = dayName;
}
nextDate.setDate(nextDate.getDate() + 1);
if (itemDate.getDate() === nextDate.getDate()){
this.day3.push(itemP);
this.day3Name = dayName;
}
nextDate.setDate(nextDate.getDate() + 1);
if (itemDate.getDate() === nextDate.getDate()){
this.day4.push(itemP);
this.day4Name = dayName;
}
nextDate.setDate(nextDate.getDate() + 1);
if (itemDate.getDate() === nextDate.getDate()){
this.day5.push(itemP);
this.day5Name = dayName;
}
}
The pattern in this function are repeating them and you can better organize this code.
You can iterate from 1 to 5 (for the weekdays) and minimize your code and keep clean code and the DRY principle.
I would say for the size of your app it is just fine. Regarding things I might do differently, I would not use utils function wrapper, since you already have module serving as namespace.
As for weatherImage function I would probably put it into component file that uses it. If more than one component uses it, I would probably put it into components/common.js. createNewLists would probably also go to this module.

How to add a module to Angular in Pencilblue?

So I'm building this Pencilblue website. Pencilblue is based on the MEAN stack.
I'm trying to get a search function going. I need to declare a module.
Pencilblue does it like this:
ClientJs.getAngularController = function(objects, modules, directiveJS) {
if(!util.isArray(modules) || modules.length > 0) {
modules = ['ngRoute'];
}
var angularController = 'var pencilblueApp = angular.module("pencilblueApp", ' + JSON.stringify(modules) + ')';
So the 2nd line is telling me the modules are loaded from somewhere else, unless there are none, in which case, the modules = ['ngRoute']; should be loaded.
What I came up with is this:
ClientJs.getAngularController = function(objects, modules, directiveJS) {
if( modules.length > 0) {
modules = ['ngRoute', 'elasticui'];
}
var angularController = "var pencilblueApp = angular.module('pencilblueApp', " + JSON.stringify(modules) + ").constant('euiHost', 'localhost:9200')";
While this works, I'm not sure it's an orthodox way of doing it and I might need to add others in the future. I'd really appreciate if someone could help out and tell me the right way to add this ['elasticui'] module in Pencilblue, together with the last part, the .constant('euiHost', 'localhost:9200')";
I'm adding ElasticUI to my project, and the only thing that I had problems with was adding this step: angular.module('yourApp', ['elasticui']).constant('euiHost', 'http://localhost:9200');
It's rather trivial to do it in a MEAN stack or plain Angular.js, but it's quite confusing in Pencilblue.
Would really appreciate a detailed response on how to do this the proper way. Thanks.

Composite C1 blog - not using media folder

I have a Composite C1 4.04 site.
The user needs a blog - and they can upload images.
However, the images go into some weird virtual 'media' folder that apparently doesn't exist - and they aren't stored like normal images.
I would like them instead to just go into a regular folder - as I need to manipulate them later - to re-compress them (for example).
How can I do this?
thx
The media files are plugable in Composite C1, in the default implementation media files are represented as
A record in a database, that contains file's meta data (mime type, etc)
A physical file with the content, located under "\App_Data\Media" f.e.
\App_Data\Media\0b11c288-5432-4482-a776-3eb0ac9ad437
This has certain advantages - having a database record allows to keep additional meta data relevant to serving http requests (such as MimeType), apply security to those files, etc.
; also file names don't follow file system restrictions (such as path length and certain reserved names/forbidden characters) - so when you upload a file,
you don't have to care if website folder path + media folder path + file name would exceed 255 characters.
There are also other media archive plug-ings, when f.e. files are kept in a SQL data base or files are fetched from a Facebook album.
If you want to compress the image files, you can iterate over files in \App_Data\Media\ folder. You can get the list of media files by calling Get() on a DataConnection instance.
If you want to export media to a different solution, you can use the following code that copies a Composite C1 media folder to a physical folder:
private int MediaToFiles(string mediaFolder, string physicalFolder)
{
if (!mediaFolder.StartsWith("/"))
{
mediaFolder = "/" + mediaFolder;
}
string mediaFolderPrefix = mediaFolder == "/" ? "/" : mediaFolder + "/";
using (var conn = new DataConnection())
{
var mediaFiles = conn.Get<IMediaFile>().Where(f => string.Equals(f.FolderPath, mediaFolder, StringComparison.OrdinalIgnoreCase)
|| f.FolderPath.StartsWith(mediaFolderPrefix, StringComparison.OrdinalIgnoreCase))
.ToList();
if(mediaFiles.Count == 0) return 0;
Directory.CreateDirectory(physicalFolder);
int newFiles = 0;
foreach (var file in mediaFiles)
{
string targetFolder = file.FolderPath.Length <= mediaFolderPrefix.Length ?
physicalFolder : Path.Combine(physicalFolder, file.FolderPath.Substring(mediaFolderPrefix.Length));
Directory.CreateDirectory(targetFolder);
string targetFilePath = Path.Combine(targetFolder, file.FileName);
if(File.Exists(targetFilePath) && File.GetLastWriteTime(targetFilePath) == file.LastWriteTime) continue;
using (var stream = file.GetReadStream())
{
using (var outputStream = File.Create(targetFilePath, 8192))
{
stream.CopyTo(outputStream);
outputStream.Close();
}
}
File.SetLastWriteTime(targetFilePath, file.LastWriteTime.Value);
newFiles++;
}
return newFiles;
}
}
// Example of usage:
int newFiles = MediaToFiles("/", #"c:\Temp\C1media"); // Copying all the media files
OutPut("New files: " + newFiles);
int newFiles2 = MediaToFiles("/Office", #"c:\Temp\C1media\Office pictures"); // Copying only "Office" media folder
OutPut("New files: " + newFiles2);

gradle: Execute task "type:Exec" with many arguments with spaces

I have the gradle task that should create Websphere profile on Windows OS
task createProfile(type:Exec) {
def commandToExecute = new StringBuffer()
def profile = 'AppSrv02'
def wasHome = 'C:/IBM new/WebSphere/AppServer'
def str = new LinkedList <String> ();
str.add('cmd')
str.add('/c')
str.add(wasHome + '/bin/manageprofiles.bat')
str.add('-create')
str.add('-profileName')
str.add(profile)
//str.add('-templatePath')
//str.add(wasHome + '/profileTemplates/default')
println (str)
commandLine str.toArray()
}
And the problem appears if I uncomment commented lines, after it task fails and say me that: "C:/IBM" is not valid batch file. If I put profileTemplates not in the folder that contains spaces, everything works fine again. But templates should lies int wasHome( And sometimes wasHome has spaces(
I have, now ideas why adding templates key with value with spaces influence in such way that Gradle tries to start "C:/IBM" instead specified 'C:/IBM new/WebSphere/AppServer/bin/manageprofiles.bat'. It seems that, possibly, problem inside java.lang.ProcessBuilder.
I tries to quote paths, by adding "/"" but nothing works(((( what isn't surprise, because ProcessBuilder implies quoting by itself if it is needed.
So, I am asking if anybody had the similar problem and could recommend how to work around this issue? Thanks in advance.
If somebody needed it, we found a workaround for this problem. The task finally looks like:
task createProfile(type: Exec) {
executable = new File(wsadminLocation, manageProfilesFileName)
def templatePath = wasHome + File.separator + "profileTemplates" + File.separator + "default"
def argsList = ["-create", "-profileName", profile, "-templatePath", templatePath, "-nodeName", nodeName, "-cellName", wasCellName, "-enableAdminSecurity", isProfileSecured, "-adminUserName", rootProject.wasLogin, "-adminPassword", rootProject.wasPassword]
args = argsList
}
The basic idea is to pass the arguments to the Gradle not as long string, but as a list. So in this way there aren't any problems if an argument contains a space.
Change following lines
def wasHome = '"C:/IBM new/WebSphere/AppServer'
...
str.add(wasHome + '/bin/manageprofiles.bat"')
That way, the full path to the batch file is quoted.
EDITED - As stated by dbenhan, a little obfuscated. This "should" be something like
task createProfile(type:Exec) {
def commandToExecute = new StringBuffer()
def profile = 'AppSrv02'
def wasHome = 'C:/IBM new/WebSphere/AppServer'
def str = new LinkedList <String> ();
str.add('cmd')
str.add('/c')
str.add('"' + wasHome + '/bin/manageprofiles.bat"')
str.add('-create')
str.add('-profileName')
str.add(profile)
str.add('-templatePath')
str.add('"' + wasHome + '/profileTemplates/default"')
println (str)
commandLine str.toArray()
}
BUT, while gradle in particular and windows in general can handle paths with slash separators, i have no idea if manageprofiles.bat can, and you are passing a parameter with a path in it. Maybe, you will need to change your paths to 'c:\\IBM new\\....'
Try This
task xyz {
def result1 = exec {
workingDir "D:/abc/efg"
commandLine 'cmd', '/c', 'CDUTIL.bat', "qwe", "rty"
}
println result1.toString()
}

Resources