binhend 1.3.0 → 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.3.0",
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,10 +1,13 @@
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
12
  binh.context = function(module, defaultRequire) {
10
13
  var context = { module, require: defaultRequire };
@@ -44,14 +47,24 @@ function WebBuilder(binh, Binh) {
44
47
  var component = ui || service || style;
45
48
  var type = ui && 'ui' || service && 'service' || style && 'style';
46
49
 
47
- if (component == null) return;
50
+ if (!(component instanceof Function)) return;
48
51
 
49
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
+
50
62
  component.htmltags = [];
51
63
  component.links = [];
52
64
  component.options = { csses: [] };
53
-
54
- binh.bundle(type, context.module, component);
65
+ component.vars = {};
66
+ component.varname = getVariableName(component.filename);
67
+ component.as = alias;
55
68
  };
56
69
 
57
70
  binh.final = function(module) {
@@ -60,62 +73,58 @@ function WebBuilder(binh, Binh) {
60
73
  if (!(component instanceof Function)) return;
61
74
  if (component && component.constructor !== Component) return;
62
75
 
63
- module.children.forEach(function(child) {
64
- child = child.exports;
65
- if (child.constructor !== Component) return;
66
- if (child.alias) {
67
- 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;
68
81
  }
69
- });
82
+ }
70
83
  };
71
84
 
72
85
  binh.ui = function(module, component, htmltags, links) {
86
+ binh.component({ module }, component);
73
87
  component.htmltags = htmltags;
74
88
  component.links = links;
75
- binh.bundle('ui', module, component);
89
+ binh.final(module);
76
90
  };
77
91
 
78
92
  binh.service = function(module, component, links) {
93
+ binh.component({ module }, null, component, null);
79
94
  component.links = links;
80
- binh.bundle('service', module, component);
95
+ binh.final(module);
81
96
  };
82
97
 
83
98
  binh.style = function(module, component) {
84
- binh.bundle('style', module, component);
99
+ binh.component({ module }, null, null, component);
100
+ binh.final(module);
85
101
  };
86
102
 
87
103
  binh.css = function(module, cssFilename) {
88
104
  var cssFilePath = cssFilename && path.join(module.path, cssFilename) || module.filename.replace(/.js$/, '');
89
- var content = require('fs').readFileSync(cssFilePath, { encoding: 'utf8', flag: 'r' });
90
- content = content.replace(/\s+/g, ' ');
91
- var component = new Function(`return ${JSON.stringify(content)};`);
92
- binh.bundle('style', module, component);
93
- };
94
-
95
- binh.bundle = function(type, module, component) {
96
- if (!(component instanceof Function)) return;
97
-
98
- component.type = type;
99
- component.filename = module.filename;
100
- component.constructor = Component;
101
- component.module = module;
102
- component.as = alias;
103
- component.vars = {};
104
-
105
- module.exports = component;
106
-
107
- module.children.forEach(function(child) {
108
- child = child.exports;
109
- if (child.constructor !== Component) return;
110
- if (child.alias) component.vars[child.filename] = child.alias;
111
- });
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);
112
110
  };
113
111
 
114
112
  function alias(name) {
113
+ if (!isString(name)) return this;
114
+ name = name.trim();
115
115
  this.alias = name;
116
116
  return this;
117
117
  }
118
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
+
119
128
  Binh.web = function(webPath, sourcePath, modulePath) {
120
129
  switch (arguments.length) {
121
130
  case 1:
package/src/code.js CHANGED
@@ -1,138 +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 = '';
6
-
7
- var children = component.module.children;
8
-
9
- children.forEach(function(child) {
10
- child = child.exports;
11
-
12
- if (child.constructor !== component.constructor) return;
13
-
14
- var filename = child.filename;
7
+ filenames.forEach(function(filename) {
8
+ var existed = global[filename];
9
+
10
+ if (existed) return;
11
+
12
+ var { type, url, dependency } = local[filename];
15
13
 
16
- var url = '';
14
+ var dependencyDelaration = getDependencyDelaration(dependency, rootPath);
15
+ var componentCode = dependency.toString();
16
+ var optionCode = generateOptionCode(dependency, '', rootPath);
17
+ var htmlTagDeclaration = getHtmlTagDeclaration(dependency);
17
18
 
18
- if (filename.indexOf(root) === 0) {
19
- url = filename.replace(root, '').replace(/\\/g, '/');
19
+ if (dependencyDelaration) {
20
+ componentCode = componentCode.replace('{', `{\r\n${dependencyDelaration}\r\n`);
20
21
  }
21
- else {
22
- var nodeModulePaths = require.main.paths;
23
- var length = nodeModulePaths.length;
24
22
 
25
- for (var i = 0; i < length; i++) {
26
- var nodeModulePath = nodeModulePaths[i];
27
-
28
- if (filename.indexOf(nodeModulePath) === 0) {
29
- url = filename.replace(nodeModulePath, 'npm:/').replace(/\\/g, '/');
30
- break;
31
- }
32
- }
23
+ var blockCodes = [];
24
+ blockCodes.push(`Binh.${type}('${url}', ${type})${optionCode};`);
25
+ if (htmlTagDeclaration) {
26
+ blockCodes.push(htmlTagDeclaration);
33
27
  }
28
+ blockCodes.push(componentCode);
34
29
 
35
- var name = component.vars[filename] || parse(filename).name.replace(/-/g, '').replace(/\W.*/, '');
30
+ codes.push(IIF(blockCodes));
31
+ codes.push('');
36
32
 
37
- local[filename] = {
38
- name, url,
39
- type: child.type,
40
- component: child
41
- };
33
+ global[filename] = local[filename];
42
34
  });
43
35
 
44
- Object.keys(local).forEach(function(filename) {
45
- var declaration = '',
46
- current = local[filename],
47
- existed = global[filename];
36
+ filenames.forEach(function(filename) {
37
+ var { dependency } = local[filename];
38
+ var codeOfDependencies = getCodeOfDependencies(dependency, rootPath, global);
39
+ if (codeOfDependencies) codes.push(codeOfDependencies);
40
+ });
41
+
42
+ return codes.join('\r\n');
43
+ }
48
44
 
49
- var { type, name, url, component } = current;
45
+ function getDependencyDelaration(component, rootPath) {
46
+ var dependencies = getMetadataOfDependencies(component, rootPath);
47
+ var codes = [], fullCode = '';
50
48
 
51
- if (existed) {
52
- declaration += `Binh.later(function() {${name} = Binh.${type}('${url}');});\r\n`;
53
- variables[name] = true;
49
+ for (var filePath in dependencies) {
50
+ var { name, url, type } = dependencies[filePath];
51
+ if (name) {
52
+ codes.push(` ${name} = Binh.${type}('${url}')`);
54
53
  }
55
- else {
56
- declaration += `${name} = Binh.${type}('${url}', ${component.toString()});\r\n`;
57
- global[filename] = local[filename];
58
- variables[name] = true;
59
- };
54
+ }
60
55
 
61
- var optionCode = buildCodeApplyOptions(name, component);
56
+ var declarationCode = codes.join(',');
62
57
 
63
- if (optionCode) {
64
- declaration += `Binh.later(function() {${optionCode};});\r\n`;
65
- }
58
+ if (declarationCode) {
59
+ fullCode = [
60
+ `var Binh = _Binh;`,
61
+ `var${declarationCode};`,
62
+ ''
63
+ ].join('\r\n');
64
+ }
66
65
 
67
- code += IIF([
68
- dependencies(component, root, Object.assign({}, global, local)),
69
- declaration
70
- ]);
66
+ return fullCode;
67
+ }
71
68
 
72
- code += '\r\n\r\n';
73
- });
69
+ function getMetadataOfDependencies(component, rootPath) {
70
+ if (component.dependencies) return component.dependencies;
74
71
 
75
- var vars = Object.keys(variables);
72
+ var dependencies = component.module.children;
76
73
 
77
- if (vars.length) {
78
- code += `var ${vars.join(', ')};\r\n`;
79
- }
74
+ component.dependencies = {};
80
75
 
81
- return code;
76
+ dependencies.forEach(function(module) {
77
+ var dependency = module.exports;
78
+
79
+ if (dependency.constructor !== component.constructor) return;
80
+
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
+ };
89
+ });
90
+
91
+ return component.dependencies;
82
92
  }
83
93
 
84
- function buildCodeApplyOptions(componentName, component) {
85
- var options = component.options, variableNames = [];
94
+ function generateOptionCode(component, varname, rootPath) {
95
+ var options = component.options, urls = [];
86
96
 
87
97
  if (!options) return '';
88
98
 
89
99
  component.type === 'ui' && options.csses.forEach(function(cssModule) {
90
- var filename = cssModule.filename;
91
- var variableName = component.vars[filename] || parse(filename).name.replace(/-/g, '').replace(/\W.*/, '');
92
- variableNames.push(variableName);
100
+ var url = getRelativeFilePath(cssModule.filename, rootPath);
101
+ urls.push(JSON.stringify(url));
93
102
  });
94
103
 
95
- if (variableNames.length) {
96
- return `${componentName}.style([${variableNames.join(',')}])`;
104
+ if (urls.length) {
105
+ return `${varname}.style([${urls.join(',')}])`;
97
106
  }
98
107
 
99
108
  return '';
100
109
  }
101
110
 
102
- function bundle(component, root) {
103
- var code = '';
111
+ function getRelativeFilePath(filePath, rootPath) {
112
+ if (getRelativeFilePath.cache.hasOwnProperty(filePath)) {
113
+ return getRelativeFilePath.cache[filePath];
114
+ }
104
115
 
105
- code += dependencies(component, root);
116
+ var url = '';
106
117
 
107
- 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;
108
124
 
109
- code += `Binh.${component.type}(${component.toString()})${buildCodeApplyOptions('', component)};\r\n`;
125
+ for (var i = 0; i < length; i++) {
126
+ var nodeModulePath = nodeModulePaths[i];
110
127
 
111
- return code;
112
- }
128
+ if (filePath.indexOf(nodeModulePath) === 0) {
129
+ url = filePath.replace(nodeModulePath, 'npm:/').replace(/\\/g, '/');
130
+ break;
131
+ }
132
+ }
133
+ }
113
134
 
114
- function htmltags(component) {
115
- var code = '', list = [],
116
- tags = distinctValues(component, 'htmltags');
135
+ return url;
136
+ }
117
137
 
118
- tags.forEach(function(tag) {
119
- list.push(`${tag} = Binh.el('${tag}')`);
120
- });
138
+ getRelativeFilePath.cache = {};
121
139
 
122
- if (list.length) {
123
- 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}`);
124
148
  }
125
149
 
126
- code += code ? '\r\n' : '';
150
+ var codes = [];
127
151
 
128
- 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`);
129
181
  }
130
182
 
131
183
  function prequire(component, codes) {
132
184
  var code = '', links = distinctValues(component, 'links');
133
185
 
134
186
  if (links.length) {
135
- 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});`;
136
188
  }
137
189
  else {
138
190
  code = IIF(codes);
@@ -142,7 +194,7 @@ function prequire(component, codes) {
142
194
  }
143
195
 
144
196
  function IIF(codes) {
145
- return `!function(){\r\n\r\n${codes.join('\r\n')}\r\n}();`
197
+ return `!function(){\r\n${codes.join('\r\n')}\r\n}();`;
146
198
  }
147
199
 
148
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 = {
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'));