structured-fw 0.9.8 → 0.9.9
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/build/system/Util.d.ts +1 -0
- package/build/system/Util.js +4 -0
- package/build/system/server/Component.js +1 -1
- package/build/system/server/Components.js +5 -1
- package/build/system/server/Document.d.ts +1 -1
- package/build/system/server/Document.js +8 -24
- package/build/system/server/dom/HTMLParser.d.ts +1 -0
- package/build/system/server/dom/HTMLParser.js +9 -1
- package/package.json +8 -3
package/build/system/Util.d.ts
CHANGED
|
@@ -18,3 +18,4 @@ export declare function attributeValueEscape(str: string): string;
|
|
|
18
18
|
export declare function isObject(item: any): boolean;
|
|
19
19
|
export declare function equalDeep(a: LooseObject, b: LooseObject): boolean;
|
|
20
20
|
export declare function mergeDeep(target: any, ...sources: Array<any>): LooseObject;
|
|
21
|
+
export declare function stripBOM(str: string): string;
|
package/build/system/Util.js
CHANGED
|
@@ -59,7 +59,7 @@ export class Component extends EventEmitter {
|
|
|
59
59
|
}
|
|
60
60
|
this.dom.setAttribute(`data-${this.document.application.config.components.componentNameAttribute}`, this.name);
|
|
61
61
|
if (typeof this.attributes.componentId !== 'string') {
|
|
62
|
-
this.id = this.document.allocateId(
|
|
62
|
+
this.id = this.document.allocateId();
|
|
63
63
|
this.dom.setAttribute('data-component-id', this.id);
|
|
64
64
|
}
|
|
65
65
|
else {
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { existsSync, readdirSync, readFileSync, statSync } from 'node:fs';
|
|
2
2
|
import * as path from 'node:path';
|
|
3
|
+
import { stripBOM } from '../Util.js';
|
|
3
4
|
export class Components {
|
|
4
5
|
constructor(app) {
|
|
5
6
|
this.components = {};
|
|
@@ -72,7 +73,10 @@ export class Components {
|
|
|
72
73
|
return this.components[name.toUpperCase()] || null;
|
|
73
74
|
}
|
|
74
75
|
loadHTML(path) {
|
|
75
|
-
|
|
76
|
+
const html = readFileSync(path, {
|
|
77
|
+
encoding: 'utf-8'
|
|
78
|
+
}).toString();
|
|
79
|
+
return this.stripComments(stripBOM(html).replace(/\r/g, ''));
|
|
76
80
|
}
|
|
77
81
|
stripComments(html) {
|
|
78
82
|
return html.replaceAll(/<!--(?!-?>)(?!.*--!>)(?!.*<!--(?!>)).*?(?<!<!-)-->/g, '');
|
|
@@ -20,7 +20,7 @@ export declare class Document extends Component<{
|
|
|
20
20
|
initInitializers(): Record<string, string>;
|
|
21
21
|
private initClientConfig;
|
|
22
22
|
toString(): string;
|
|
23
|
-
allocateId(
|
|
23
|
+
allocateId(): string;
|
|
24
24
|
loadView(pathRelative: string, data?: LooseObject): Promise<boolean>;
|
|
25
25
|
loadComponent(componentName: string, data?: LooseObject): Promise<void>;
|
|
26
26
|
}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { Md5 } from 'ts-md5';
|
|
2
1
|
import { DocumentHead } from './DocumentHead.js';
|
|
3
2
|
import { Component } from './Component.js';
|
|
4
|
-
import { attributeValueToString,
|
|
3
|
+
import { attributeValueToString, stripBOM } from '../Util.js';
|
|
5
4
|
import path from 'node:path';
|
|
6
5
|
import { existsSync, readFileSync } from 'node:fs';
|
|
6
|
+
import { randomUUID } from 'node:crypto';
|
|
7
7
|
export class Document extends Component {
|
|
8
8
|
constructor(app, title, ctx) {
|
|
9
9
|
super('root');
|
|
@@ -63,26 +63,8 @@ export class Document extends Component {
|
|
|
63
63
|
</body>
|
|
64
64
|
</html>`;
|
|
65
65
|
}
|
|
66
|
-
allocateId(
|
|
67
|
-
|
|
68
|
-
this.componentIds = [];
|
|
69
|
-
}
|
|
70
|
-
let id = Md5.hashStr(`${component.name}:${'id' in component.attributes ? component.attributes.id : `${component.path.join('/')}:${JSON.stringify(component.attributesRaw)}`}`);
|
|
71
|
-
if (this.componentIds.includes(id)) {
|
|
72
|
-
let current = component.parent;
|
|
73
|
-
do {
|
|
74
|
-
if (current === null || current.isRoot) {
|
|
75
|
-
console.error(`Could not define an unique ID for component ${component.name}, path: ${component.path}`);
|
|
76
|
-
id = randomString(16);
|
|
77
|
-
}
|
|
78
|
-
else {
|
|
79
|
-
id += '-' + Md5.hashStr(current.dom.outerHTML);
|
|
80
|
-
}
|
|
81
|
-
current = current?.parent || null;
|
|
82
|
-
} while (this.componentIds.includes(id));
|
|
83
|
-
}
|
|
84
|
-
this.componentIds.push(id);
|
|
85
|
-
return id;
|
|
66
|
+
allocateId() {
|
|
67
|
+
return randomUUID();
|
|
86
68
|
}
|
|
87
69
|
async loadView(pathRelative, data) {
|
|
88
70
|
const viewPath = path.resolve('../' + this.application.config.components.path + '/' + pathRelative + (pathRelative.endsWith('.html') ? '' : '.html'));
|
|
@@ -90,8 +72,10 @@ export class Document extends Component {
|
|
|
90
72
|
console.warn(`Couldn't load document ${this.document.head.title}: ${viewPath}`);
|
|
91
73
|
return false;
|
|
92
74
|
}
|
|
93
|
-
const html = readFileSync(viewPath
|
|
94
|
-
|
|
75
|
+
const html = readFileSync(viewPath, {
|
|
76
|
+
encoding: 'utf-8'
|
|
77
|
+
}).toString();
|
|
78
|
+
await this.init(stripBOM(html).replace(/\r/g, ''), data);
|
|
95
79
|
return true;
|
|
96
80
|
}
|
|
97
81
|
async loadComponent(componentName, data) {
|
|
@@ -181,6 +181,9 @@ export class HTMLParser {
|
|
|
181
181
|
line() {
|
|
182
182
|
return this.html.substring(0, this.offset).split('\n').length;
|
|
183
183
|
}
|
|
184
|
+
lineChar() {
|
|
185
|
+
return this.offset % this.html.split('\n').slice(0, this.line()).length;
|
|
186
|
+
}
|
|
184
187
|
isLetter(charCode) {
|
|
185
188
|
const isLowerCase = charCode > 96 && charCode < 123;
|
|
186
189
|
if (isLowerCase) {
|
|
@@ -199,6 +202,11 @@ export class HTMLParser {
|
|
|
199
202
|
return this.fragment;
|
|
200
203
|
}
|
|
201
204
|
error(message) {
|
|
202
|
-
return new Error(`
|
|
205
|
+
return new Error(`
|
|
206
|
+
HTMLParser: ${message}
|
|
207
|
+
Line ${this.line()}, col ${this.lineChar()}
|
|
208
|
+
Char ${this.char()}, code ${this.char().charCodeAt(0)}
|
|
209
|
+
HTML:
|
|
210
|
+
${this.html}`);
|
|
203
211
|
}
|
|
204
212
|
}
|
package/package.json
CHANGED
|
@@ -2,7 +2,12 @@
|
|
|
2
2
|
"name": "structured-fw",
|
|
3
3
|
"displayName": "Structured framework",
|
|
4
4
|
"description": "Production-tested Node.js framework for creating performant server-side rendered web apps and APIs, with a sane amount of client side abstraction.",
|
|
5
|
-
"keywords": [
|
|
5
|
+
"keywords": [
|
|
6
|
+
"typescript",
|
|
7
|
+
"framework",
|
|
8
|
+
"ssr",
|
|
9
|
+
"component"
|
|
10
|
+
],
|
|
6
11
|
"repository": {
|
|
7
12
|
"type": "git",
|
|
8
13
|
"url": "git+https://github.com/julijan/structured"
|
|
@@ -14,7 +19,7 @@
|
|
|
14
19
|
"license": "MIT",
|
|
15
20
|
"type": "module",
|
|
16
21
|
"main": "build/index",
|
|
17
|
-
"version": "0.9.
|
|
22
|
+
"version": "0.9.9",
|
|
18
23
|
"scripts": {
|
|
19
24
|
"develop": "tsc --watch",
|
|
20
25
|
"startDev": "cd build && nodemon --watch '../app/**/*' --watch '../build/**/*' -e js,html,css index.js",
|
|
@@ -42,7 +47,7 @@
|
|
|
42
47
|
"README.md",
|
|
43
48
|
"LICENSE"
|
|
44
49
|
],
|
|
45
|
-
"exports"
|
|
50
|
+
"exports": {
|
|
46
51
|
"./Types": "./build/system/Types.js",
|
|
47
52
|
"./Symbols": "./build/system/Symbols.js",
|
|
48
53
|
"./Util": "./build/system/Util.js",
|