lui-templates 0.0.6

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.
Files changed (34) hide show
  1. package/.vscode/settings.json +10 -0
  2. package/README.md +103 -0
  3. package/package.json +32 -0
  4. package/schema/intermediary.json +147 -0
  5. package/src/cli.js +59 -0
  6. package/src/constants.js +8 -0
  7. package/src/generator.js +276 -0
  8. package/src/main.js +74 -0
  9. package/src/parser.js +57 -0
  10. package/src/parsers/json.js +9 -0
  11. package/src/parsers/liquid.js +1194 -0
  12. package/test/basic.js +9 -0
  13. package/test/templates/article.liquid +9 -0
  14. package/test/templates/button.liquid +3 -0
  15. package/test/templates/complex-nested.liquid +11 -0
  16. package/test/templates/complex.liquid +4 -0
  17. package/test/templates/conditional-bool-attr.liquid +4 -0
  18. package/test/templates/conditional-nonbool-attr.liquid +4 -0
  19. package/test/templates/conditional-unless-attr.liquid +4 -0
  20. package/test/templates/conditional-unless-nonbool-attr.liquid +4 -0
  21. package/test/templates/conditional.liquid +6 -0
  22. package/test/templates/dynamic-class.liquid +1 -0
  23. package/test/templates/greeting.json +74 -0
  24. package/test/templates/image.liquid +5 -0
  25. package/test/templates/link.json +31 -0
  26. package/test/templates/mixed.liquid +5 -0
  27. package/test/templates/nested-attr-conditionals.liquid +1 -0
  28. package/test/templates/nested-comprehensive.liquid +51 -0
  29. package/test/templates/nested-conditionals.liquid +9 -0
  30. package/test/templates/nested-if-flatten.liquid +6 -0
  31. package/test/templates/root-text.liquid +2 -0
  32. package/test/templates/test-attr-cond.liquid +1 -0
  33. package/test/templates/text-nodes.liquid +5 -0
  34. package/test/templates/unless.liquid +5 -0
package/src/main.js ADDED
@@ -0,0 +1,74 @@
1
+ import {
2
+ readFileSync,
3
+ } from 'fs';
4
+ import {
5
+ readdir,
6
+ stat,
7
+ } from 'fs/promises';
8
+ import {dirname} from 'path';
9
+ import {fileURLToPath} from 'url';
10
+
11
+ import {
12
+ generate,
13
+ list_generate,
14
+ } from './generator.js';
15
+ import {parse} from './parser.js';
16
+
17
+ const __dirname = dirname(fileURLToPath(import.meta.url));
18
+ const version = JSON.parse(
19
+ readFileSync(__dirname + '/../package.json', 'utf8')
20
+ ).version;
21
+
22
+ const options_default = {
23
+ lui_name: 'lui',
24
+ components_name: './externs.js',
25
+ };
26
+
27
+ export default async function lui_templates(path, options = {}) {
28
+ options = {
29
+ ...options_default,
30
+ ...options,
31
+ };
32
+ const is_directory = (await stat(path)).isDirectory();
33
+
34
+ const paths = is_directory
35
+ ? (await readdir(path)).map(name => `${path}/${name}`)
36
+ : [path];
37
+
38
+ const all_parsed = await Promise.all(paths.map(parse));
39
+
40
+ // console.log('parsed', JSON.stringify(all_parsed, null, 2));
41
+
42
+ const lui_imports = new Set();
43
+ const component_imports = new Set();
44
+ const result = [];
45
+
46
+ for (const [name, parsed] of all_parsed) {
47
+ const expression = generate(name, parsed, lui_imports, component_imports);
48
+
49
+ result.push(
50
+ 'export ' +
51
+ (is_directory ? '' : 'default ') +
52
+ expression
53
+ );
54
+ }
55
+
56
+ // write component_imports to the top of the file
57
+ for (const [name] of all_parsed) {
58
+ component_imports.delete(name);
59
+ }
60
+ if (component_imports.size > 0) {
61
+ result.unshift(`import {${
62
+ list_generate([...component_imports], 0)
63
+ }} from ${JSON.stringify(options.components_name)};`);
64
+ }
65
+
66
+ // write lui_imports to the top of the file
67
+ result.unshift(`import {${
68
+ list_generate([...lui_imports], 0)
69
+ }} from ${JSON.stringify(options.lui_name)};`);
70
+
71
+ result.unshift('// generated by lui-templates ' + version);
72
+
73
+ return result.join('\n\n') + '\n';
74
+ }
package/src/parser.js ADDED
@@ -0,0 +1,57 @@
1
+ import fs from 'fs/promises';
2
+
3
+ import {name_format} from './generator.js';
4
+
5
+ const parsers = new Map();
6
+
7
+ export async function parse(path) {
8
+ const src_promise = fs.readFile(path, 'utf8');
9
+
10
+ let name = path.split('/').pop().split('.');
11
+ const extension = name.pop();
12
+ name = name.join('.');
13
+
14
+ let parser = parsers.get(extension);
15
+ if (!parser) {
16
+ try {
17
+ parser = (await import(`./parsers/${extension}.js`)).default;
18
+ } catch (e) {
19
+ throw new Error(`No parser found for extension: ${extension}`);
20
+ }
21
+
22
+ parsers.set(extension, parser);
23
+ }
24
+
25
+ return [
26
+ name_format(name),
27
+ await parser(await src_promise, path),
28
+ ];
29
+ }
30
+
31
+ const html_attr_to_dom_map = new Map([
32
+ ['class', 'className'],
33
+ ['for', 'htmlFor'],
34
+ ['tabindex', 'tabIndex'],
35
+ ['readonly', 'readOnly'],
36
+ ['maxlength', 'maxLength'],
37
+ ['cellspacing', 'cellSpacing'],
38
+ ['cellpadding', 'cellPadding'],
39
+ ['rowspan', 'rowSpan'],
40
+ ['colspan', 'colSpan'],
41
+ ['usemap', 'useMap'],
42
+ ['frameborder', 'frameBorder'],
43
+ ['contenteditable', 'contentEditable'],
44
+ ]);
45
+ export function html_attr_to_dom(attr) {
46
+ attr = attr.toLowerCase();
47
+ return html_attr_to_dom_map.get(attr) || attr;
48
+ }
49
+
50
+ const html_whitespaces = ' \n\r\t\f\v'.split('');
51
+ export const html_is_whitespace = char => html_whitespaces.includes(char);
52
+
53
+ const html_self_closing = 'img,input,br,hr'.split(',');
54
+ export const html_is_self_closing = tag => html_self_closing.includes(tag);
55
+
56
+ const html_boolean_attrs = new Set('disabled,checked,selected,readonly,required,autofocus,autoplay,controls,loop,muted,open,hidden,multiple,defer,async,novalidate,formnovalidate'.split(','));
57
+ export const html_is_boolean_attr = attr => html_boolean_attrs.has(attr.toLowerCase());
@@ -0,0 +1,9 @@
1
+ export default async function parse_json(src, path) {
2
+ const parsed = JSON.parse(src);
3
+ // that was simple, wasn't it? oh wait, we need to annoy people by enforcing a schema
4
+ if (parsed.$schema !== 'https://l3p3.de/shr/schema/lui-templates.intermediary.json') {
5
+ throw new Error(`Invalid schema in file: ${path}`);
6
+ }
7
+ // TODO validate the schema? nah... later, maybe...
8
+ return parsed;
9
+ }