structured-fw 0.7.2
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/Config.ts +47 -0
- package/LICENSE +21 -0
- package/README.md +332 -0
- package/app/Types.ts +1 -0
- package/app/models/README.md +9 -0
- package/app/routes/README.md +19 -0
- package/app/views/README.md +1 -0
- package/app/views/layout.html +1 -0
- package/bin/structured +114 -0
- package/build/Config.d.ts +2 -0
- package/build/Config.js +31 -0
- package/build/app/Types.d.ts +1 -0
- package/build/app/Types.js +1 -0
- package/build/app/models/Users.d.ts +0 -0
- package/build/app/models/Users.js +1 -0
- package/build/app/routes/Auth.d.ts +0 -0
- package/build/app/routes/Auth.js +1 -0
- package/build/app/routes/Test.d.ts +2 -0
- package/build/app/routes/Test.js +101 -0
- package/build/app/routes/Todo.d.ts +0 -0
- package/build/app/routes/Todo.js +1 -0
- package/build/app/routes/Upload.d.ts +0 -0
- package/build/app/routes/Upload.js +1 -0
- package/build/app/routes/Validation.d.ts +2 -0
- package/build/app/routes/Validation.js +34 -0
- package/build/app/views/components/ClientImport/ClientImport.client.d.ts +2 -0
- package/build/app/views/components/ClientImport/ClientImport.client.js +4 -0
- package/build/app/views/components/ClientImport/Export.d.ts +1 -0
- package/build/app/views/components/ClientImport/Export.js +1 -0
- package/build/app/views/components/Conditionals/Conditionals.client.d.ts +2 -0
- package/build/app/views/components/Conditionals/Conditionals.client.js +43 -0
- package/build/app/views/components/FormTest/FormTestNested/FormTestNested.d.ts +8 -0
- package/build/app/views/components/FormTest/FormTestNested/FormTestNested.js +7 -0
- package/build/app/views/components/ModelsTest/ModelsTest.client.d.ts +2 -0
- package/build/app/views/components/ModelsTest/ModelsTest.client.js +5 -0
- package/build/app/views/components/MultipartForm/MultipartForm.client.d.ts +0 -0
- package/build/app/views/components/MultipartForm/MultipartForm.client.js +1 -0
- package/build/app/views/components/PassObject/PassObject.d.ts +10 -0
- package/build/app/views/components/PassObject/PassObject.js +10 -0
- package/build/app/views/components/PassObject/ReceiveObj/ReceiveObj.d.ts +6 -0
- package/build/app/views/components/PassObject/ReceiveObj/ReceiveObj.js +6 -0
- package/build/app/views/components/RedrawAbort/RedrawAbort.client.d.ts +2 -0
- package/build/app/views/components/RedrawAbort/RedrawAbort.client.js +6 -0
- package/build/app/views/components/RedrawAbort/RedrawAbort.d.ts +8 -0
- package/build/app/views/components/RedrawAbort/RedrawAbort.js +8 -0
- package/build/app/views/components/ServerSideContext/ServerSideContext.d.ts +7 -0
- package/build/app/views/components/ServerSideContext/ServerSideContext.js +10 -0
- package/build/assets/ts/Export.d.ts +1 -0
- package/build/assets/ts/Export.js +1 -0
- package/build/index.d.ts +1 -0
- package/build/index.js +3 -0
- package/build/system/Helpers.d.ts +3 -0
- package/build/system/Helpers.js +72 -0
- package/build/system/Symbols.d.ts +3 -0
- package/build/system/Symbols.js +3 -0
- package/build/system/Types.d.ts +171 -0
- package/build/system/Types.js +1 -0
- package/build/system/Util.d.ts +20 -0
- package/build/system/Util.js +336 -0
- package/build/system/client/App.d.ts +7 -0
- package/build/system/client/App.js +8 -0
- package/build/system/client/Client.d.ts +6 -0
- package/build/system/client/Client.js +9 -0
- package/build/system/client/ClientComponent.d.ts +68 -0
- package/build/system/client/ClientComponent.js +734 -0
- package/build/system/client/DataStore.d.ts +22 -0
- package/build/system/client/DataStore.js +64 -0
- package/build/system/client/DataStoreView.d.ts +19 -0
- package/build/system/client/DataStoreView.js +56 -0
- package/build/system/client/EventEmitter.d.ts +7 -0
- package/build/system/client/EventEmitter.js +31 -0
- package/build/system/client/Net.d.ts +13 -0
- package/build/system/client/Net.js +39 -0
- package/build/system/client/NetRequest.d.ts +13 -0
- package/build/system/client/NetRequest.js +45 -0
- package/build/system/server/Application.d.ts +31 -0
- package/build/system/server/Application.js +171 -0
- package/build/system/server/Component.d.ts +27 -0
- package/build/system/server/Component.js +249 -0
- package/build/system/server/Components.d.ts +12 -0
- package/build/system/server/Components.js +77 -0
- package/build/system/server/Cookies.d.ts +6 -0
- package/build/system/server/Cookies.js +19 -0
- package/build/system/server/Document.d.ts +24 -0
- package/build/system/server/Document.js +107 -0
- package/build/system/server/DocumentHead.d.ts +32 -0
- package/build/system/server/DocumentHead.js +118 -0
- package/build/system/server/FormValidation.d.ts +16 -0
- package/build/system/server/FormValidation.js +197 -0
- package/build/system/server/Handlebars.d.ts +11 -0
- package/build/system/server/Handlebars.js +34 -0
- package/build/system/server/Request.d.ts +21 -0
- package/build/system/server/Request.js +356 -0
- package/build/system/server/Session.d.ts +23 -0
- package/build/system/server/Session.js +114 -0
- package/build/system/server/dom/DOMFragment.d.ts +4 -0
- package/build/system/server/dom/DOMFragment.js +6 -0
- package/build/system/server/dom/DOMNode.d.ts +31 -0
- package/build/system/server/dom/DOMNode.js +110 -0
- package/build/system/server/dom/HTMLParser.d.ts +21 -0
- package/build/system/server/dom/HTMLParser.js +204 -0
- package/index.ts +4 -0
- package/package.json +31 -0
- package/system/Helpers.ts +97 -0
- package/system/Symbols.ts +6 -0
- package/system/Types.ts +234 -0
- package/system/Util.ts +488 -0
- package/system/client/App.ts +11 -0
- package/system/client/Client.ts +9 -0
- package/system/client/ClientComponent.ts +1117 -0
- package/system/client/DataStore.ts +101 -0
- package/system/client/DataStoreView.ts +82 -0
- package/system/client/EventEmitter.ts +38 -0
- package/system/client/Net.ts +58 -0
- package/system/client/NetRequest.ts +64 -0
- package/system/server/Application.ts +230 -0
- package/system/server/Component.ts +404 -0
- package/system/server/Components.ts +111 -0
- package/system/server/Cookies.ts +29 -0
- package/system/server/Document.ts +163 -0
- package/system/server/DocumentHead.ts +150 -0
- package/system/server/FormValidation.ts +231 -0
- package/system/server/Handlebars.ts +51 -0
- package/system/server/Request.ts +497 -0
- package/system/server/Session.ts +151 -0
- package/system/server/dom/DOMFragment.ts +7 -0
- package/system/server/dom/DOMNode.ts +140 -0
- package/system/server/dom/HTMLParser.ts +238 -0
- package/tsconfig.json +35 -0
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
import { HTMLParser } from "./HTMLParser.js";
|
|
2
|
+
|
|
3
|
+
type DOMNodeAttribute = { name: string, value: string | true };
|
|
4
|
+
|
|
5
|
+
type JSONNode = {
|
|
6
|
+
name: string,
|
|
7
|
+
children: Array<JSONNode>,
|
|
8
|
+
attributes: Record<string, DOMNodeAttribute>,
|
|
9
|
+
strings: Array<string>
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export const selfClosingTags: ReadonlyArray<string> = ['br', 'hr', 'input', 'img', 'link', 'meta', 'source', 'embed', 'path', 'area'];
|
|
13
|
+
|
|
14
|
+
export class DOMNode {
|
|
15
|
+
|
|
16
|
+
tagName: string;
|
|
17
|
+
|
|
18
|
+
parentNode: DOMNode | null = null;
|
|
19
|
+
children: Array<DOMNode | string> = [];
|
|
20
|
+
|
|
21
|
+
attributes: Array<DOMNodeAttribute> = []
|
|
22
|
+
attributeMap: Record<string, DOMNodeAttribute> = {}
|
|
23
|
+
|
|
24
|
+
style: Partial<CSSStyleDeclaration> = {}
|
|
25
|
+
|
|
26
|
+
selfClosing: boolean;
|
|
27
|
+
|
|
28
|
+
constructor(tagName: string) {
|
|
29
|
+
this.tagName = tagName;
|
|
30
|
+
this.selfClosing = selfClosingTags.includes(tagName);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
appendChild(node: DOMNode | string): void {
|
|
34
|
+
if (typeof node !== 'string') {
|
|
35
|
+
node.parentNode = this;
|
|
36
|
+
}
|
|
37
|
+
this.children.push(node);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
setAttribute(attributeName: string, attributeValue: string | true): void {
|
|
41
|
+
const attributeExisting = this.attributeMap[attributeName];
|
|
42
|
+
|
|
43
|
+
if (! attributeExisting) {
|
|
44
|
+
const attribute = {
|
|
45
|
+
name: attributeName,
|
|
46
|
+
value: attributeValue
|
|
47
|
+
}
|
|
48
|
+
this.attributeMap[attributeName] = attribute;
|
|
49
|
+
this.attributes.push(attribute);
|
|
50
|
+
} else {
|
|
51
|
+
attributeExisting.value = attributeValue;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
hasAttribute(attributeName: string): boolean {
|
|
56
|
+
return attributeName in this.attributeMap;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
queryByTagName(...tagNames: Array<string>): Array<DOMNode> {
|
|
60
|
+
let nodes: Array<DOMNode> = [];
|
|
61
|
+
|
|
62
|
+
for (let i = 0; i < this.children.length; i++) {
|
|
63
|
+
const child = this.children[i];
|
|
64
|
+
if (typeof child === 'string') {continue;}
|
|
65
|
+
if (tagNames.includes(child.tagName)) {
|
|
66
|
+
nodes.push(child);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
nodes = nodes.concat(child.queryByTagName(...tagNames));
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
return nodes;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
queryByHasAttribute(...attributeNames: Array<string>): Array<DOMNode> {
|
|
76
|
+
let nodes: Array<DOMNode> = [];
|
|
77
|
+
|
|
78
|
+
for (let i = 0; i < this.children.length; i++) {
|
|
79
|
+
const child = this.children[i];
|
|
80
|
+
if (typeof child === 'string') {continue;}
|
|
81
|
+
if (attributeNames.some((attributeName) => {
|
|
82
|
+
return child.hasAttribute(attributeName)
|
|
83
|
+
})) {
|
|
84
|
+
nodes.push(child);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
nodes = nodes.concat(child.queryByHasAttribute(...attributeNames));
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
return nodes;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
get innerHTML(): string {
|
|
94
|
+
return this.children.reduce((html, child) => {
|
|
95
|
+
if (typeof child === 'string') {
|
|
96
|
+
return html += child;
|
|
97
|
+
} else {
|
|
98
|
+
return html += child.outerHTML;
|
|
99
|
+
}
|
|
100
|
+
}, '') as string;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
set innerHTML(html: string) {
|
|
104
|
+
const fragment = new HTMLParser(html).dom();
|
|
105
|
+
this.children = fragment.children;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
get outerHTML(): string {
|
|
109
|
+
const attributes = this.attributes.reduce((attributes, attribute) => {
|
|
110
|
+
attributes += ` ${attribute.name}${attribute.value === true ? '' : `="${attribute.value}"`}`;
|
|
111
|
+
return attributes;
|
|
112
|
+
}, '');
|
|
113
|
+
|
|
114
|
+
const style = Object.keys(this.style).reduce((style, styleName) => {
|
|
115
|
+
const styleValue = this.style[styleName as keyof CSSStyleDeclaration];
|
|
116
|
+
if (styleValue?.toString().trim().length === 0) {return style};
|
|
117
|
+
style += ` ${styleName}: ${styleValue};`;
|
|
118
|
+
return style;
|
|
119
|
+
}, '');
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
return `<${this.tagName}${attributes}${style.trim().length > 0 ? ` style="${style}"` : ''}>${this.selfClosing ? '' : `${this.innerHTML}</${this.tagName}>`}`;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
toObject():JSONNode {
|
|
126
|
+
return {
|
|
127
|
+
name: this.tagName,
|
|
128
|
+
children: this.children.filter((child) => {
|
|
129
|
+
return typeof child !== 'string';
|
|
130
|
+
}).map((child) => {
|
|
131
|
+
return child.toObject()
|
|
132
|
+
}),
|
|
133
|
+
attributes: this.attributeMap,
|
|
134
|
+
strings: this.children.filter((child) => {
|
|
135
|
+
return typeof child === 'string';
|
|
136
|
+
})
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
}
|
|
@@ -0,0 +1,238 @@
|
|
|
1
|
+
import { DOMFragment } from "./DOMFragment.js";
|
|
2
|
+
import { DOMNode } from "./DOMNode.js";
|
|
3
|
+
|
|
4
|
+
export class HTMLParser {
|
|
5
|
+
|
|
6
|
+
private readonly html: string;
|
|
7
|
+
|
|
8
|
+
private offset: number = 0;
|
|
9
|
+
private context: DOMFragment | DOMNode;
|
|
10
|
+
private state: 'idle' | 'tagStart' | 'tagOpen' | 'tagClose' | 'attributeName' | 'attributeValueStart' | 'attributeValue' | 'attributeEnd' | 'text' = 'idle';
|
|
11
|
+
|
|
12
|
+
private tokenCurrent: string = '';
|
|
13
|
+
|
|
14
|
+
private fragment: DOMFragment = new DOMFragment();
|
|
15
|
+
|
|
16
|
+
private attributeOpenQuote: '"' | "'" = '"';
|
|
17
|
+
private attributeNameCurrent: string = '';
|
|
18
|
+
private attributeContext: DOMNode | null = null;
|
|
19
|
+
|
|
20
|
+
constructor(html: string) {
|
|
21
|
+
this.html = html;
|
|
22
|
+
this.context = this.fragment;
|
|
23
|
+
while (this.parse()) {
|
|
24
|
+
// console.log({ char: this.char(), state: this.state, context: this.context.tagName });
|
|
25
|
+
this.offset++;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
private char(): string {
|
|
30
|
+
return this.html.charAt(this.offset);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
private lastChar(): boolean {
|
|
34
|
+
return this.offset === this.html.length - 1;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
public parse(): boolean {
|
|
38
|
+
if (this.offset >= this.html.length) {
|
|
39
|
+
// done
|
|
40
|
+
return false;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
const char = this.char();
|
|
44
|
+
const charCode = char.charCodeAt(0);
|
|
45
|
+
|
|
46
|
+
if (this.state === 'idle') {
|
|
47
|
+
if (char === ' ') {return true;}
|
|
48
|
+
if (char === '<') {
|
|
49
|
+
this.state = 'tagStart';
|
|
50
|
+
this.tokenCurrent = '';
|
|
51
|
+
return true;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// text
|
|
55
|
+
this.state = 'text';
|
|
56
|
+
this.tokenCurrent = char;
|
|
57
|
+
|
|
58
|
+
} else if (this.state === 'tagStart') {
|
|
59
|
+
if (char === '/') {
|
|
60
|
+
this.state = 'tagClose';
|
|
61
|
+
return true;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
if (this.isLetter(charCode)) {
|
|
65
|
+
this.state = 'tagOpen';
|
|
66
|
+
this.tokenCurrent = char;
|
|
67
|
+
return true;
|
|
68
|
+
}
|
|
69
|
+
} else if (this.state === 'tagOpen') {
|
|
70
|
+
// this state means we found "<" previously and we expect to find the tag name
|
|
71
|
+
|
|
72
|
+
if (char === '\n') {
|
|
73
|
+
return true;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
if (char === '/') {
|
|
77
|
+
if (this.tokenCurrent.length === 0) {
|
|
78
|
+
throw this.error(`Unexpected tag closing sequence "</", expected opening tag`);
|
|
79
|
+
}
|
|
80
|
+
// ignore this one, it's a self closing tag, but we will expect to find ">" anyway
|
|
81
|
+
return true;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
if (char === '>') {
|
|
85
|
+
if (this.tokenCurrent.length === 0) {
|
|
86
|
+
throw this.error(`Found an empty HTML tag <>`);
|
|
87
|
+
}
|
|
88
|
+
// opening tag end, create node and switch context to new node
|
|
89
|
+
const node = new DOMNode(this.tokenCurrent);
|
|
90
|
+
this.context.appendChild(node);
|
|
91
|
+
this.state = 'idle';
|
|
92
|
+
this.tokenCurrent = '';
|
|
93
|
+
if (! node.selfClosing) {
|
|
94
|
+
this.context = node;
|
|
95
|
+
}
|
|
96
|
+
this.attributeContext = node;
|
|
97
|
+
return true;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
if (char === ' ') {
|
|
101
|
+
if (this.tokenCurrent.length === 0) {
|
|
102
|
+
return true;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
// encountered space after opening tag name, could be a start of attribute name
|
|
106
|
+
this.state = 'attributeName';
|
|
107
|
+
const node = new DOMNode(this.tokenCurrent);
|
|
108
|
+
this.context.appendChild(node);
|
|
109
|
+
this.tokenCurrent = '';
|
|
110
|
+
if (! node.selfClosing) {
|
|
111
|
+
this.context = node;
|
|
112
|
+
}
|
|
113
|
+
this.attributeContext = node;
|
|
114
|
+
return true;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
if (char !== '_' && ! this.isLetter(charCode) && (this.tokenCurrent.length > 0 && ! this.isNumber(charCode))) {
|
|
118
|
+
throw this.error(`Expected a-Z after HTML opening tag`);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
this.tokenCurrent += char;
|
|
122
|
+
return true;
|
|
123
|
+
} else if(this.state === 'tagClose') {
|
|
124
|
+
if (char === '/') {
|
|
125
|
+
// slash before closing tag eg. <input name="..." />
|
|
126
|
+
return true;
|
|
127
|
+
}
|
|
128
|
+
if (char === '>') {
|
|
129
|
+
if (this.tokenCurrent !== this.context.tagName) {
|
|
130
|
+
throw this.error(`Found closing tag ${this.tokenCurrent}, expected ${this.context.tagName}`);
|
|
131
|
+
}
|
|
132
|
+
// tag closed, switch context to parent of the current context
|
|
133
|
+
this.context = this.context.parentNode || this.fragment;
|
|
134
|
+
this.state = 'idle';
|
|
135
|
+
}
|
|
136
|
+
this.tokenCurrent += char;
|
|
137
|
+
} else if (this.state === 'text') {
|
|
138
|
+
if (char === '<') {
|
|
139
|
+
// end text
|
|
140
|
+
this.state = 'tagStart';
|
|
141
|
+
this.context.appendChild(this.tokenCurrent);
|
|
142
|
+
this.tokenCurrent = '';
|
|
143
|
+
return true;
|
|
144
|
+
}
|
|
145
|
+
this.tokenCurrent += char;
|
|
146
|
+
|
|
147
|
+
if (this.lastChar() && this.tokenCurrent.length > 0) {
|
|
148
|
+
// text within node is handled when node closing tag is found
|
|
149
|
+
// this handles text that is a direct child of the fragment
|
|
150
|
+
this.context.appendChild(this.tokenCurrent);
|
|
151
|
+
}
|
|
152
|
+
} else if (this.state === 'attributeName') {
|
|
153
|
+
const boundsChar = char === ' ' || char === '\n' || char === '\t';
|
|
154
|
+
if (boundsChar || char === '=' || char === '>') {
|
|
155
|
+
// end of attribute name
|
|
156
|
+
if (char === '=') {
|
|
157
|
+
this.state = 'attributeValueStart';
|
|
158
|
+
} else if (char === '>') {
|
|
159
|
+
this.state = 'idle';
|
|
160
|
+
}
|
|
161
|
+
if (this.tokenCurrent.length > 0) {
|
|
162
|
+
if (this.attributeContext !== null && this.tokenCurrent.trim().length > 0) {
|
|
163
|
+
this.attributeContext.setAttribute(this.tokenCurrent, true);
|
|
164
|
+
}
|
|
165
|
+
this.attributeNameCurrent = this.tokenCurrent;
|
|
166
|
+
this.tokenCurrent = '';
|
|
167
|
+
return true;
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
if (! boundsChar) {
|
|
172
|
+
this.tokenCurrent += char;
|
|
173
|
+
}
|
|
174
|
+
} else if (this.state === 'attributeValueStart') {
|
|
175
|
+
if (char === '"' || char === "'") {
|
|
176
|
+
this.state = 'attributeValue';
|
|
177
|
+
this.attributeOpenQuote = char;
|
|
178
|
+
return true;
|
|
179
|
+
}
|
|
180
|
+
} else if (this.state === 'attributeValue') {
|
|
181
|
+
|
|
182
|
+
if (char === this.attributeOpenQuote) {
|
|
183
|
+
// attribute value ended
|
|
184
|
+
if (this.attributeContext) {
|
|
185
|
+
this.attributeContext.setAttribute(this.attributeNameCurrent, this.tokenCurrent);
|
|
186
|
+
}
|
|
187
|
+
this.tokenCurrent = '';
|
|
188
|
+
this.attributeNameCurrent = '';
|
|
189
|
+
this.state = 'attributeEnd';
|
|
190
|
+
return true;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
this.tokenCurrent += char;
|
|
194
|
+
} else if (this.state === 'attributeEnd') {
|
|
195
|
+
if (char === '>') {
|
|
196
|
+
this.state = 'idle';
|
|
197
|
+
return true;
|
|
198
|
+
} if (char === ' ' || char === '\n') {
|
|
199
|
+
this.state = 'attributeName';
|
|
200
|
+
return true;
|
|
201
|
+
} else if (char === '/') {
|
|
202
|
+
return true;
|
|
203
|
+
} else {
|
|
204
|
+
throw this.error(`Unexpected character ${char} after attribute value`);
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
return true;
|
|
209
|
+
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
// returns current line
|
|
213
|
+
private line(): number {
|
|
214
|
+
return this.html.substring(0, this.offset).split('\n').length;
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
private isLetter(charCode: number): boolean {
|
|
218
|
+
const isLowerCase = charCode > 96 && charCode < 123;
|
|
219
|
+
if (isLowerCase) {return true;}
|
|
220
|
+
const isUpperCase = charCode > 64 && charCode < 91;
|
|
221
|
+
if (isUpperCase) {return true;}
|
|
222
|
+
|
|
223
|
+
return false;
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
private isNumber(charCode: number): boolean {
|
|
227
|
+
return charCode > 47 && charCode < 58;
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
public dom(): DOMFragment {
|
|
231
|
+
return this.fragment;
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
private error(message: string): Error {
|
|
235
|
+
return new Error(`HTMLParser: ${message}\nLine ${this.line()}\nHTML:\n${this.html}\n`);
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
}
|
package/tsconfig.json
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"noImplicitAny": true,
|
|
4
|
+
"strictNullChecks": true,
|
|
5
|
+
"strictPropertyInitialization": true,
|
|
6
|
+
"strictBindCallApply": true,
|
|
7
|
+
"noUnusedLocals": true,
|
|
8
|
+
"moduleResolution" : "Node",
|
|
9
|
+
"outDir": "./build",
|
|
10
|
+
"module": "ES2020",
|
|
11
|
+
"target": "ES2021",
|
|
12
|
+
"alwaysStrict": true,
|
|
13
|
+
"allowSyntheticDefaultImports": true, // albe to do import { default as varname } from 'module'
|
|
14
|
+
"declaration": true,
|
|
15
|
+
"isolatedDeclarations": true,
|
|
16
|
+
"noImplicitReturns": true,
|
|
17
|
+
"preserveSymlinks": true,
|
|
18
|
+
"removeComments": true,
|
|
19
|
+
"baseUrl": ".",
|
|
20
|
+
"rootDir": ".",
|
|
21
|
+
"paths": {
|
|
22
|
+
"/assets/ts/*": ["./assets/ts/*"],
|
|
23
|
+
"/assets/client-js/*": ["./system/*"],
|
|
24
|
+
"@structured/*": [
|
|
25
|
+
"./node_modules/structured/build/system/server/*",
|
|
26
|
+
"./node_modules/structured/build/system/client/*",
|
|
27
|
+
"./node_modules/structured/build/system/*",
|
|
28
|
+
"./system/server/*",
|
|
29
|
+
"./system/client/*",
|
|
30
|
+
"./system/*",
|
|
31
|
+
]
|
|
32
|
+
}
|
|
33
|
+
},
|
|
34
|
+
"include": ["./system/**/*", "./app/**/*", "./assets/ts/**/*", "index.ts"]
|
|
35
|
+
}
|