vaderjs 1.2.6 → 1.2.8
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/.vscode/vaderjs.autosense.json +1 -1
- package/index.js +1 -1
- package/package.json +1 -1
- package/readme.md +32 -7
- package/snippet-gen/vader/.vscode/launch.json +17 -0
- package/snippet-gen/vader/.vscodeignore +4 -0
- package/snippet-gen/vader/CHANGELOG.md +9 -0
- package/snippet-gen/vader/README.md +26 -0
- package/snippet-gen/vader/extension/extension.js +70 -0
- package/snippet-gen/vader/extension/html_completion/html_completion.js +91 -0
- package/snippet-gen/vader/extension/html_completion/html_completion.json +1891 -0
- package/snippet-gen/vader/icons/logo.png +0 -0
- package/snippet-gen/vader/language-configuration.json +128 -0
- package/snippet-gen/vader/package.json +47 -0
- package/snippet-gen/vader/snippets/vader.json +13 -0
- package/snippet-gen/vader/syntaxes/vader.tmLanguage.json +2644 -0
- package/vader.js +253 -152
- package/worker.js +106 -0
package/vader.js
CHANGED
|
@@ -6,7 +6,8 @@ let states = {};
|
|
|
6
6
|
* @description Allows you to convert markdown to html
|
|
7
7
|
*/
|
|
8
8
|
function markdown(content) {
|
|
9
|
-
const lines = content.split('\n');
|
|
9
|
+
const lines = content.split('\n').filter((line) => line !== '').map((line) => line.trim());
|
|
10
|
+
|
|
10
11
|
let result = '';
|
|
11
12
|
|
|
12
13
|
lines.forEach((line) => {
|
|
@@ -16,7 +17,8 @@ function markdown(content) {
|
|
|
16
17
|
|
|
17
18
|
let link = line.match(/\[(.*?)\]\((.*?)\)/g);
|
|
18
19
|
let ul = line.match(/^\-\s/);
|
|
19
|
-
let ol =
|
|
20
|
+
let ol = line.match(/^\d\.\s/);
|
|
21
|
+
|
|
20
22
|
let li = line.match(/^\s/);
|
|
21
23
|
let hr = line.match(/^\-\-\-\s/);
|
|
22
24
|
let blockquote = line.match(/^\>\s/);
|
|
@@ -25,6 +27,8 @@ function markdown(content) {
|
|
|
25
27
|
|
|
26
28
|
let codeBlock = line.match(/\`\`\`/g);
|
|
27
29
|
let codeBlockEnd = line.match(/\`\`\`/g);
|
|
30
|
+
let code = line.match(/\`(.*?)\`/g);
|
|
31
|
+
|
|
28
32
|
|
|
29
33
|
|
|
30
34
|
if (heading) {
|
|
@@ -35,12 +39,16 @@ function markdown(content) {
|
|
|
35
39
|
}
|
|
36
40
|
if (bold) {
|
|
37
41
|
bold.forEach((b) => {
|
|
38
|
-
line = line.replace(b, `<strong
|
|
42
|
+
line = line.replace(b, `<strong
|
|
43
|
+
className="$vader_markdown_bold"
|
|
44
|
+
>${b.replace(/\*\*/g, "")}</strong>`);
|
|
39
45
|
});
|
|
40
46
|
}
|
|
41
47
|
if (italic) {
|
|
42
48
|
italic.forEach((i) => {
|
|
43
|
-
line = line.replace(i, `<em
|
|
49
|
+
line = line.replace(i, `<em
|
|
50
|
+
className="$vader_markdown_italic"
|
|
51
|
+
>${i.replace(/\*/g, "")}</em>`);
|
|
44
52
|
});
|
|
45
53
|
}
|
|
46
54
|
|
|
@@ -51,26 +59,30 @@ function markdown(content) {
|
|
|
51
59
|
let text = l.match(/\[(.*?)\]/g)[0].replace(/\[|\]/g, "");
|
|
52
60
|
// @ts-ignore
|
|
53
61
|
let href = l.match(/\((.*?)\)/g)[0].replace(/\(|\)/g, "");
|
|
54
|
-
line = line.replace(l, `<a
|
|
62
|
+
line = line.replace(l, `<a
|
|
63
|
+
className="$vader_markdown_link"
|
|
64
|
+
href="${href}">${text}</a>`);
|
|
55
65
|
});
|
|
56
66
|
}
|
|
57
67
|
if (ul) {
|
|
58
68
|
line = line.replace(ul[0], `<li
|
|
59
|
-
|
|
60
|
-
>`);
|
|
69
|
+
className="$vader_markdown_ul"
|
|
70
|
+
style="list-style-type: disc;">`);
|
|
61
71
|
line += `</li>`;
|
|
62
72
|
}
|
|
63
73
|
if (ol) {
|
|
64
|
-
line = line.replace(ol[0], `<li
|
|
65
|
-
|
|
66
|
-
>`);
|
|
74
|
+
line = line.replace(ol[0], `<li
|
|
75
|
+
className="$vader_markdown_ol"
|
|
76
|
+
style="list-style-type: decimal;">`);
|
|
67
77
|
line += `</li>`;
|
|
68
78
|
}
|
|
69
79
|
if (hr) {
|
|
70
80
|
line = line.replace(hr[0], `<hr/>`);
|
|
71
81
|
}
|
|
72
82
|
if (blockquote) {
|
|
73
|
-
line = line.replace(blockquote[0], `<blockquote
|
|
83
|
+
line = line.replace(blockquote[0], `<blockquote
|
|
84
|
+
className="$vader_markdown_blockquote"
|
|
85
|
+
>`);
|
|
74
86
|
line += `</blockquote>`;
|
|
75
87
|
}
|
|
76
88
|
if (image) {
|
|
@@ -80,18 +92,32 @@ function markdown(content) {
|
|
|
80
92
|
// @ts-ignore
|
|
81
93
|
let src = i.match(/\((.*?)\)/g)[0].replace(/\(|\)/g, "");
|
|
82
94
|
i.replace(i, `<img src="${src}" alt="${alt}"/>`);
|
|
83
|
-
line = line.replace(i, `<img
|
|
95
|
+
line = line.replace(i, `<img
|
|
96
|
+
className="$vader_markdown_image"
|
|
97
|
+
src="${src}" alt="${alt}"/>`).replace('!','')
|
|
84
98
|
});
|
|
85
99
|
}
|
|
86
|
-
if(
|
|
87
|
-
line = line.replace(
|
|
88
|
-
|
|
100
|
+
if (li) {
|
|
101
|
+
line = line.replace(li[0], `<li>`);
|
|
102
|
+
line += `</li>`;
|
|
103
|
+
}
|
|
104
|
+
if (codeBlock) {
|
|
105
|
+
line = line.replace(codeBlock[0], `<pre className="$vader_markdown_code_block" ><code>`);
|
|
89
106
|
}
|
|
90
|
-
if(codeBlockEnd){
|
|
91
|
-
line = line.replace(codeBlockEnd[0], `</code>`);
|
|
92
|
-
// remove spaces
|
|
93
|
-
line = line.replace(/^\s+/g, '');
|
|
107
|
+
if (codeBlockEnd) {
|
|
108
|
+
line = line.replace(codeBlockEnd[0], `</code></pre>`);
|
|
94
109
|
}
|
|
110
|
+
|
|
111
|
+
if (code) {
|
|
112
|
+
code.forEach((c) => {
|
|
113
|
+
line = line.replace(c, `<code
|
|
114
|
+
className="$vader_markdown_code"
|
|
115
|
+
style="background-color: #f5f5f5; padding: 5px; border-radius: 5px;
|
|
116
|
+
"
|
|
117
|
+
>${c.replace(/\`/g, "")}</code>`);
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
|
|
95
121
|
|
|
96
122
|
|
|
97
123
|
|
|
@@ -182,6 +208,19 @@ export class Component {
|
|
|
182
208
|
});
|
|
183
209
|
this.snapshots = [];
|
|
184
210
|
|
|
211
|
+
/**
|
|
212
|
+
* @property {Boolean} cfr
|
|
213
|
+
* @description Allows you to compile html code on the fly - client fly rendering
|
|
214
|
+
*
|
|
215
|
+
*/
|
|
216
|
+
this.cfr = false
|
|
217
|
+
/**
|
|
218
|
+
* @property {Boolean} worker
|
|
219
|
+
* @description Allows you to use a web worker to compile html code on the fly - client fly rendering
|
|
220
|
+
|
|
221
|
+
*/
|
|
222
|
+
// @ts-ignore
|
|
223
|
+
this.worker = new Worker(new URL('./worker.js', import.meta.url));
|
|
185
224
|
}
|
|
186
225
|
|
|
187
226
|
/**
|
|
@@ -195,6 +234,7 @@ export class Component {
|
|
|
195
234
|
}
|
|
196
235
|
init() {
|
|
197
236
|
this.registerComponent();
|
|
237
|
+
|
|
198
238
|
}
|
|
199
239
|
|
|
200
240
|
registerComponent() {
|
|
@@ -763,88 +803,11 @@ export class Component {
|
|
|
763
803
|
return /^[a-zA-Z0-9-_]+$/.test(className);
|
|
764
804
|
}
|
|
765
805
|
|
|
766
|
-
/**
|
|
767
|
-
* The `html` method generates and processes HTML content for a component, performing various validations and tasks.
|
|
768
|
-
*
|
|
769
|
-
* @param {String} strings - The HTML content to be processed.
|
|
770
|
-
* @param {...any} args - Dynamic values to be inserted into the template.
|
|
771
|
-
* @returns {string} - The processed HTML content as a string.
|
|
772
|
-
*
|
|
773
|
-
* @throws {SyntaxError} - Throws a `SyntaxError` if image-related attributes are missing or invalid.
|
|
774
|
-
* @throws {Error} - Throws an `Error` if there are issues with class names or relative paths.
|
|
775
|
-
*
|
|
776
|
-
* @example
|
|
777
|
-
* // Example usage within a component:
|
|
778
|
-
* const myComponent = new Component();
|
|
779
|
-
* const htmlContent = myComponent.html`
|
|
780
|
-
* <div>
|
|
781
|
-
* <img src="/images/example.jpg" alt="Example Image" />
|
|
782
|
-
* </div>
|
|
783
|
-
* `;
|
|
784
|
-
* document.body.innerHTML = htmlContent;
|
|
785
|
-
*
|
|
786
|
-
* @remarks
|
|
787
|
-
* The `html` method is a core function used in component rendering. It allows you to define and generate HTML content within your component while enforcing best practices and accessibility standards. The method performs several essential tasks:
|
|
788
|
-
*
|
|
789
|
-
* 1. **Image Validation**: It checks images for the presence of 'alt' attributes and their validity.
|
|
790
|
-
* - Throws a `SyntaxError` if an image is missing the 'alt' attribute.
|
|
791
|
-
* - Throws a `SyntaxError` if the 'alt' attribute is empty.
|
|
792
|
-
* - Checks for an 'aria-hidden' attribute for image elements.
|
|
793
|
-
*
|
|
794
|
-
* 2. **Class Attribute Handling**: It enforces class attribute usage and allows optional configuration via comments.
|
|
795
|
-
* - Throws an `Error` if 'class' attributes are used without permission.
|
|
796
|
-
* - Supports 'className' attributes for class definitions.
|
|
797
|
-
* - Allows or disallows class-related comments based on your configuration.
|
|
798
|
-
*
|
|
799
|
-
* 3. **Relative Path Handling**: It processes relative paths in 'href' and 'src' attributes, ensuring proper routing.
|
|
800
|
-
* - Converts relative 'href' attributes to anchor links with appropriate routing.
|
|
801
|
-
* - Converts relative 'src' attributes to absolute paths with 'public' directories.
|
|
802
|
-
*
|
|
803
|
-
* 4. **Custom Component Attributes**: It supports adding a 'data-component' attribute to the root element.
|
|
804
|
-
* - Ensures that the 'data-component' attribute is present for component identification.
|
|
805
|
-
*
|
|
806
|
-
* 5. **Lifecycle Method Invocation**: It invokes the `componentDidMount` method if called from a 'render' context.
|
|
807
|
-
* - Executes `componentDidMount` to handle component initialization once the DOM is ready.
|
|
808
|
-
*
|
|
809
|
-
* @see {@link Component}
|
|
810
|
-
* @see {@link Component#componentDidMount}
|
|
811
|
-
*/
|
|
812
|
-
|
|
813
|
-
html(strings, ...args) {
|
|
814
|
-
// @ts-ignore
|
|
815
|
-
if (
|
|
816
|
-
// @ts-ignore
|
|
817
|
-
new Error().stack &&
|
|
818
|
-
// @ts-ignore
|
|
819
|
-
new Error().stack.split("\n").length > 0 &&
|
|
820
|
-
// @ts-ignore
|
|
821
|
-
new Error().stack.split("\n")[2] &&
|
|
822
|
-
// @ts-ignore
|
|
823
|
-
new Error().stack.split("\n")[2].includes("render") &&
|
|
824
|
-
!this.componentMounted
|
|
825
|
-
) {
|
|
826
|
-
this.componentMounted = true;
|
|
827
|
-
this.componentDidMount();
|
|
828
|
-
console.log("component mounted");
|
|
829
|
-
}
|
|
830
|
-
|
|
831
|
-
let result = "";
|
|
832
|
-
for (let i = 0; i < strings.length; i++) {
|
|
833
|
-
result += strings[i];
|
|
834
|
-
if (i < args.length) {
|
|
835
|
-
result += args[i];
|
|
836
|
-
}
|
|
837
|
-
}
|
|
838
|
-
|
|
839
|
-
result = new Function("useRef", `return \`${result}\``)(useRef)
|
|
840
806
|
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
"You should wrap your html in a body tag, vader may not grab all html!"
|
|
844
|
-
);
|
|
845
|
-
}
|
|
846
|
-
|
|
807
|
+
parseHTML(result) {
|
|
808
|
+
|
|
847
809
|
const dom = new DOMParser().parseFromString(result, "text/html");
|
|
810
|
+
console.log(dom)
|
|
848
811
|
const elements = dom.documentElement.querySelectorAll("*");
|
|
849
812
|
|
|
850
813
|
elements.forEach((element) => {
|
|
@@ -883,6 +846,7 @@ export class Component {
|
|
|
883
846
|
element.setAttribute("hidden", "true");
|
|
884
847
|
// if window.lcoation.pathname includes a html file remove it and only use the path
|
|
885
848
|
let url = window.location.origin + window.location.pathname.replace(/\/[^\/]*$/, '') + '/public/' + element.getAttribute("src");
|
|
849
|
+
// @ts-ignore
|
|
886
850
|
let image = new Image();
|
|
887
851
|
image.src = url;
|
|
888
852
|
image.onerror = () => {
|
|
@@ -925,27 +889,6 @@ export class Component {
|
|
|
925
889
|
);
|
|
926
890
|
}
|
|
927
891
|
} else if (element.hasAttribute("className")) {
|
|
928
|
-
const isLocalhost = window.location.href.includes("localhost");
|
|
929
|
-
const is127001 = window.location.href.includes("127.0.0.1");
|
|
930
|
-
const ignoreClassComments = document.documentElement.outerHTML
|
|
931
|
-
.trim()
|
|
932
|
-
.includes("<!-- #vader-class-ignore -->");
|
|
933
|
-
const allowClassComments = document.documentElement.outerHTML
|
|
934
|
-
.trim()
|
|
935
|
-
.includes("<!-- #vader-allow_class -->");
|
|
936
|
-
|
|
937
|
-
if (
|
|
938
|
-
// @ts-ignore
|
|
939
|
-
(!this.validateClassName(element.getAttribute("className")) &&
|
|
940
|
-
isLocalhost) ||
|
|
941
|
-
(is127001 && !ignoreClassComments && !allowClassComments)
|
|
942
|
-
) {
|
|
943
|
-
throw new Error(
|
|
944
|
-
`Invalid className ${element.getAttribute(
|
|
945
|
-
"className"
|
|
946
|
-
)}, please use camelCase instead - example: myClass`
|
|
947
|
-
);
|
|
948
|
-
}
|
|
949
892
|
// @ts-ignore
|
|
950
893
|
element.setAttribute("class", element.getAttribute("className"));
|
|
951
894
|
element.removeAttribute("className");
|
|
@@ -982,6 +925,7 @@ export class Component {
|
|
|
982
925
|
}
|
|
983
926
|
break;
|
|
984
927
|
}
|
|
928
|
+
|
|
985
929
|
});
|
|
986
930
|
|
|
987
931
|
result = dom.body.innerHTML;
|
|
@@ -989,12 +933,128 @@ export class Component {
|
|
|
989
933
|
this.Componentcontent = result;
|
|
990
934
|
|
|
991
935
|
if (!result.includes("<div data-component")) {
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
936
|
+
result = `<div data-component="${this.name}">${result}</div>`;
|
|
937
|
+
}
|
|
938
|
+
return markdown(result.replace(/\\n/g, '\n').trim())
|
|
939
|
+
|
|
940
|
+
}
|
|
941
|
+
|
|
942
|
+
/**
|
|
943
|
+
* The `html` method generates and processes HTML content for a component, performing various validations and tasks.
|
|
944
|
+
*
|
|
945
|
+
* @param {String} strings - The HTML content to be processed.
|
|
946
|
+
* @param {...any} args - Dynamic values to be inserted into the template.
|
|
947
|
+
* @returns {string} - The processed HTML content as a string.
|
|
948
|
+
*
|
|
949
|
+
* @throws {SyntaxError} - Throws a `SyntaxError` if image-related attributes are missing or invalid.
|
|
950
|
+
* @throws {Error} - Throws an `Error` if there are issues with class names or relative paths.
|
|
951
|
+
*
|
|
952
|
+
* @example
|
|
953
|
+
* // Example usage within a component:
|
|
954
|
+
* const myComponent = new Component();
|
|
955
|
+
* const htmlContent = myComponent.html`
|
|
956
|
+
* <div>
|
|
957
|
+
* <img src="/images/example.jpg" alt="Example Image" />
|
|
958
|
+
* </div>
|
|
959
|
+
* `;
|
|
960
|
+
* document.body.innerHTML = htmlContent;
|
|
961
|
+
*
|
|
962
|
+
* @remarks
|
|
963
|
+
* The `html` method is a core function used in component rendering. It allows you to define and generate HTML content within your component while enforcing best practices and accessibility standards. The method performs several essential tasks:
|
|
964
|
+
*
|
|
965
|
+
* 1. **Image Validation**: It checks images for the presence of 'alt' attributes and their validity.
|
|
966
|
+
* - Throws a `SyntaxError` if an image is missing the 'alt' attribute.
|
|
967
|
+
* - Throws a `SyntaxError` if the 'alt' attribute is empty.
|
|
968
|
+
* - Checks for an 'aria-hidden' attribute for image elements.
|
|
969
|
+
*
|
|
970
|
+
* 2. **Class Attribute Handling**: It enforces class attribute usage and allows optional configuration via comments.
|
|
971
|
+
* - Throws an `Error` if 'class' attributes are used without permission.
|
|
972
|
+
* - Supports 'className' attributes for class definitions.
|
|
973
|
+
* - Allows or disallows class-related comments based on your configuration.
|
|
974
|
+
*
|
|
975
|
+
* 3. **Relative Path Handling**: It processes relative paths in 'href' and 'src' attributes, ensuring proper routing.
|
|
976
|
+
* - Converts relative 'href' attributes to anchor links with appropriate routing.
|
|
977
|
+
* - Converts relative 'src' attributes to absolute paths with 'public' directories.
|
|
978
|
+
*
|
|
979
|
+
* 4. **Custom Component Attributes**: It supports adding a 'data-component' attribute to the root element.
|
|
980
|
+
* - Ensures that the 'data-component' attribute is present for component identification.
|
|
981
|
+
*
|
|
982
|
+
* 5. **Lifecycle Method Invocation**: It invokes the `componentDidMount` method if called from a 'render' context.
|
|
983
|
+
* - Executes `componentDidMount` to handle component initialization once the DOM is ready.
|
|
984
|
+
*
|
|
985
|
+
* @see {@link Component}
|
|
986
|
+
* @see {@link Component#componentDidMount}
|
|
987
|
+
*/
|
|
988
|
+
|
|
989
|
+
|
|
990
|
+
|
|
991
|
+
html(strings, ...args) {
|
|
992
|
+
// @ts-ignore
|
|
993
|
+
if (
|
|
994
|
+
// @ts-ignore
|
|
995
|
+
new Error().stack &&
|
|
996
|
+
// @ts-ignore
|
|
997
|
+
new Error().stack.split("\n").length > 0 &&
|
|
998
|
+
// @ts-ignore
|
|
999
|
+
new Error().stack.split("\n")[2] &&
|
|
1000
|
+
// @ts-ignore
|
|
1001
|
+
new Error().stack.split("\n")[2].includes("render") &&
|
|
1002
|
+
!this.componentMounted
|
|
1003
|
+
) {
|
|
1004
|
+
this.componentMounted = true;
|
|
1005
|
+
this.componentDidMount();
|
|
995
1006
|
}
|
|
996
1007
|
|
|
997
|
-
|
|
1008
|
+
|
|
1009
|
+
if(this.cfr){
|
|
1010
|
+
|
|
1011
|
+
this.worker.postMessage({strings, args, location: window.location.href, name: this.name})
|
|
1012
|
+
let promise = new Promise((resolve, reject)=>{
|
|
1013
|
+
this.worker.onmessage = (e)=>{
|
|
1014
|
+
if(e.data.error){
|
|
1015
|
+
throw new Error(e.data.error)
|
|
1016
|
+
}
|
|
1017
|
+
|
|
1018
|
+
let d = ""
|
|
1019
|
+
if(new Function("useRef", `return \`${e.data}\``)(useRef).includes('#')){
|
|
1020
|
+
d = markdown(new Function("useRef", `return \`${e.data}\``)(useRef))
|
|
1021
|
+
}else{
|
|
1022
|
+
d = new Function("useRef", `return \`${e.data}\``)(useRef)
|
|
1023
|
+
}
|
|
1024
|
+
|
|
1025
|
+
resolve(d)
|
|
1026
|
+
|
|
1027
|
+
|
|
1028
|
+
|
|
1029
|
+
}
|
|
1030
|
+
this.worker.onerror = (e)=>{
|
|
1031
|
+
reject(e)
|
|
1032
|
+
}
|
|
1033
|
+
})
|
|
1034
|
+
// @ts-ignore
|
|
1035
|
+
return promise;
|
|
1036
|
+
}else{
|
|
1037
|
+
let result = "";
|
|
1038
|
+
for (let i = 0; i < strings.length; i++) {
|
|
1039
|
+
result += strings[i];
|
|
1040
|
+
if (i < args.length) {
|
|
1041
|
+
result += args[i];
|
|
1042
|
+
}
|
|
1043
|
+
}
|
|
1044
|
+
result = new Function("useRef", `return \`${result}\``)(useRef)
|
|
1045
|
+
|
|
1046
|
+
if (!result.trim().startsWith("<body>")) {
|
|
1047
|
+
console.warn(
|
|
1048
|
+
"You should wrap your html in a body tag, vader may not grab all html!"
|
|
1049
|
+
);
|
|
1050
|
+
}
|
|
1051
|
+
|
|
1052
|
+
|
|
1053
|
+
|
|
1054
|
+
return this.parseHTML(result);
|
|
1055
|
+
}
|
|
1056
|
+
|
|
1057
|
+
|
|
998
1058
|
}
|
|
999
1059
|
// write types to ensure it returns a string
|
|
1000
1060
|
/**
|
|
@@ -1101,39 +1161,80 @@ export const include = async (path) => {
|
|
|
1101
1161
|
return res.text();
|
|
1102
1162
|
})
|
|
1103
1163
|
.then(async (data) => {
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1164
|
+
data = new Function(`return \`${data}\`;`)();
|
|
1165
|
+
|
|
1166
|
+
let dom = new DOMParser().parseFromString(data, "text/html");
|
|
1167
|
+
let elements = dom.documentElement.querySelectorAll("*");
|
|
1168
|
+
let conccurentIncludes = [];
|
|
1169
|
+
if(cache[path]){
|
|
1170
|
+
return new Function(`return \`${cache[path]}\`;`)();
|
|
1171
|
+
}
|
|
1172
|
+
if (elements.length > 0) {
|
|
1173
|
+
for (var i = 0; i < elements.length; i++) {
|
|
1109
1174
|
|
|
1110
|
-
|
|
1111
|
-
|
|
1175
|
+
if (elements[i].nodeName === "INCLUDE") {
|
|
1176
|
+
if(!elements[i].getAttribute("src") || elements[i].getAttribute("src") === ""){
|
|
1177
|
+
throw new Error("Include tag must have src attribute")
|
|
1178
|
+
}
|
|
1179
|
+
|
|
1180
|
+
let componentName = elements[i].getAttribute("src")?.split("/").pop()?.split(".")[0]
|
|
1181
|
+
// @ts-ignore
|
|
1182
|
+
let filedata = await include(elements[i].getAttribute("src"));
|
|
1183
|
+
filedata = new Function(`return \`${filedata}\`;`)();
|
|
1184
|
+
let newdom = new DOMParser().parseFromString(filedata, "text/html");
|
|
1112
1185
|
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1186
|
+
newdom.querySelectorAll("include").forEach((el)=>{
|
|
1187
|
+
el.remove()
|
|
1188
|
+
})
|
|
1189
|
+
// @ts-ignore
|
|
1190
|
+
|
|
1191
|
+
let els = dom.querySelectorAll(componentName)
|
|
1192
|
+
|
|
1193
|
+
els.forEach((el)=>{
|
|
1194
|
+
|
|
1195
|
+
console.log(el)
|
|
1196
|
+
if(el.attributes.length > 0){
|
|
1197
|
+
for(var i = 0; i < el.attributes.length; i++){
|
|
1198
|
+
newdom.body.outerHTML = newdom.body.outerHTML.replace(`{{${el.attributes[i].name}}}`, el.attributes[i].value)
|
|
1199
|
+
}
|
|
1200
|
+
|
|
1201
|
+
}
|
|
1202
|
+
if(el.children.length > 0 && newdom.body.querySelector('slot')){
|
|
1203
|
+
for(var i = 0; i < el.children.length; i++){
|
|
1204
|
+
let slots = newdom.body.querySelectorAll("slot")
|
|
1205
|
+
slots.forEach((slot)=>{
|
|
1206
|
+
let id = slot.getAttribute("id")
|
|
1207
|
+
if(id === el.nodeName.toLowerCase()){
|
|
1208
|
+
slot.outerHTML = `<div>${el.innerHTML}</div>`
|
|
1209
|
+
}
|
|
1210
|
+
})
|
|
1211
|
+
|
|
1212
|
+
|
|
1213
|
+
}
|
|
1214
|
+
|
|
1215
|
+
}
|
|
1126
1216
|
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1217
|
+
dom.body.querySelectorAll('include').forEach((el)=>{
|
|
1218
|
+
el.remove()
|
|
1219
|
+
})
|
|
1220
|
+
|
|
1221
|
+
dom.body.outerHTML = dom.body.outerHTML.replace(el.outerHTML, newdom.body.innerHTML)
|
|
1222
|
+
|
|
1223
|
+
|
|
1224
|
+
})
|
|
1225
|
+
|
|
1130
1226
|
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1227
|
+
|
|
1228
|
+
|
|
1229
|
+
}
|
|
1230
|
+
}
|
|
1231
|
+
|
|
1232
|
+
|
|
1136
1233
|
}
|
|
1234
|
+
|
|
1235
|
+
data = dom.body.outerHTML
|
|
1236
|
+
|
|
1237
|
+
return data;
|
|
1137
1238
|
});
|
|
1138
1239
|
};
|
|
1139
1240
|
|
package/worker.js
ADDED
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
onmessage = (e)=>{
|
|
2
|
+
let time_started = Date.now()
|
|
3
|
+
let strings = e.data.strings
|
|
4
|
+
let args = e.data.args
|
|
5
|
+
let l = e.data.location.split('/#/')[0]
|
|
6
|
+
let result = "";
|
|
7
|
+
for (let i = 0; i < strings.length; i++) {
|
|
8
|
+
result += strings[i];
|
|
9
|
+
if (i < args.length) {
|
|
10
|
+
result += args[i];
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
let comments = result.match(/--([^>]*)--/gs)
|
|
15
|
+
if(comments){
|
|
16
|
+
while(comments.length){
|
|
17
|
+
let comment = comments.pop()
|
|
18
|
+
console.log(comment)
|
|
19
|
+
// @ts-ignore
|
|
20
|
+
result = result.replace(comment,'')
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
let code = result.match(/<code([^>]*)>/g)
|
|
25
|
+
if(code){
|
|
26
|
+
while(code.length){
|
|
27
|
+
let c = code.pop()
|
|
28
|
+
// @ts-ignore
|
|
29
|
+
c = c.replace('<code','').replace('>','')
|
|
30
|
+
result = result.replace(`<code${c}>`,`<code${c} style="background:#000;color:#fff;padding:5px;border-radius:5px;font-size:12px;font-weight:bold">`)
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
if(!result.includes('<body>')){
|
|
36
|
+
throw new Error(`Vader Error: You must enclose your html in a body tag for all components. \n\n${result}`)
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* @type {string[]}
|
|
40
|
+
* @description - grabbing all className attributes and replace them with class
|
|
41
|
+
*/
|
|
42
|
+
// @ts-ignore
|
|
43
|
+
result = result.replace(/classname/g,'class')
|
|
44
|
+
/**
|
|
45
|
+
* @type {string[]}
|
|
46
|
+
* @description - grabbing all image tags and replace the src attribute with the absolute path
|
|
47
|
+
*/
|
|
48
|
+
// @ts-ignore
|
|
49
|
+
let images = result.match(/<img([^>]*)>/g)
|
|
50
|
+
for(let i = 0; i < images.length; i++){
|
|
51
|
+
let image = images[i]
|
|
52
|
+
let src = image.match(/src="([^"]*)"/)
|
|
53
|
+
let alt = image.match(/alt="([^"]*)"/)
|
|
54
|
+
if(src){
|
|
55
|
+
if(!src[1].includes('http') || !result.includes('<!-- #vader-disable_relative-paths -->')){
|
|
56
|
+
result = result.replace(src[0],`src="${l}/public/${src[1]}"`)
|
|
57
|
+
}else{
|
|
58
|
+
throw new Error(`Vader Error: You cannot use relative paths in the src attribute of ${src[0]}. Use absolute paths instead. \n\n${src[0]}`)
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
if(!alt && !result.includes('<!-- #vader-disable_accessibility -->')){
|
|
62
|
+
throw new Error(`Vader Error: You must include an alt attribute in the image tag \n\n${image} of class ${e.data.name}. `)
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// @ts-ignore
|
|
66
|
+
if(!caches.match(`${l}/public/${src[1]}`)){
|
|
67
|
+
caches.open('vader').then((cache)=>{
|
|
68
|
+
// @ts-ignore
|
|
69
|
+
cache.add(`${l}/public/${src[1]}`)
|
|
70
|
+
// @ts-ignore
|
|
71
|
+
console.log('cached', `${l}/public/${src[1]}`)
|
|
72
|
+
}).catch((err)=>{
|
|
73
|
+
console.log(err)
|
|
74
|
+
})
|
|
75
|
+
}else{
|
|
76
|
+
// @ts-ignore
|
|
77
|
+
console.log('already cached', caches.match(`${l}/public/${src[1]}`))
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
let href = result.match(/href="([^"]*)"/g)
|
|
82
|
+
if(href){
|
|
83
|
+
while(href.length){
|
|
84
|
+
let h = href.pop()
|
|
85
|
+
// @ts-ignore
|
|
86
|
+
h = h.replace('href="','').replace('"','')
|
|
87
|
+
if(!h.includes('http') || !result.includes('<!-- #vader-disable_relative-paths -->')){
|
|
88
|
+
result = result.replace(`href="${h}"`,`href="#${h}"`)
|
|
89
|
+
}else{
|
|
90
|
+
throw new Error(`Vader Error: You cannot use relative paths in ${e.data.file}. Use absolute paths instead. \n\n${h}`)
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
let time_ended = Date.now()
|
|
96
|
+
let time_taken = time_ended - time_started
|
|
97
|
+
let hasran = false
|
|
98
|
+
if(l.includes('localhost') || l.includes('127.0.0.1') && !hasran){
|
|
99
|
+
hasran = true
|
|
100
|
+
result+= `\$\{console.log('%c${e.data.name} component rendered in ${time_taken}ms','color:#fff;background:#000;padding:5px;border-radius:5px;font-size:12px;font-weight:bold'),""\}`
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
postMessage(`<div data-component=${e.data.name}>${result}</div>`)
|
|
105
|
+
|
|
106
|
+
}
|