binhend 1.2.5 → 1.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "binhend",
3
- "version": "1.2.5",
3
+ "version": "1.4.0",
4
4
  "description": "",
5
5
  "main": "index.js",
6
6
  "author": "Nguyen Duc Binh",
@@ -15,7 +15,10 @@
15
15
  "example-web2": "node example_web2"
16
16
  },
17
17
  "dependencies": {
18
- "express": "^4.17.1"
18
+ "express": "^4.17.1",
19
+ "js-beautify": "^1.15.1",
20
+ "uglify-js": "^3.17.4",
21
+ "uglifycss": "^0.0.29"
19
22
  },
20
23
  "engines": {
21
24
  "node": ">=16.17.1",
@@ -1,18 +1,23 @@
1
1
 
2
2
  const path = require('path');
3
+ const fs = require('fs');
3
4
 
4
5
  const Component = require('./component');
5
6
  const ComponentFormat = require('./component.format');
6
7
  const ComponentBuild = require('./component.build');
7
8
 
9
+ const UglifyCSS = require('uglifycss');
10
+
8
11
  function WebBuilder(binh, Binh) {
9
- binh.context = function(module) {
10
- var context = { module };
12
+ binh.context = function(module, defaultRequire) {
13
+ var context = { module, require: defaultRequire };
11
14
  return {
12
15
  context,
13
16
  tag: tag.bind(context),
14
- script: script.bind(context)
15
- }
17
+ script: script.bind(context),
18
+ require: customRequire.bind(context),
19
+ css: css.bind(context)
20
+ };
16
21
  };
17
22
 
18
23
  function tag(tagNames) {
@@ -26,18 +31,40 @@ function WebBuilder(binh, Binh) {
26
31
  var links = this.component.links;
27
32
  links.push.apply(links, scripts);
28
33
  }
34
+
35
+ function customRequire(filePath) {
36
+ filePath = filePath.endsWith('.css') ? (filePath+'.js') : filePath;
37
+ return this.require(filePath);
38
+ }
39
+
40
+ function css() {
41
+ var csses = Array.from(arguments);
42
+ var appliedStyles = this.component.options.csses;
43
+ appliedStyles.push.apply(appliedStyles, csses);
44
+ }
29
45
 
30
46
  binh.component = function(context, ui, service, style) {
31
47
  var component = ui || service || style;
32
48
  var type = ui && 'ui' || service && 'service' || style && 'style';
33
49
 
34
- if (component == null) return;
50
+ if (!(component instanceof Function)) return;
35
51
 
36
52
  context.component = component;
53
+
54
+ var module = context.module;
55
+ module.exports = component;
56
+
57
+ component.module = module;
58
+ component.constructor = Component;
59
+ component.filename = module.filename;
60
+ component.type = type;
61
+
37
62
  component.htmltags = [];
38
63
  component.links = [];
39
-
40
- binh.bundle(type, context.module, component);
64
+ component.options = { csses: [] };
65
+ component.vars = {};
66
+ component.varname = getVariableName(component.filename);
67
+ component.as = alias;
41
68
  };
42
69
 
43
70
  binh.final = function(module) {
@@ -46,61 +73,58 @@ function WebBuilder(binh, Binh) {
46
73
  if (!(component instanceof Function)) return;
47
74
  if (component && component.constructor !== Component) return;
48
75
 
49
- module.children.forEach(function(child) {
50
- child = child.exports;
51
- if (child.constructor !== Component) return;
52
- if (child.alias) {
53
- component.vars[child.filename] = child.alias;
76
+ for (var index in module.children) {
77
+ var dependency = module.children[index].exports;
78
+ if (dependency.constructor !== Component) continue;
79
+ if (dependency.alias) {
80
+ component.vars[dependency.filename] = dependency.alias;
54
81
  }
55
- });
82
+ }
56
83
  };
57
84
 
58
85
  binh.ui = function(module, component, htmltags, links) {
86
+ binh.component({ module }, component);
59
87
  component.htmltags = htmltags;
60
88
  component.links = links;
61
- binh.bundle('ui', module, component);
89
+ binh.final(module);
62
90
  };
63
91
 
64
92
  binh.service = function(module, component, links) {
93
+ binh.component({ module }, null, component, null);
65
94
  component.links = links;
66
- binh.bundle('service', module, component);
95
+ binh.final(module);
67
96
  };
68
97
 
69
98
  binh.style = function(module, component) {
70
- binh.bundle('style', module, component);
99
+ binh.component({ module }, null, null, component);
100
+ binh.final(module);
71
101
  };
72
102
 
73
103
  binh.css = function(module, cssFilename) {
74
104
  var cssFilePath = cssFilename && path.join(module.path, cssFilename) || module.filename.replace(/.js$/, '');
75
- var content = require('fs').readFileSync(cssFilePath, { encoding: 'utf8', flag: 'r' });
76
- content = content.replace(/\s+/g, ' ');
77
- var component = new Function(`return ${JSON.stringify(content)};`);
78
- binh.bundle('style', module, component);
79
- };
80
-
81
- binh.bundle = function(type, module, component) {
82
- if (!(component instanceof Function)) return;
83
-
84
- component.type = type;
85
- component.filename = module.filename;
86
- component.constructor = Component;
87
- component.module = module;
88
- component.as = alias;
89
- component.vars = {};
90
-
91
- module.exports = component;
92
-
93
- module.children.forEach(function(child) {
94
- child = child.exports;
95
- if (child.constructor !== Component) return;
96
- if (child.alias) component.vars[child.filename] = child.alias;
97
- });
105
+ var content = fs.readFileSync(cssFilePath, { encoding: 'utf8', flag: 'r' });
106
+ content = UglifyCSS.processString(content);
107
+ var component = new Function(`return function style() { return ${JSON.stringify(content)}; };`)();
108
+ binh.component({ module }, null, null, component);
109
+ binh.final(module);
98
110
  };
99
111
 
100
112
  function alias(name) {
113
+ if (!isString(name)) return this;
114
+ name = name.trim();
101
115
  this.alias = name;
116
+ return this;
102
117
  }
103
118
 
119
+ function getVariableName(filePath) {
120
+ return path.parse(filePath).name.replace(/-/g, '').replace(/\W.*/, '').trim();
121
+ }
122
+
123
+ Binh.minify = function(flag = true) {
124
+ Component.minification = flag;
125
+ return Binh;
126
+ };
127
+
104
128
  Binh.web = function(webPath, sourcePath, modulePath) {
105
129
  switch (arguments.length) {
106
130
  case 1:
package/src/code.js CHANGED
@@ -1,117 +1,190 @@
1
1
 
2
- const { parse } = require('path');
2
+ function getCodeOfDependencies(component, rootPath, metadata) {
3
+ var global = metadata || {};
4
+ var local = getMetadataOfDependencies(component, rootPath);
5
+ var codes = [], filenames = Object.keys(local);
3
6
 
4
- function dependencies(component, root, metadata) {
5
- var global = metadata || {}, local = {}, variables = {}, code = '';
7
+ filenames.forEach(function(filename) {
8
+ var existed = global[filename];
9
+
10
+ if (existed) return;
11
+
12
+ var { type, url, dependency } = local[filename];
6
13
 
7
- var children = component.module.children;
14
+ var dependencyDelaration = getDependencyDelaration(dependency, rootPath);
15
+ var componentCode = dependency.toString();
16
+ var optionCode = generateOptionCode(dependency, '', rootPath);
17
+ var htmlTagDeclaration = getHtmlTagDeclaration(dependency);
8
18
 
9
- children.forEach(function(child) {
10
- child = child.exports;
19
+ if (dependencyDelaration) {
20
+ componentCode = componentCode.replace('{', `{\r\n${dependencyDelaration}\r\n`);
21
+ }
11
22
 
12
- if (child.constructor !== component.constructor) return;
23
+ var blockCodes = [];
24
+ blockCodes.push(`Binh.${type}('${url}', ${type})${optionCode};`);
25
+ if (htmlTagDeclaration) {
26
+ blockCodes.push(htmlTagDeclaration);
27
+ }
28
+ blockCodes.push(componentCode);
13
29
 
14
- var filename = child.filename;
30
+ codes.push(IIF(blockCodes));
31
+ codes.push('');
15
32
 
16
- var url = '';
33
+ global[filename] = local[filename];
34
+ });
17
35
 
18
- if (filename.indexOf(root) === 0) {
19
- url = filename.replace(root, '').replace(/\\/g, '/');
20
- }
21
- else {
22
- var nodeModulePaths = require.main.paths;
23
- var length = nodeModulePaths.length;
36
+ filenames.forEach(function(filename) {
37
+ var { dependency } = local[filename];
38
+ var codeOfDependencies = getCodeOfDependencies(dependency, rootPath, global);
39
+ if (codeOfDependencies) codes.push(codeOfDependencies);
40
+ });
24
41
 
25
- for (var i = 0; i < length; i++) {
26
- var nodeModulePath = nodeModulePaths[i];
42
+ return codes.join('\r\n');
43
+ }
27
44
 
28
- if (filename.indexOf(nodeModulePath) === 0) {
29
- url = filename.replace(nodeModulePath, 'npm:/').replace(/\\/g, '/');
30
- break;
31
- }
32
- }
45
+ function getDependencyDelaration(component, rootPath) {
46
+ var dependencies = getMetadataOfDependencies(component, rootPath);
47
+ var codes = [], fullCode = '';
48
+
49
+ for (var filePath in dependencies) {
50
+ var { name, url, type } = dependencies[filePath];
51
+ if (name) {
52
+ codes.push(` ${name} = Binh.${type}('${url}')`);
33
53
  }
54
+ }
34
55
 
35
- var name = component.vars[filename] || parse(filename).name.replace(/-/g, '').replace(/\W.*/, '');
56
+ var declarationCode = codes.join(',');
36
57
 
37
- local[filename] = {
38
- name, url,
39
- type: child.type,
40
- component: child
41
- };
42
- });
58
+ if (declarationCode) {
59
+ fullCode = [
60
+ `var Binh = _Binh;`,
61
+ `var${declarationCode};`,
62
+ ''
63
+ ].join('\r\n');
64
+ }
65
+
66
+ return fullCode;
67
+ }
43
68
 
44
- Object.keys(local).forEach(function(filename) {
45
- var declaration = '',
46
- current = local[filename],
47
- existed = global[filename];
69
+ function getMetadataOfDependencies(component, rootPath) {
70
+ if (component.dependencies) return component.dependencies;
48
71
 
49
- var { type, name, url, component } = current;
72
+ var dependencies = component.module.children;
50
73
 
51
- if (existed) {
52
- var sameVariableName = (name === existed.name);
53
- if (sameVariableName) return;
74
+ component.dependencies = {};
54
75
 
55
- declaration += `${name} = Binh.${type}('${url}');\r\n`;
56
- variables[name] = true;
57
- }
58
- else {
59
- declaration += `${name} = Binh.${type}('${url}', ${component.toString()});\r\n`;
60
- global[filename] = local[filename];
61
- variables[name] = true;
62
- };
76
+ dependencies.forEach(function(module) {
77
+ var dependency = module.exports;
63
78
 
64
- code += IIF([
65
- dependencies(component, root, Object.assign({}, global, local)),
66
- declaration
67
- ]);
79
+ if (dependency.constructor !== component.constructor) return;
68
80
 
69
- code += '\r\n\r\n';
81
+ var filename = dependency.filename;
82
+ var name = component.vars[filename] || dependency.varname;
83
+ var url = getRelativeFilePath(filename, rootPath);
84
+
85
+ component.dependencies[filename] = {
86
+ name, url, dependency,
87
+ type: dependency.type
88
+ };
70
89
  });
90
+
91
+ return component.dependencies;
92
+ }
71
93
 
72
- var vars = Object.keys(variables);
94
+ function generateOptionCode(component, varname, rootPath) {
95
+ var options = component.options, urls = [];
73
96
 
74
- if (vars.length) {
75
- code += `var ${vars.join(', ')};\r\n`;
97
+ if (!options) return '';
98
+
99
+ component.type === 'ui' && options.csses.forEach(function(cssModule) {
100
+ var url = getRelativeFilePath(cssModule.filename, rootPath);
101
+ urls.push(JSON.stringify(url));
102
+ });
103
+
104
+ if (urls.length) {
105
+ return `${varname}.style([${urls.join(',')}])`;
76
106
  }
77
107
 
78
- return code;
108
+ return '';
79
109
  }
80
110
 
81
- function bundle(component, root) {
82
- var code = '';
111
+ function getRelativeFilePath(filePath, rootPath) {
112
+ if (getRelativeFilePath.cache.hasOwnProperty(filePath)) {
113
+ return getRelativeFilePath.cache[filePath];
114
+ }
83
115
 
84
- code += dependencies(component, root);
116
+ var url = '';
85
117
 
86
- code += '\r\n';
118
+ if (filePath.indexOf(rootPath) === 0) {
119
+ url = filePath.replace(rootPath, '').replace(/\\/g, '/');
120
+ }
121
+ else {
122
+ var nodeModulePaths = require.main.paths;
123
+ var length = nodeModulePaths.length;
87
124
 
88
- code += `Binh.${component.type}(${component.toString()});\r\n`;
125
+ for (var i = 0; i < length; i++) {
126
+ var nodeModulePath = nodeModulePaths[i];
89
127
 
90
- return code;
91
- }
128
+ if (filePath.indexOf(nodeModulePath) === 0) {
129
+ url = filePath.replace(nodeModulePath, 'npm:/').replace(/\\/g, '/');
130
+ break;
131
+ }
132
+ }
133
+ }
92
134
 
93
- function htmltags(component) {
94
- var code = '', list = [],
95
- tags = distinctValues(component, 'htmltags');
135
+ return url;
136
+ }
96
137
 
97
- tags.forEach(function(tag) {
98
- list.push(`${tag} = Binh.el('${tag}')`);
99
- });
138
+ getRelativeFilePath.cache = {};
100
139
 
101
- if (list.length) {
102
- code = `var ${list.join(',\r\n')};`;
140
+ function bundle(component, rootPath) {
141
+ var codeOfDependencies = getCodeOfDependencies(component, rootPath);
142
+ var dependencyDelaration = getDependencyDelaration(component, rootPath);
143
+ var optionCode = generateOptionCode(component, '', rootPath);
144
+ var componentCode = component.toString();
145
+
146
+ if (dependencyDelaration) {
147
+ componentCode = componentCode.replace('{', `{\r\n${dependencyDelaration}`);
103
148
  }
104
149
 
105
- code += code ? '\r\n' : '';
150
+ var codes = [];
106
151
 
107
- return code;
152
+ if (codeOfDependencies) codes.push(codeOfDependencies);
153
+ if (componentCode) codes.push(`Binh.${component.type}(${componentCode})${optionCode};`);
154
+
155
+ return codes.join('\r\n');
156
+ }
157
+
158
+ function getHtmlTagDeclaration(component) {
159
+ var variablesList = component.htmltags.join(',');
160
+
161
+ if (!variablesList) return '';
162
+
163
+ return `var {${variablesList}} = Binh.els;\r\n`;
164
+ }
165
+
166
+ function htmltags(component) {
167
+ var tags = distinctValues(component, 'htmltags');
168
+
169
+ if (!tags.length) return '';
170
+
171
+ var variablesList = tags.join(',');
172
+ tags = tags.map((tag) => JSON.stringify(tag));
173
+
174
+ return [
175
+ `Binh.els = Binh.element(${tags.join(',')});`,
176
+ '',
177
+ `var {${variablesList}} = Binh.els;`,
178
+ ''
179
+ ]
180
+ .join(`\r\n`);
108
181
  }
109
182
 
110
183
  function prequire(component, codes) {
111
184
  var code = '', links = distinctValues(component, 'links');
112
185
 
113
186
  if (links.length) {
114
- code = `Binh.prequire(['${links.join("','")}'], function() {\r\n\r\n${codes.join('\r\n')}\r\n});`;
187
+ code = `Binh.prequire(['${links.join("','")}'], function() {\r\n${codes.join('\r\n')}\r\n});`;
115
188
  }
116
189
  else {
117
190
  code = IIF(codes);
@@ -121,7 +194,7 @@ function prequire(component, codes) {
121
194
  }
122
195
 
123
196
  function IIF(codes) {
124
- return `!function(){\r\n\r\n${codes.join('\r\n')}\r\n}();`
197
+ return `!function(){\r\n${codes.join('\r\n')}\r\n}();`;
125
198
  }
126
199
 
127
200
  function distinctValues(component, key) {
@@ -3,9 +3,8 @@ const { parse } = require('path');
3
3
  const { scanNestedFiles, cloneFile, writeToFile, makeFullDirPath } = require('./component.file');
4
4
  const CodeFormat = require('./code');
5
5
  const Component = require('./component');
6
-
7
- // TODO
8
- // [-] Able to minify/beautify generated files
6
+ const UglifyJS = require('uglify-js');
7
+ const BeautifyJS = require('js-beautify/js');
9
8
 
10
9
  function generate(sourceRootPath, outputRootPath, stageRootPath) {
11
10
  if (sourceRootPath == undefined || outputRootPath == undefined) return;
@@ -36,17 +35,33 @@ function generate(sourceRootPath, outputRootPath, stageRootPath) {
36
35
 
37
36
  var code = joinCodes(component, stageRootPath);
38
37
 
38
+ code = Component.minification ? minifyCode(code) : beautifyCode(code);
39
+
39
40
  writeToFile(fileOutputPath, code);
40
41
  });
41
42
  }
42
43
 
43
44
  function joinCodes(component, rootPath) {
44
- var fullcode = CodeFormat.prequire(component, [
45
- CodeFormat.bundle(component, rootPath),
46
- CodeFormat.htmltags(component)
45
+ var mainCode = CodeFormat.prequire(component, [
46
+ `var _Binh = Binh;\r\n`,
47
+ CodeFormat.htmltags(component),
48
+ CodeFormat.bundle(component, rootPath)
49
+ ]);
50
+
51
+ return CodeFormat.IIF([
52
+ `var Binh = window.Binh;`,
53
+ mainCode
47
54
  ]);
55
+ }
56
+
57
+ function minifyCode(code) {
58
+ var result = UglifyJS.minify(code);
59
+ if (result.error) throw result.error;
60
+ return result.code;
61
+ }
48
62
 
49
- return fullcode;
63
+ function beautifyCode(code) {
64
+ return BeautifyJS.js(code);
50
65
  }
51
66
 
52
67
  module.exports = {
@@ -7,28 +7,35 @@ const { scanNestedFiles, cloneFile, printError, makeFullDirPath } = require('./c
7
7
  // [-] Enhance code by removing sync logics (except for existsSync, mkdirSync): readdir, readFileSync, (statSync?)
8
8
 
9
9
  const PREFIX_CODE =
10
- `var { context, tag, script } = binh.context(module);
10
+ `var { context, tag, script, require, css } = binh.context(module, require);
11
11
  binh.component(context, ui, service, style);
12
12
  var ui = null, service = null, style = null;\r\n\r\n`;
13
13
 
14
14
  function generate(sourceRootPath, outputRootPath, callbackDone) {
15
15
  if (sourceRootPath == undefined || outputRootPath == undefined) return;
16
- console.log('[BINHEND][COMPONENT] Format files from:', sourceRootPath);
17
- console.log('[BINHEND][COMPONENT] to:', outputRootPath);
16
+ console.info('[BINHEND][COMPONENT] Format files from:', sourceRootPath);
17
+ console.info('[BINHEND][COMPONENT] to:', outputRootPath);
18
18
 
19
19
  scanNestedFiles(sourceRootPath, (file, done) => {
20
20
  if (done) return callbackDone instanceof Function ? callbackDone() : null;
21
21
 
22
22
  var fileSourcePath = file.path;
23
23
  var fileOutputPath = fileSourcePath.replace(sourceRootPath, outputRootPath);
24
-
25
- makeFullDirPath(fileOutputPath);
26
-
27
- if (parse(file.name).ext !== '.js') {
28
- return cloneFile(fileSourcePath, fileOutputPath);
29
- }
30
24
 
31
25
  try {
26
+ makeFullDirPath(fileOutputPath);
27
+
28
+ var fileExtension = parse(file.name).ext;
29
+
30
+ if (fileExtension === '.css') {
31
+ var cssModuleCode = 'binh.css(module);';
32
+ writeFileSync(fileOutputPath + '.js', cssModuleCode, { encoding: 'utf8', flag: 'w' });
33
+ }
34
+
35
+ if (fileExtension !== '.js') {
36
+ return cloneFile(fileSourcePath, fileOutputPath);
37
+ }
38
+
32
39
  var content = readFileSync(fileSourcePath, { encoding: 'utf8', flag: 'r' });
33
40
  var code = PREFIX_CODE + content.trim() + '\r\n\r\n;binh.final(module);';
34
41
  writeFileSync(fileOutputPath, code, { encoding: 'utf8', flag: 'w' });
package/src/component.js CHANGED
@@ -102,7 +102,8 @@ function showError(message, id, error) {
102
102
  }
103
103
 
104
104
  var Component = {
105
- generate
105
+ generate,
106
+ minification: false
106
107
  };
107
108
 
108
109
  module.exports = Component;
package/test.js ADDED
@@ -0,0 +1,22 @@
1
+ const path = require('path');
2
+
3
+
4
+ function parseFilePathToVariableName(filePath) {
5
+ return path.parse(filePath).name.replace(/-/g, '').replace(/\W.*/, '');
6
+ // try {
7
+ // }
8
+ // catch (error) {
9
+ // return '';
10
+ // }
11
+ };
12
+
13
+
14
+ // console.log(parseFilePathToVariableName(1));
15
+ console.log(parseFilePathToVariableName(''));
16
+ // console.log(parseFilePathToVariableName(null));
17
+ // console.log(parseFilePathToVariableName());
18
+ // console.log(parseFilePathToVariableName('abc.js'));
19
+ // console.log(parseFilePathToVariableName('abc,.js'));
20
+ // console.log(parseFilePathToVariableName('abc.css.js'));
21
+ // console.log(parseFilePathToVariableName('./uhm/abc.css.js'));
22
+ console.log(parseFilePathToVariableName('.css.js'));