@ui5/webcomponents-tools 1.3.1 → 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/CHANGELOG.md +11 -0
- package/components-package/nps.js +5 -1
- package/components-package/wdio.js +1 -1
- package/icons-collection/nps.js +1 -7
- package/lib/copy-and-watch/index.js +0 -1
- package/lib/copy-list/index.js +16 -16
- package/lib/create-icons/index.js +82 -72
- package/lib/create-illustrations/index.js +101 -90
- package/lib/documentation/index.js +119 -116
- package/lib/esm-abs-to-rel/index.js +13 -9
- package/lib/generate-json-imports/i18n.js +38 -31
- package/lib/generate-json-imports/themes.js +28 -21
- package/lib/hbs2lit/src/compiler.js +2 -2
- package/lib/hbs2lit/src/includesReplacer.js +5 -5
- package/lib/hbs2ui5/index.js +37 -21
- package/lib/i18n/defaults.js +49 -57
- package/lib/i18n/toJSON.js +12 -11
- package/lib/replace-global-core/index.js +13 -8
- package/package.json +3 -3
- package/lib/hash/config.js +0 -10
- package/lib/hash/generate.js +0 -19
- package/lib/hash/upToDate.js +0 -31
@@ -7,159 +7,162 @@ const eventsTemplate = require('./templates/api-events-section').template;
|
|
7
7
|
const methodsTemplate = require('./templates/api-methods-section').template;
|
8
8
|
const cssVariablesTemplate = require('./templates/api-css-variables-section').template;
|
9
9
|
const Handlebars = require('handlebars/dist/handlebars.min.js');
|
10
|
-
const fs = require('fs');
|
10
|
+
const fs = require('fs').promises;
|
11
11
|
const path = require('path');
|
12
|
-
const mkdirp = require('mkdirp');
|
13
12
|
const beautify = require("json-beautify");
|
14
13
|
|
14
|
+
const generate = async () => {
|
15
15
|
|
16
|
-
const apiJSONPath = path.normalize(process.argv[2]);
|
17
|
-
const api = JSON.parse(fs.
|
16
|
+
const apiJSONPath = path.normalize(process.argv[2]);
|
17
|
+
const api = JSON.parse(await fs.readFile(apiJSONPath));
|
18
18
|
|
19
|
-
fs.
|
19
|
+
await fs.writeFile(apiJSONPath, beautify(api, null, 2, 100));
|
20
20
|
|
21
|
-
const entries = api['symbols'];
|
22
|
-
const compiledHandlebars = Handlebars.compile(template);
|
23
|
-
const compiledSinceTemplate = Handlebars.compile(sinceTemplate);
|
24
|
-
const linkMatcher = /{@link(\s)(\w+)\s*}/gi;
|
25
|
-
const sinceMarker = "<!--since_tag_marker-->";
|
21
|
+
const entries = api['symbols'];
|
22
|
+
const compiledHandlebars = Handlebars.compile(template);
|
23
|
+
const compiledSinceTemplate = Handlebars.compile(sinceTemplate);
|
24
|
+
const linkMatcher = /{@link(\s)(\w+)\s*}/gi;
|
25
|
+
const sinceMarker = "<!--since_tag_marker-->";
|
26
26
|
|
27
|
-
const getComponentByName = name => {
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
};
|
27
|
+
const getComponentByName = name => {
|
28
|
+
return entries.find(element => {
|
29
|
+
return element.basename === name;
|
30
|
+
})
|
31
|
+
};
|
32
32
|
|
33
|
-
const getCSSVarsByName = name => {
|
34
|
-
|
35
|
-
};
|
33
|
+
const getCSSVarsByName = name => {
|
34
|
+
return cssVariables[name] || [];
|
35
|
+
};
|
36
36
|
|
37
|
-
const capitalize = str => {
|
38
|
-
|
39
|
-
};
|
40
|
-
|
41
|
-
Handlebars.registerHelper('toLowerCase', function (str) {
|
42
|
-
return str ? str.toLowerCase() : "";
|
43
|
-
});
|
37
|
+
const capitalize = str => {
|
38
|
+
return str.replace(/^./, str => str.toUpperCase());
|
39
|
+
};
|
44
40
|
|
45
|
-
Handlebars.registerHelper('
|
46
|
-
|
47
|
-
|
48
|
-
});
|
49
|
-
|
50
|
-
Handlebars.registerHelper('checkEven', function (iIndex) {
|
51
|
-
return (iIndex % 2 === 0) ? "api-table-roll-even" : "api-table-roll-odd";
|
52
|
-
});
|
41
|
+
Handlebars.registerHelper('toLowerCase', function (str) {
|
42
|
+
return str ? str.toLowerCase() : "";
|
43
|
+
});
|
53
44
|
|
54
|
-
Handlebars.
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
Handlebars.registerPartial('cssVariables', cssVariablesTemplate);
|
45
|
+
Handlebars.registerHelper('toKebabCase', function (str) {
|
46
|
+
const kebab = str.replace(/([a-z])([A-Z])/g, '$1-$2').toLowerCase();
|
47
|
+
return kebab !== str ? kebab : undefined;
|
48
|
+
});
|
59
49
|
|
60
|
-
|
50
|
+
Handlebars.registerHelper('checkEven', function (iIndex) {
|
51
|
+
return (iIndex % 2 === 0) ? "api-table-roll-even" : "api-table-roll-odd";
|
52
|
+
});
|
61
53
|
|
62
|
-
|
54
|
+
Handlebars.registerPartial('properties', propertiesTemplate);
|
55
|
+
Handlebars.registerPartial('slots', slotsTemplate);
|
56
|
+
Handlebars.registerPartial('events', eventsTemplate);
|
57
|
+
Handlebars.registerPartial('methods', methodsTemplate);
|
58
|
+
Handlebars.registerPartial('cssVariables', cssVariablesTemplate);
|
63
59
|
|
64
|
-
|
65
|
-
entry.cssVariables = getCSSVarsByName(entry.basename);
|
66
|
-
return entry;
|
67
|
-
}
|
60
|
+
await fs.mkdir(`dist/test-resources/api`, { recursive: true });
|
68
61
|
|
69
|
-
|
70
|
-
return component[entity].some(x => x && x.name === name);
|
71
|
-
};
|
72
|
-
const removeEmpty = arr => arr.filter(x => x);
|
62
|
+
let entriesAPI = [];
|
73
63
|
|
74
|
-
const
|
75
|
-
|
76
|
-
return
|
64
|
+
const appendCSSVarsAPI = entry => {
|
65
|
+
entry.cssVariables = getCSSVarsByName(entry.basename);
|
66
|
+
return entry;
|
77
67
|
}
|
78
|
-
const entities = ["properties", "slots", "events", "methods", "cssVariables"];
|
79
68
|
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
69
|
+
const componentHasEntityItem = (component, entity, name) => {
|
70
|
+
return component[entity].some(x => x && x.name === name);
|
71
|
+
};
|
72
|
+
const removeEmpty = arr => arr.filter(x => x);
|
84
73
|
|
85
|
-
|
74
|
+
const calculateAPI = component => {
|
75
|
+
if (entriesAPI.indexOf(component.basename) !== -1) {
|
76
|
+
return component;
|
77
|
+
}
|
78
|
+
const entities = ["properties", "slots", "events", "methods", "cssVariables"];
|
86
79
|
|
87
|
-
|
88
|
-
if (parent) {
|
89
|
-
let parentComponent = calculateAPI(parent);
|
80
|
+
// Initialize all entities with [] if necessary, and remove undefined things, and only leave public things
|
90
81
|
entities.forEach(entity => {
|
91
|
-
|
92
|
-
if (!componentHasEntityItem(component, entity, x.name)) {
|
93
|
-
component[entity].push(x);
|
94
|
-
}
|
95
|
-
});
|
82
|
+
component[entity] = removeEmpty(component[entity] || []).filter(x => x.visibility === "public");
|
96
83
|
});
|
97
|
-
}
|
98
84
|
|
99
|
-
|
85
|
+
component = appendCSSVarsAPI(component);
|
86
|
+
|
87
|
+
let parent = getComponentByName(component.extends);
|
88
|
+
if (parent) {
|
89
|
+
let parentComponent = calculateAPI(parent);
|
90
|
+
entities.forEach(entity => {
|
91
|
+
parentComponent[entity].forEach(x => {
|
92
|
+
if (!componentHasEntityItem(component, entity, x.name)) {
|
93
|
+
component[entity].push(x);
|
94
|
+
}
|
95
|
+
});
|
96
|
+
});
|
97
|
+
}
|
100
98
|
|
101
|
-
|
102
|
-
};
|
99
|
+
entriesAPI.push(component.basename);
|
103
100
|
|
104
|
-
|
105
|
-
|
106
|
-
const additionalEntries = entry.appenddocs.split(" ");
|
107
|
-
entry.additionalDocs = [];
|
101
|
+
return component;
|
102
|
+
};
|
108
103
|
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
entry.additionalDocs
|
113
|
-
});
|
114
|
-
}
|
104
|
+
const appendAdditionalEntriesAPI = entry => {
|
105
|
+
if (entry.appenddocs) {
|
106
|
+
const additionalEntries = entry.appenddocs.split(" ");
|
107
|
+
entry.additionalDocs = [];
|
115
108
|
|
116
|
-
|
117
|
-
|
109
|
+
additionalEntries.forEach(entryName => {
|
110
|
+
let additionalEntry = getComponentByName(entryName);
|
111
|
+
additionalEntry = calculateAPI(additionalEntry);
|
112
|
+
entry.additionalDocs.push(additionalEntry);
|
113
|
+
});
|
114
|
+
}
|
118
115
|
|
119
|
-
|
120
|
-
|
116
|
+
return entry;
|
117
|
+
}
|
121
118
|
|
122
|
-
|
123
|
-
content =
|
124
|
-
} catch (err) { }
|
119
|
+
const generateSamplePage = async entry => {
|
120
|
+
let content = "";
|
125
121
|
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
}
|
131
|
-
});
|
132
|
-
const APIReference = compiledHandlebars(entry).replace(/\[\]/g, " [0..n]");
|
133
|
-
const EntitySince = compiledSinceTemplate(entry).replace(/\[\]/g, " [0..n]");
|
122
|
+
try {
|
123
|
+
content = await fs.readFile(`dist/test-resources/samples/${capitalize(entry.basename)}.sample.html`, 'utf8');
|
124
|
+
} catch (err) {
|
125
|
+
}
|
134
126
|
|
135
|
-
|
136
|
-
|
127
|
+
if (content) {
|
128
|
+
entry.slots.forEach(slotData => {
|
129
|
+
if (!slotData.type.startsWith("Node") && !slotData.type.startsWith("HTMLElement")) { // interface -> don't show in documentation
|
130
|
+
slotData.type = "HTMLElement" + (slotData.type.endsWith("[]") ? "[]" : "");
|
131
|
+
}
|
132
|
+
});
|
133
|
+
const APIReference = compiledHandlebars(entry).replace(/\[\]/g, " [0..n]");
|
134
|
+
const EntitySince = compiledSinceTemplate(entry).replace(/\[\]/g, " [0..n]");
|
137
135
|
|
138
|
-
|
139
|
-
|
136
|
+
content = content.replace('<!-- JSDoc marker -->', APIReference);
|
137
|
+
content = content.replace(sinceMarker, EntitySince);
|
140
138
|
|
141
|
-
|
142
|
-
|
139
|
+
content = content.replace(linkMatcher, match => {
|
140
|
+
const component = linkMatcher.exec(match)[2];
|
143
141
|
|
144
|
-
|
145
|
-
|
142
|
+
// reset the regex
|
143
|
+
linkMatcher.lastIndex = 0;
|
146
144
|
|
147
|
-
|
148
|
-
|
149
|
-
|
145
|
+
return `<a href="#" onclick="redirect(event, '${component}')">${component}</a>`;
|
146
|
+
});
|
147
|
+
|
148
|
+
return fs.writeFile(`dist/test-resources/api/${entry.basename}.sample.html`, content);
|
149
|
+
}
|
150
150
|
}
|
151
|
-
}
|
152
151
|
|
153
|
-
const generateComponentAPI = entry => {
|
154
|
-
|
155
|
-
|
152
|
+
const generateComponentAPI = entry => {
|
153
|
+
// (1) calculate the API
|
154
|
+
entry = calculateAPI(entry);
|
156
155
|
|
157
|
-
|
158
|
-
|
156
|
+
// (2) append additional API for composition components - List -> ListIems, TabContainer -> Tabs, Table -> TableRow/Column/Cell
|
157
|
+
entry = appendAdditionalEntriesAPI(entry);
|
159
158
|
|
160
|
-
|
161
|
-
|
162
|
-
}
|
159
|
+
// (3) generate sample page
|
160
|
+
return generateSamplePage(entry);
|
161
|
+
}
|
162
|
+
|
163
|
+
return Promise.all(entries.map(generateComponentAPI));
|
164
|
+
};
|
163
165
|
|
164
|
-
|
165
|
-
|
166
|
+
generate().then(() => {
|
167
|
+
console.log("Documentation generated.");
|
168
|
+
});
|
@@ -1,15 +1,14 @@
|
|
1
1
|
const esprima = require("esprima");
|
2
2
|
const escodegen = require("escodegen");
|
3
3
|
|
4
|
-
const fs = require("fs");
|
4
|
+
const fs = require("fs").promises;
|
5
5
|
const path = require("path");
|
6
|
-
const glob = require("glob");
|
7
6
|
const basePath = process.argv[2];
|
8
7
|
|
9
|
-
const convertImports = (srcPath) => {
|
8
|
+
const convertImports = async (srcPath) => {
|
10
9
|
let changed = false;
|
11
10
|
// console.log("scanning imports of", srcPath);
|
12
|
-
let code = fs.
|
11
|
+
let code = (await fs.readFile(srcPath)).toString();
|
13
12
|
const tree = esprima.parseModule(code);
|
14
13
|
const importer = srcPath.replace(basePath, "");
|
15
14
|
const importerDir = path.dirname(importer);
|
@@ -44,11 +43,16 @@ const convertImports = (srcPath) => {
|
|
44
43
|
});
|
45
44
|
|
46
45
|
if (changed) {
|
47
|
-
fs.
|
46
|
+
return fs.writeFile(srcPath, escodegen.generate(tree));
|
48
47
|
}
|
49
48
|
}
|
50
49
|
|
51
|
-
const
|
52
|
-
|
53
|
-
fileNames
|
54
|
-
|
50
|
+
const generate = async () => {
|
51
|
+
const { globby } = await import("globby");
|
52
|
+
const fileNames = await globby(basePath + "**/*.js");
|
53
|
+
return Promise.all(fileNames.map(convertImports).filter(x => !!x));
|
54
|
+
};
|
55
|
+
|
56
|
+
generate().then(() => {
|
57
|
+
console.log("Success: Converted absolute imports to relative for files in:", basePath);
|
58
|
+
});
|
@@ -1,37 +1,38 @@
|
|
1
|
-
const fs = require("fs");
|
1
|
+
const fs = require("fs").promises;
|
2
2
|
const path = require('path');
|
3
|
-
const mkdirp = require("mkdirp");
|
4
3
|
|
5
|
-
const
|
4
|
+
const generate = async () => {
|
6
5
|
|
7
|
-
const
|
8
|
-
|
9
|
-
const
|
6
|
+
const packageName = JSON.parse(await fs.readFile("package.json")).name;
|
7
|
+
|
8
|
+
const inputFolder = path.normalize(process.argv[2]);
|
9
|
+
const outputFile = path.normalize(`${process.argv[3]}/i18n-static.js`);
|
10
|
+
const outputFileDynamic = path.normalize(`${process.argv[3]}/i18n.js`);
|
10
11
|
|
11
12
|
// All languages present in the file system
|
12
|
-
const files = fs.
|
13
|
-
const languages = files.map(file => {
|
14
|
-
|
15
|
-
|
16
|
-
}).filter(key => !!key);
|
13
|
+
const files = await fs.readdir(inputFolder);
|
14
|
+
const languages = files.map(file => {
|
15
|
+
const matches = file.match(/messagebundle_(.+?).json$/);
|
16
|
+
return matches ? matches[1] : undefined;
|
17
|
+
}).filter(key => !!key);
|
17
18
|
|
18
|
-
let contentStatic, contentDynamic;
|
19
|
+
let contentStatic, contentDynamic;
|
19
20
|
|
20
21
|
// No i18n - just import dependencies, if any
|
21
|
-
if (languages.length === 0) {
|
22
|
-
|
23
|
-
|
22
|
+
if (languages.length === 0) {
|
23
|
+
contentStatic = "";
|
24
|
+
contentDynamic = "";
|
24
25
|
// There is i18n - generate the full file
|
25
|
-
} else {
|
26
|
-
|
27
|
-
|
28
|
-
|
26
|
+
} else {
|
27
|
+
// Keys for the array
|
28
|
+
const languagesKeysString = languages.map(key => `"${key}": _${key},`).join("\n\t");
|
29
|
+
const languagesKeysStringArray = languages.map(key => `"${key}",`).join("\n\t");
|
29
30
|
|
30
|
-
|
31
|
-
|
31
|
+
// Actual imports for json assets
|
32
|
+
const assetsImportsString = languages.map(key => `import _${key} from "../assets/i18n/messagebundle_${key}.json";`).join("\n");
|
32
33
|
|
33
|
-
|
34
|
-
|
34
|
+
// static imports
|
35
|
+
contentStatic = `import { registerI18nLoader } from "@ui5/webcomponents-base/dist/asset-registries/i18n.js";
|
35
36
|
|
36
37
|
${assetsImportsString}
|
37
38
|
|
@@ -54,11 +55,11 @@ localeIds.forEach(localeId => {
|
|
54
55
|
});
|
55
56
|
`;
|
56
57
|
|
57
|
-
|
58
|
-
|
58
|
+
// Actual imports for json assets
|
59
|
+
const dynamicImportsString = languages.map(key => ` case "${key}": return (await import("../assets/i18n/messagebundle_${key}.json")).default;`).join("\n");
|
59
60
|
|
60
|
-
|
61
|
-
|
61
|
+
// Resulting file content
|
62
|
+
contentDynamic = `import { registerI18nLoader } from "@ui5/webcomponents-base/dist/asset-registries/i18n.js";
|
62
63
|
|
63
64
|
const importMessageBundle = async (localeId) => {
|
64
65
|
switch (localeId) {
|
@@ -83,9 +84,15 @@ localeIds.forEach(localeId => {
|
|
83
84
|
`;
|
84
85
|
|
85
86
|
|
86
|
-
}
|
87
|
+
}
|
87
88
|
|
89
|
+
await fs.mkdir(path.dirname(outputFile), { recursive: true });
|
90
|
+
return Promise.all([
|
91
|
+
fs.writeFile(outputFile, contentStatic),
|
92
|
+
fs.writeFile(outputFileDynamic, contentDynamic),
|
93
|
+
]);
|
94
|
+
}
|
88
95
|
|
89
|
-
|
90
|
-
|
91
|
-
|
96
|
+
generate().then(() => {
|
97
|
+
console.log("Generated i18n JSON imports.");
|
98
|
+
});
|
@@ -1,32 +1,32 @@
|
|
1
|
-
const fs = require("fs");
|
1
|
+
const fs = require("fs").promises;
|
2
2
|
const path = require('path');
|
3
|
-
const mkdirp = require("mkdirp");
|
4
3
|
const assets = require("../../assets-meta.js");
|
5
4
|
|
6
|
-
const
|
7
|
-
const
|
8
|
-
const
|
5
|
+
const generate = async () => {
|
6
|
+
const inputFolder = path.normalize(process.argv[2]);
|
7
|
+
const outputFile = path.normalize(`${process.argv[3]}/Themes-static.js`);
|
8
|
+
const outputFileDynamic = path.normalize(`${process.argv[3]}/Themes.js`);
|
9
9
|
|
10
10
|
// All supported optional themes
|
11
|
-
const allThemes = assets.themes.all;
|
11
|
+
const allThemes = assets.themes.all;
|
12
12
|
|
13
13
|
// All themes present in the file system
|
14
|
-
const dirs = fs.
|
15
|
-
const themesOnFileSystem = dirs.map(dir => {
|
16
|
-
|
17
|
-
|
18
|
-
}).filter(key => !!key && allThemes.includes(key));
|
14
|
+
const dirs = await fs.readdir(inputFolder);
|
15
|
+
const themesOnFileSystem = dirs.map(dir => {
|
16
|
+
const matches = dir.match(/sap_.*$/);
|
17
|
+
return matches ? dir : undefined;
|
18
|
+
}).filter(key => !!key && allThemes.includes(key));
|
19
19
|
|
20
|
-
const packageName = JSON.parse(fs.
|
20
|
+
const packageName = JSON.parse(await fs.readFile("package.json")).name;
|
21
21
|
|
22
|
-
const importLines = themesOnFileSystem.map(theme => `import ${theme} from "../assets/themes/${theme}/parameters-bundle.css.json";`).join("\n");
|
23
|
-
const themeUrlsByName = "{\n" + themesOnFileSystem.join(",\n") + "\n}";
|
24
|
-
const availableThemesArray = `[${themesOnFileSystem.map(theme => `"${theme}"`).join(", ")}]`;
|
25
|
-
const dynamicImportLines = themesOnFileSystem.map(theme => `\t\tcase "${theme}": return (await import("../assets/themes/${theme}/parameters-bundle.css.json")).default;`).join("\n");
|
22
|
+
const importLines = themesOnFileSystem.map(theme => `import ${theme} from "../assets/themes/${theme}/parameters-bundle.css.json";`).join("\n");
|
23
|
+
const themeUrlsByName = "{\n" + themesOnFileSystem.join(",\n") + "\n}";
|
24
|
+
const availableThemesArray = `[${themesOnFileSystem.map(theme => `"${theme}"`).join(", ")}]`;
|
25
|
+
const dynamicImportLines = themesOnFileSystem.map(theme => `\t\tcase "${theme}": return (await import("../assets/themes/${theme}/parameters-bundle.css.json")).default;`).join("\n");
|
26
26
|
|
27
27
|
|
28
28
|
// static imports file content
|
29
|
-
const contentStatic = `import { registerThemePropertiesLoader } from "@ui5/webcomponents-base/dist/asset-registries/Themes.js";
|
29
|
+
const contentStatic = `import { registerThemePropertiesLoader } from "@ui5/webcomponents-base/dist/asset-registries/Themes.js";
|
30
30
|
|
31
31
|
${importLines}
|
32
32
|
|
@@ -47,7 +47,7 @@ ${availableThemesArray}
|
|
47
47
|
|
48
48
|
|
49
49
|
// dynamic imports file content
|
50
|
-
const contentDynamic = `import { registerThemePropertiesLoader } from "@ui5/webcomponents-base/dist/asset-registries/Themes.js";
|
50
|
+
const contentDynamic = `import { registerThemePropertiesLoader } from "@ui5/webcomponents-base/dist/asset-registries/Themes.js";
|
51
51
|
|
52
52
|
const loadThemeProperties = async (themeName) => {
|
53
53
|
switch (themeName) {
|
@@ -68,6 +68,13 @@ ${availableThemesArray}
|
|
68
68
|
.forEach(themeName => registerThemePropertiesLoader("${packageName}", themeName, loadAndCheck));
|
69
69
|
`;
|
70
70
|
|
71
|
-
|
72
|
-
|
73
|
-
fs.
|
71
|
+
await fs.mkdir(path.dirname(outputFile), { recursive: true });
|
72
|
+
return Promise.all([
|
73
|
+
fs.writeFile(outputFile, contentStatic),
|
74
|
+
fs.writeFile(outputFileDynamic, contentDynamic)
|
75
|
+
]);
|
76
|
+
};
|
77
|
+
|
78
|
+
generate().then(() => {
|
79
|
+
console.log("Generated themes JSON imports.");
|
80
|
+
});
|
@@ -12,8 +12,8 @@ const removeWhiteSpaces = (source) => {
|
|
12
12
|
.replace(/}}\s+{{/g, "}}{{"); // Remove whitespace between }} and {{
|
13
13
|
};
|
14
14
|
|
15
|
-
const hbs2lit = (file) => {
|
16
|
-
let sPreprocessed = includesReplacer.replace(file);
|
15
|
+
const hbs2lit = async (file) => {
|
16
|
+
let sPreprocessed = await includesReplacer.replace(file);
|
17
17
|
|
18
18
|
sPreprocessed = removeWhiteSpaces(sPreprocessed);
|
19
19
|
|
@@ -1,9 +1,9 @@
|
|
1
1
|
const path = require("path");
|
2
|
-
const fs = require("fs");
|
2
|
+
const fs = require("fs").promises;
|
3
3
|
|
4
|
-
|
4
|
+
const replaceIncludes = async (file) => {
|
5
5
|
const filePath = path.dirname(file);
|
6
|
-
let fileContent = fs.
|
6
|
+
let fileContent = await fs.readFile(file, "utf-8");
|
7
7
|
|
8
8
|
const inclRegex = /{{>\s*include\s*["'](.+?)["']}}/g;
|
9
9
|
let match;
|
@@ -20,11 +20,11 @@ function replaceIncludes(file) {
|
|
20
20
|
targetFile = require.resolve(targetFile);
|
21
21
|
}
|
22
22
|
|
23
|
-
fileContent = fileContent.replace(match[0], replaceIncludes(targetFile));
|
23
|
+
fileContent = fileContent.replace(match[0], await replaceIncludes(targetFile));
|
24
24
|
}
|
25
25
|
|
26
26
|
return fileContent;
|
27
|
-
}
|
27
|
+
};
|
28
28
|
|
29
29
|
module.exports = {
|
30
30
|
replace: replaceIncludes
|
package/lib/hbs2ui5/index.js
CHANGED
@@ -1,10 +1,9 @@
|
|
1
|
-
const fs = require('fs');
|
1
|
+
const fs = require('fs').promises;
|
2
2
|
const getopts = require('getopts');
|
3
3
|
const hbs2lit = require('../hbs2lit');
|
4
4
|
const path = require('path');
|
5
5
|
const litRenderer = require('./RenderTemplates/LitRenderer');
|
6
6
|
const recursiveReadDir = require("recursive-readdir");
|
7
|
-
const mkdirp = require('mkdirp');
|
8
7
|
|
9
8
|
const args = getopts(process.argv.slice(2), {
|
10
9
|
alias: {
|
@@ -24,13 +23,13 @@ const onError = (place) => {
|
|
24
23
|
|
25
24
|
const isHandlebars = (fileName) => fileName.indexOf('.hbs') !== -1;
|
26
25
|
|
27
|
-
const processFile = (file, outputDir) => {
|
28
|
-
const litCode = hbs2lit(file);
|
26
|
+
const processFile = async (file, outputDir) => {
|
27
|
+
const litCode = await hbs2lit(file);
|
29
28
|
const absoluteOutputDir = composeAbsoluteOutputDir(file, outputDir);
|
30
29
|
const componentNameMatcher = /(\w+)(\.hbs)/gim;
|
31
30
|
const componentName = componentNameMatcher.exec(file)[1];
|
32
31
|
|
33
|
-
writeRenderers(absoluteOutputDir, componentName, litRenderer.generateTemplate(componentName, litCode));
|
32
|
+
return writeRenderers(absoluteOutputDir, componentName, litRenderer.generateTemplate(componentName, litCode));
|
34
33
|
};
|
35
34
|
|
36
35
|
const composeAbsoluteOutputDir = (file, outputDir) => {
|
@@ -40,39 +39,54 @@ const composeAbsoluteOutputDir = (file, outputDir) => {
|
|
40
39
|
const fileDir = file.split(path.sep).slice(1, -1).join(path.sep);
|
41
40
|
|
42
41
|
// (2) Compose full output dir - "dist/generated/templates/lvl1/lvl2"
|
43
|
-
return `${outputDir}${path.sep}${fileDir}`;
|
42
|
+
return `${outputDir}${path.sep}${fileDir}`;
|
44
43
|
};
|
45
44
|
|
46
45
|
const wrapDirectory = (directory, outputDir) => {
|
47
46
|
directory = path.normalize(directory);
|
48
47
|
outputDir = path.normalize(outputDir);
|
49
48
|
|
50
|
-
|
49
|
+
return new Promise((resolve, reject) => {
|
50
|
+
recursiveReadDir(directory, (err, files) => {
|
51
51
|
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
files.forEach(fileName => {
|
57
|
-
if (isHandlebars(fileName)) {
|
58
|
-
processFile(fileName, outputDir);
|
52
|
+
if (err) {
|
53
|
+
onError('directory');
|
54
|
+
reject();
|
59
55
|
}
|
56
|
+
|
57
|
+
const promises = files.map(fileName => {
|
58
|
+
if (isHandlebars(fileName)) {
|
59
|
+
return processFile(fileName, outputDir);
|
60
|
+
}
|
61
|
+
}).filter(x => !!x);
|
62
|
+
|
63
|
+
resolve(Promise.all(promises));
|
60
64
|
});
|
61
|
-
})
|
65
|
+
});
|
62
66
|
};
|
63
67
|
|
64
|
-
const writeRenderers = (outputDir, controlName, fileContent) => {
|
68
|
+
const writeRenderers = async (outputDir, controlName, fileContent) => {
|
65
69
|
try {
|
66
|
-
|
67
|
-
|
68
|
-
}
|
70
|
+
|
71
|
+
await fs.mkdir(outputDir, { recursive: true });
|
69
72
|
|
70
73
|
const compiledFilePath = `${outputDir}${path.sep}${controlName}Template.lit.js`;
|
71
74
|
|
72
75
|
// strip DOS line endings because the break the source maps
|
73
76
|
let fileContentUnix = fileContent.replace(/\r\n/g, "\n");
|
74
77
|
fileContentUnix = fileContentUnix.replace(/\r/g, "\n");
|
75
|
-
|
78
|
+
|
79
|
+
// Only write to the file system actual changes - each updated file, no matter if the same or not, triggers an expensive operation for rollup
|
80
|
+
// Note: .hbs files that include a changed .hbs file will also be recompiled as their content will be updated too
|
81
|
+
|
82
|
+
let existingFileContent = "";
|
83
|
+
try {
|
84
|
+
existingFileContent = await fs.readFile(compiledFilePath);
|
85
|
+
} catch (e) {}
|
86
|
+
|
87
|
+
if (existingFileContent !== fileContentUnix) {
|
88
|
+
return fs.writeFile(compiledFilePath, fileContentUnix);
|
89
|
+
}
|
76
90
|
|
77
91
|
} catch (e) {
|
78
92
|
console.log(e);
|
@@ -82,5 +96,7 @@ const writeRenderers = (outputDir, controlName, fileContent) => {
|
|
82
96
|
if (!args['d'] || !args['o']) {
|
83
97
|
console.log('Please provide an input and output directory (-d and -o)');
|
84
98
|
} else {
|
85
|
-
wrapDirectory(args['d'], args['o'])
|
99
|
+
wrapDirectory(args['d'], args['o']).then(() => {
|
100
|
+
console.log("Templates generated");
|
101
|
+
});
|
86
102
|
}
|