coralite 0.6.2 → 0.6.4

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/README.md CHANGED
@@ -30,20 +30,6 @@ yarn add -D coralite
30
30
  pnpm add -D coralite
31
31
  ```
32
32
 
33
- ## Requirements
34
-
35
- Coralite uses **ECMAScript Modules** which requires to run Node.js with the **`--experimental-vm-modules`** option enabled.
36
-
37
- ```bash
38
- node --experimental-vm-modules node_modules/coralite/bin/coralite.js [options]
39
- ```
40
-
41
- or using NODE_OPTIONS
42
-
43
- ```bash
44
- NODE_OPTIONS=--experimental-vm-modules coralite [options]
45
- ```
46
-
47
33
  ## Basic Syntax
48
34
 
49
35
  Coralite is executed using the following command:
@@ -65,7 +51,7 @@ To generate a website using Coralite, you must provide three essential options:
65
51
  Here's an example of how these options might look:
66
52
 
67
53
  ```bash
68
- coralite --templates ./src/templates --pages ./src/pages --output ./dist
54
+ coralite --templates ./path/to/templates --pages ./path/to/pages --output ./dist
69
55
  ```
70
56
 
71
57
  ## Optional Options
@@ -75,5 +61,20 @@ coralite --templates ./src/templates --pages ./src/pages --output ./dist
75
61
  Run the CLI in dry-run mode to preview the actions that would be performed without actually generating the website. This is useful for debugging or when you want to check potential issues before committing changes:
76
62
 
77
63
  ```bash
78
- coralite --templates ./src/templates --pages ./src/pages --output ./dist --dry-run
64
+ coralite --templates ./path/to/templates --pages ./path/to/pages --output ./dist --dry-run
79
65
  ```
66
+
67
+ ## Troubleshooting
68
+
69
+
70
+ Coralite uses **ECMAScript Modules** which requires to run Node.js with the **`--experimental-vm-modules`** option enabled.
71
+
72
+ ```bash
73
+ node --experimental-vm-modules node_modules/coralite/bin/coralite.js [options]
74
+ ```
75
+
76
+ or using NODE_OPTIONS
77
+
78
+ ```bash
79
+ NODE_OPTIONS=--experimental-vm-modules coralite [options]
80
+ ```
package/bin/coralite.js CHANGED
@@ -1,4 +1,4 @@
1
- #!/usr/bin/env node
1
+ #!/usr/bin/env node --experimental-vm-modules
2
2
 
3
3
  import { getSubDirectory, getPkg, coralite } from '#lib'
4
4
  import { Command } from 'commander'
@@ -6,6 +6,9 @@ import { join } from 'node:path'
6
6
  import { existsSync, mkdirSync, writeFileSync } from 'node:fs'
7
7
  import kleur from 'kleur'
8
8
 
9
+ // Remove all Node warnings before doing anything else
10
+ process.removeAllListeners('warning')
11
+
9
12
  const pkg = await getPkg()
10
13
  const program = new Command()
11
14
 
package/change-logs.md ADDED
@@ -0,0 +1,96 @@
1
+ # 🎁 Release notes (`v0.6.4`)
2
+
3
+ ## Changes
4
+ - 41771d5 (HEAD -> main, tag: v0.6.4, origin/main) chore: version bump - (*Thomas David*)
5
+ - ea2ef46 test: cover values param - (*Thomas David*)
6
+ - 60e70d3 feat: add props argument to tokens and slots functions - (*Thomas David*)
7
+ - 1ed074a chore: version bump - (*Thomas David*)
8
+ - 9d710c0 ci: fix publish needs ref - (*Thomas David*)
9
+
10
+ ## Metadata
11
+ ```
12
+ This version -------- v0.6.4
13
+ Previous version ---- v0.6.3
14
+ Total commits ------- 5
15
+ ```
16
+
17
+ # 🎁 Release notes (`v0.6.3`)
18
+
19
+ ## Changes
20
+ - 6fe640d (HEAD -> main, tag: v0.6.3, origin/main) test: cover ignore by attribute - (*[Thomas David](https://github.com/tjdav)*)
21
+ - a47ff8f types: add IgnoreByAttribute type - (*[Thomas David](https://github.com/tjdav)*)
22
+ - 8547c37 feat: ignore element by attributes inside meta and component parsers - (*[Thomas David](https://github.com/tjdav)*)
23
+ - f61ae88 docs: update ignore-attribute example with quotes - (*[Thomas David](https://github.com/tjdav)*)
24
+ - d4a277d docs: create consistent path names in example - (*[Thomas David](https://github.com/tjdav)*)
25
+ - 566463f docs: remove requirements section - (*[Thomas David](https://github.com/tjdav)*)
26
+ - 2493ab3 style: import type new line - (*[Thomas David](https://github.com/tjdav)*)
27
+ - 2e44174 ci: test before publish - (*[Thomas David](https://github.com/tjdav)*)
28
+ - c1d5ce7 fix: add template id to script module error - (*[Thomas David](https://github.com/tjdav)*)
29
+ - 4fabac1 ci: include self to test script - (*[Thomas David](https://github.com/tjdav)*)
30
+ - efd34d0 fix: add --experimental-vm-modules to shebang - (*[Thomas David](https://github.com/tjdav)*)
31
+ - 7da5d98 refactor: add type check before splicing children. - (*[Thomas David](https://github.com/tjdav)*)
32
+ - 2e39027 fix: catch bad options for aggregate function - (*[Thomas David](https://github.com/tjdav)*)
33
+
34
+ ## Metadata
35
+ ```
36
+ This version -------- v0.6.3
37
+ Previous version ---- v0.6.2
38
+ Total commits ------- 13
39
+ ```
40
+ # 🎁 Release notes (`v0.6.2`)
41
+
42
+ ## Changes
43
+ - be6c54c (HEAD -> main, tag: v0.6.2, origin/main) fix: update lock - (*[Thomas David](https://github.com/tjdav)*)
44
+ - 15d9b4e chore: version bump - (*[Thomas David](https://github.com/tjdav)*)
45
+ - fac695e fix: node v18 requires globalThis reference for crypto - (*[Thomas David](https://github.com/tjdav)*)
46
+ - d7c551e doc: format doc links - (*[Thomas David](https://github.com/tjdav)*)
47
+
48
+ ## Metadata
49
+ ```
50
+ This version -------- v0.6.2
51
+ Previous version ---- v0.6.1
52
+ Total commits ------- 4
53
+ ```
54
+ # 🎁 Release notes (`v0.6.1`)
55
+
56
+ ## Changes
57
+ - bcc1637 (HEAD -> main, tag: v0.6.1, origin/main) chore: version bump - (*[Thomas David](https://github.com/tjdav)*)
58
+ - 95cfdba docs: add doc links - (*[Thomas David](https://github.com/tjdav)*)
59
+ - 101a305 fix: render computedSlot nodes - (*[Thomas David](https://github.com/tjdav)*)
60
+ - 11a35d8 feat: dynamically import modules - (*[Thomas David](https://github.com/tjdav)*)
61
+ - e1364b9 docs: add CoraliteResult type - (*[Thomas David](https://github.com/tjdav)*)
62
+ - 11c6405 docs: add @example to coralite - (*[Thomas David](https://github.com/tjdav)*)
63
+ - a050263 docs: basic technical documentation - (*[Thomas David](https://github.com/tjdav)*)
64
+ - 83fdddd docs: update dry run option - (*[Thomas David](https://github.com/tjdav)*)
65
+
66
+ ## Metadata
67
+ ```
68
+ This version -------- v0.6.1
69
+ Previous version ---- v0.6.0
70
+ Total commits ------- 8
71
+ ```
72
+ # 🎁 Release notes (`v0.6.0`)
73
+
74
+ ## Changes
75
+ - 22d75e2 (HEAD -> main, tag: v0.6.0, origin/main) chore: version bump - (*[Thomas David](https://github.com/tjdav)*)
76
+ - c5cc7cc lint: ignore playwright-report - (*[Thomas David](https://github.com/tjdav)*)
77
+ - fdb3697 docs: add dry run option - (*[Thomas David](https://github.com/tjdav)*)
78
+ - 891db2e feat: export coralite utils - (*[Thomas David](https://github.com/tjdav)*)
79
+ - 9265681 test: cover ignore attribute - (*[Thomas David](https://github.com/tjdav)*)
80
+ - 5d44661 fix: allow missing component to compile - (*[Thomas David](https://github.com/tjdav)*)
81
+ - f3d6e65 docs: add remove prop to CoraliteElement - (*[Thomas David](https://github.com/tjdav)*)
82
+ - 229fef5 feat: new option to ignore element by attribute name value pair - (*[Thomas David](https://github.com/tjdav)*)
83
+ - c78dde1 chore: include kleur dep - (*[Thomas David](https://github.com/tjdav)*)
84
+ - b10bbe8 feat: update cli to use coralite module - (*[Thomas David](https://github.com/tjdav)*)
85
+ - 48fe816 docs: make defineComponent param tokens and slots optional - (*[Thomas David](https://github.com/tjdav)*)
86
+ - 02a5e8f feat: move coralite to a module - (*[Thomas David](https://github.com/tjdav)*)
87
+ - d336090 feat: get package.json util function - (*[Thomas David](https://github.com/tjdav)*)
88
+ - e210844 feat: add document used in error message - (*[Thomas David](https://github.com/tjdav)*)
89
+ - 1556a3b chore: version bump - (*[Thomas David](https://github.com/tjdav)*)
90
+
91
+ ## Metadata
92
+ ```
93
+ This version -------- v0.6.0
94
+ Previous version ---- v0.5.1
95
+ Total commits ------- 15
96
+ ```
package/lib/coralite.js CHANGED
@@ -8,7 +8,8 @@ import render from 'dom-serializer'
8
8
  * CoraliteAggregateTemplate,
9
9
  * CoraliteAnyNode,
10
10
  * CoraliteModule,
11
- * CoraliteResult} from '#types'
11
+ * CoraliteResult
12
+ * } from '#types'
12
13
  */
13
14
 
14
15
  /**
@@ -18,7 +19,13 @@ import render from 'dom-serializer'
18
19
 
19
20
  /**
20
21
  * @callback DefineComponentSlot
21
- * @param {CoraliteAnyNode[]} nodes
22
+ * @param {CoraliteAnyNode[]} nodes - The nodes to be rendered in the component's slots
23
+ * @param {Object.<string, string>} values - Attribute values
24
+ */
25
+
26
+ /**
27
+ * @callback DefineComponentToken
28
+ * @param {Object.<string, string>} values - Attribute values
22
29
  */
23
30
 
24
31
  /**
@@ -31,7 +38,7 @@ export const tokens = {}
31
38
  *
32
39
  * @param {Object} options
33
40
  * @param {string} [options.id] - Optional component id, if not defined, the id will be extracted from the first top level element with the id attribute
34
- * @param {Object.<string, (string | Function)>} [options.tokens] - Token names and values are either strings or functions representing the corresponding tokens' content or behavior.
41
+ * @param {Object.<string, (string | DefineComponentToken)>} [options.tokens] - Token names and values are either strings or functions representing the corresponding tokens' content or behavior.
35
42
  * @param {Object.<string, DefineComponentSlot>} [options.slots] - Middleware for slot content
36
43
  * @returns {Promise<Object.<string, string>>}
37
44
  */
@@ -98,7 +105,7 @@ export async function coralite ({
98
105
  // create templates
99
106
  for (let i = 0; i < htmlTemplates.length; i++) {
100
107
  const html = htmlTemplates[i]
101
- const coraliteModule = parseModule(html.content)
108
+ const coraliteModule = parseModule(html.content, ignoreByAttribute)
102
109
 
103
110
  coraliteModules[coraliteModule.id] = coraliteModule
104
111
  }
@@ -1,9 +1,10 @@
1
1
  import { join } from 'node:path'
2
2
  import getHTML from './get-html.js'
3
3
  import { createComponent, parseHTMLMeta } from './parse.js'
4
+ import { existsSync } from 'node:fs'
4
5
 
5
6
  /**
6
- * @import { CoraliteTokenOptions, CoraliteModule, CoraliteDocument, CoraliteModuleValues } from '#types'
7
+ * @import { CoraliteTokenOptions, CoraliteModule, CoraliteDocument, CoraliteModuleValues, CoraliteAggregateTemplate } from '#types'
7
8
  */
8
9
 
9
10
  /**
@@ -11,8 +12,7 @@ import { createComponent, parseHTMLMeta } from './parse.js'
11
12
  *
12
13
  * @param {Object} options - Configuration object for the aggregation process
13
14
  * @param {string} options.path - The path to aggregate, relative to pages directory
14
- * @param {Object} options.template - Templates used to display the result
15
- * @param {string} options.template.item - Unique identifier for the component used for each document
15
+ * @param {CoraliteAggregateTemplate | string} options.template - Templates used to display the result
16
16
  * @param {boolean} [options.recursive] - Whether to recursively search subdirectories
17
17
  * @param {CoraliteTokenOptions} [options.tokens] - Token configuration options
18
18
  * @param {CoraliteModuleValues} values - Default token values
@@ -25,15 +25,39 @@ import { createComponent, parseHTMLMeta } from './parse.js'
25
25
  * aggregate({
26
26
  * path: 'button',
27
27
  * recursive: true,
28
- * template: { item: 'my-component' }
28
+ * template: 'my-component'
29
29
  * }, {
30
30
  * className: 'btn'
31
31
  * }, components, document);
32
32
  * ```
33
33
  */
34
34
  export async function aggregate (options, values, components, document) {
35
+ if (!document.path.pages) {
36
+ throw new Error('Document page path was undefined')
37
+ }
38
+
39
+ const path = join(document.path.pages, options.path)
40
+
41
+ if (!existsSync(path)) {
42
+ /** @TODO Refer to documentation */
43
+ throw new Error('Aggregate path does not exist: "' + path + '"')
44
+ }
45
+
46
+ let componentId
47
+
48
+ if (typeof options.template === 'string') {
49
+ componentId = options.template
50
+ } else if (typeof options.template === 'object') {
51
+ componentId = options.template.item
52
+ }
53
+
54
+ if (!componentId) {
55
+ /** @TODO Refer to documentation */
56
+ throw new Error('Aggregate template was undefined')
57
+ }
58
+
35
59
  const pages = await getHTML({
36
- path: join(document.path.pages, options.path),
60
+ path,
37
61
  recursive: options.recursive,
38
62
  exclude: [document.name]
39
63
  })
@@ -42,7 +66,7 @@ export async function aggregate (options, values, components, document) {
42
66
 
43
67
  for (let i = 0; i < pages.length; i++) {
44
68
  const page = pages[i]
45
- const meta = parseHTMLMeta(page.content)
69
+ const meta = parseHTMLMeta(page.content, document.ignoreByAttribute)
46
70
  const pageValues = Object.assign({}, values)
47
71
 
48
72
  for (const key in meta) {
@@ -63,13 +87,16 @@ export async function aggregate (options, values, components, document) {
63
87
  }
64
88
 
65
89
  const component = await createComponent({
66
- id: options.template.item,
90
+ id: componentId,
67
91
  values: pageValues,
68
92
  components,
69
93
  document
70
94
  })
71
95
 
72
- result = result.concat(component.children)
96
+ if (typeof component === 'object') {
97
+ // concat rendered components
98
+ result = result.concat(component.children)
99
+ }
73
100
  }
74
101
 
75
102
  return result
package/lib/parse.js CHANGED
@@ -19,7 +19,8 @@ import { invalidCustomTags, validTags } from './tags.js'
19
19
  * CoraliteDocumentRoot,
20
20
  * CoraliteContentNode,
21
21
  * CoraliteModuleValues,
22
- * CoraliteAggregateTemplate
22
+ * CoraliteAggregateTemplate,
23
+ * IgnoreByAttribute
23
24
  * } from '#types'
24
25
  */
25
26
 
@@ -32,7 +33,7 @@ const customElementTagTokenRegExp = /^[^-].*[-._a-z0-9\u00B7\u00C0-\u00D6\u00D8-
32
33
  *
33
34
  * @param {HTMLData} html - The HTML data containing the content to parse
34
35
  * @param {CoralitePath} path - The path object containing the file path information
35
- * @param {Array<string[]>} [ignoreByAttribute] - Ignore element with attribute name value pair
36
+ * @param {IgnoreByAttribute} [ignoreByAttribute] - Ignore element with attribute name value pair
36
37
  * @returns {CoraliteDocument} An object representing the parsed document structure
37
38
  *
38
39
  * @example
@@ -76,17 +77,13 @@ export function parseHTMLDocument (html, path, ignoreByAttribute) {
76
77
  },
77
78
  onopentag (originalName, attributes) {
78
79
  const parent = stack[stack.length - 1]
79
- const element = createElement(originalName, attributes, customElements, parent)
80
-
81
- if (ignoreByAttribute) {
82
- for (let i = 0; i < ignoreByAttribute.length; i++) {
83
- const [key, value] = ignoreByAttribute[i]
84
-
85
- if (attributes[key] && attributes[key].includes(value)) {
86
- element.remove = true
87
- }
88
- }
89
- }
80
+ const element = createElement({
81
+ name: originalName,
82
+ attributes,
83
+ customElements,
84
+ parent,
85
+ ignoreByAttribute
86
+ })
90
87
 
91
88
  // push element to stack as it may have children
92
89
  stack.push(element)
@@ -99,10 +96,8 @@ export function parseHTMLDocument (html, path, ignoreByAttribute) {
99
96
  onclosetag () {
100
97
  const element = stack[stack.length - 1]
101
98
 
102
- // @ts-ignore
103
- if (element.remove) {
99
+ if (element.type === 'tag' && element.remove) {
104
100
  // remove element from tree
105
- // @ts-ignore
106
101
  element.parent.children.pop()
107
102
  }
108
103
 
@@ -149,7 +144,8 @@ export function parseHTMLDocument (html, path, ignoreByAttribute) {
149
144
  parentPath: html.parentPath,
150
145
  root,
151
146
  customElements,
152
- path
147
+ path,
148
+ ignoreByAttribute
153
149
  }
154
150
  }
155
151
 
@@ -157,6 +153,7 @@ export function parseHTMLDocument (html, path, ignoreByAttribute) {
157
153
  * Parses HTML string containing meta tags and extracts associated metadata.
158
154
  *
159
155
  * @param {string} string - HTML content containing meta tags
156
+ * @param {IgnoreByAttribute} ignoreByAttribute - IgnoreByAttribute option (optional) - If provided and true then the HTML tags will be ignored by this attribute name(s)
160
157
  * @returns {Object.<string, CoraliteToken[]>}
161
158
  *
162
159
  * @example
@@ -171,7 +168,7 @@ export function parseHTMLDocument (html, path, ignoreByAttribute) {
171
168
  * //}
172
169
  * ```
173
170
  */
174
- export function parseHTMLMeta (string) {
171
+ export function parseHTMLMeta (string, ignoreByAttribute) {
175
172
  // stack to keep track of current element hierarchy
176
173
  const stack = []
177
174
  /** @type {Object.<string, CoraliteToken[]>} */
@@ -182,6 +179,15 @@ export function parseHTMLMeta (string) {
182
179
  onopentag (name, attributes) {
183
180
  if (name === 'meta') {
184
181
  if (attributes.content) {
182
+ if (ignoreByAttribute) {
183
+ // ignore meta tags by attribute name
184
+ const ignore = findAttributesToIgnore(ignoreByAttribute, attributes)
185
+
186
+ if (ignore) {
187
+ return
188
+ }
189
+ }
190
+
185
191
  if (attributes.property) {
186
192
  addMetadata(meta, attributes.property, attributes.content)
187
193
  }
@@ -218,6 +224,7 @@ export function parseHTMLMeta (string) {
218
224
  * Parses HTML string containing meta tags or generates Coralite module structure from markup.
219
225
  *
220
226
  * @param {string} string - HTML content containing meta tags or module markup
227
+ * @param {IgnoreByAttribute} ignoreByAttribute
221
228
  * @returns {CoraliteModule} - Parsed module information, including template, script, tokens, and slot configurations
222
229
  *
223
230
  * @example
@@ -245,7 +252,7 @@ export function parseHTMLMeta (string) {
245
252
  * //}
246
253
  * ```
247
254
  */
248
- export function parseModule (string) {
255
+ export function parseModule (string, ignoreByAttribute) {
249
256
  // root element reference
250
257
  /** @type {CoraliteDocumentRoot} */
251
258
  const root = {
@@ -269,7 +276,13 @@ export function parseModule (string) {
269
276
  const parser = new Parser({
270
277
  onopentag (originalName, attributes) {
271
278
  const parent = stack[stack.length -1]
272
- const element = createElement(originalName, attributes, customElements, parent)
279
+ const element = createElement({
280
+ name: originalName,
281
+ attributes,
282
+ customElements,
283
+ parent,
284
+ ignoreByAttribute
285
+ })
273
286
  const attributeNames = Object.keys(attributes)
274
287
 
275
288
  // push element to stack as it may have children
@@ -352,6 +365,13 @@ export function parseModule (string) {
352
365
  }
353
366
  },
354
367
  onclosetag () {
368
+ const element = stack[stack.length - 1]
369
+
370
+ if (element.type === 'tag' && element.remove) {
371
+ // remove element from tree
372
+ element.parent.children.pop()
373
+ }
374
+
355
375
  // remove current element from stack as we're done with its children
356
376
  stack.pop()
357
377
  },
@@ -388,7 +408,7 @@ export function parseModule (string) {
388
408
 
389
409
  } else if (node.name == 'script') {
390
410
  if (node.attribs.type !== 'module') {
391
- throw new Error('Script tag must contain the `type="module"` attribute')
411
+ throw new Error('Template "'+ templateId + '" script tag must contain the `type="module"` attribute')
392
412
  }
393
413
  const scriptString = node.children[0]
394
414
 
@@ -457,10 +477,13 @@ export async function createComponent ({
457
477
  return console.warn('Could not find component "' + id +'" used in document "' + document.parentPath + '/' + document.name + '"')
458
478
  }
459
479
 
480
+ // clone the component to avoid mutations during replacement process.
460
481
  component = structuredClone(component)
482
+
461
483
  const template = component.template
462
484
  const computedTokens = []
463
485
 
486
+ // replace tokens in the template with their values from `values` object and store them into computedTokens array for later use if needed (e.g., to be injected back).
464
487
  for (let i = 0; i < component.tokens.attributes.length; i++) {
465
488
  const item = component.tokens.attributes[i]
466
489
 
@@ -480,7 +503,7 @@ export async function createComponent ({
480
503
 
481
504
  continue
482
505
  } else {
483
- console.error('Token "' + token.name +'" was empty used on "' + component.id + '"')
506
+ console.log('Token "' + token.name +'" was empty used on "' + component.id + '"')
484
507
  value = ''
485
508
  }
486
509
  }
@@ -524,7 +547,13 @@ export async function createComponent ({
524
547
 
525
548
  // merge values from component script
526
549
  if (component.script) {
527
- const computedValues = await parseScript(component, values, element, components, document)
550
+ const computedValues = await parseScript({
551
+ component,
552
+ values,
553
+ element,
554
+ components,
555
+ document
556
+ })
528
557
 
529
558
  values = Object.assign(values, computedValues)
530
559
 
@@ -588,7 +617,9 @@ export async function createComponent ({
588
617
  }
589
618
 
590
619
  // replace custom element with component
591
- children.splice(childIndex, 1, ...component.children)
620
+ if (typeof component === 'object') {
621
+ children.splice(childIndex, 1, ...component.children)
622
+ }
592
623
  }
593
624
 
594
625
  const slots = component.slotElements[id]
@@ -639,14 +670,21 @@ export async function createComponent ({
639
670
  /**
640
671
  * Parses a Coralite module script and compiles it into JavaScript.
641
672
  *
642
- * @param {CoraliteModule} component - The Coralite module to parse
643
- * @param {CoraliteModuleValues} values - Replacement tokens for the component
644
- * @param {CoraliteElement} element - Element
645
- * @param {Object.<string, CoraliteModule>} components - Mapping of other components that might be referenced
646
- * @param {CoraliteDocument} document - The current document being processed
673
+ * @param {Object} data
674
+ * @param {CoraliteModule} data.component - The Coralite module to parse
675
+ * @param {CoraliteModuleValues} data.values - Replacement tokens for the component
676
+ * @param {CoraliteElement} data.element - Element
677
+ * @param {Object.<string, CoraliteModule>} data.components - Mapping of other components that might be referenced
678
+ * @param {CoraliteDocument} data.document - The current document being processed
647
679
  * @returns {Promise<Object.<string,(string|(CoraliteElement|CoraliteTextNode)[])>>}
648
680
  */
649
- export async function parseScript (component, values, element, components, document) {
681
+ export async function parseScript ({
682
+ component,
683
+ values,
684
+ element,
685
+ components,
686
+ document
687
+ }) {
650
688
  const contextifiedObject = vm.createContext({
651
689
  crypto: globalThis.crypto,
652
690
  coralite: {
@@ -659,7 +697,7 @@ export async function parseScript (component, values, element, components, docum
659
697
  */
660
698
  async defineComponent (options) {
661
699
  /** @type {Object.<string, string>} */
662
- const values = {}
700
+ const tokens = {}
663
701
 
664
702
  if (options.tokens) {
665
703
  for (const key in options.tokens) {
@@ -667,7 +705,7 @@ export async function parseScript (component, values, element, components, docum
667
705
  const token = options.tokens[key]
668
706
 
669
707
  if (typeof token === 'function') {
670
- values[key] = await token()
708
+ tokens[key] = await token(values)
671
709
  }
672
710
  }
673
711
  }
@@ -695,7 +733,7 @@ export async function parseScript (component, values, element, components, docum
695
733
  }
696
734
 
697
735
  // compute slot nodes
698
- const result = computedSlot(slotContent) || slotContent
736
+ const result = computedSlot(slotContent, values) || slotContent
699
737
 
700
738
  // append new slot nodes
701
739
  for (let index = 0; index < result.length; index++) {
@@ -713,7 +751,7 @@ export async function parseScript (component, values, element, components, docum
713
751
  }
714
752
  }
715
753
 
716
- return values
754
+ return tokens
717
755
  },
718
756
  /**
719
757
  * @overload
@@ -733,7 +771,7 @@ export async function parseScript (component, values, element, components, docum
733
771
 
734
772
  if (typeof options.template === 'string') {
735
773
  templateId = options.template
736
- } else {
774
+ } else if (typeof options.template === 'object') {
737
775
  templateId = options.template.item
738
776
  }
739
777
 
@@ -842,12 +880,20 @@ function addMetadata (meta, name, content) {
842
880
  }
843
881
 
844
882
  /**
845
- * @param {string} name
846
- * @param {Object.<string, string>} attributes
847
- * @param {CoraliteElement[]} customElements
848
- * @param {CoraliteElement | CoraliteDocumentRoot} parent
883
+ * @param {Object} data
884
+ * @param {string} data.name
885
+ * @param {Object.<string, string>} data.attributes
886
+ * @param {CoraliteElement[]} data.customElements
887
+ * @param {CoraliteElement | CoraliteDocumentRoot} data.parent
888
+ * @param {IgnoreByAttribute} data.ignoreByAttribute
849
889
  */
850
- function createElement (name, attributes, customElements, parent) {
890
+ function createElement ({
891
+ name,
892
+ attributes,
893
+ customElements,
894
+ parent,
895
+ ignoreByAttribute
896
+ }) {
851
897
  const sanitisedName = name.toLowerCase()
852
898
 
853
899
  /** @type {CoraliteElement} */
@@ -860,6 +906,14 @@ function createElement (name, attributes, customElements, parent) {
860
906
  parentChildIndex: parent.children.length
861
907
  }
862
908
 
909
+ if (ignoreByAttribute) {
910
+ const ignore = findAttributesToIgnore(ignoreByAttribute, attributes)
911
+
912
+ if (ignore) {
913
+ element.remove = true
914
+ }
915
+ }
916
+
863
917
  if (!validTags[sanitisedName]) {
864
918
  if (invalidCustomTags[sanitisedName]) {
865
919
  throw new Error('Element name is reserved: "'+ sanitisedName +'"')
@@ -901,3 +955,22 @@ function createTextNode (data, parent) {
901
955
 
902
956
  return textNode
903
957
  }
958
+
959
+ /**
960
+ * Find attributes to be ignored by the parser.
961
+ *
962
+ * @param {Array<Array<string, string>>} ignore - An array of attribute pairs to be ignored by the parser
963
+ * @param {Object<string, string>} attributes - The HTML attribute object to be parsed by the parser
964
+ * @returns {boolean}
965
+ */
966
+ function findAttributesToIgnore (ignore, attributes) {
967
+ for (let i = 0; i < ignore.length; i++) {
968
+ const [key, value] = ignore[i]
969
+
970
+ if (attributes[key] && attributes[key].includes(value)) {
971
+ return true
972
+ }
973
+ }
974
+
975
+ return false
976
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "coralite",
3
- "version": "0.6.2",
3
+ "version": "0.6.4",
4
4
  "description": "HTML modules static site generator",
5
5
  "main": "./lib/coralite.js",
6
6
  "type": "module",
@@ -31,7 +31,7 @@
31
31
  "test-e2e": "playwright test",
32
32
  "test-e2e-report": "playwright show-report",
33
33
  "test-e2e-ui": "playwright test --ui",
34
- "html": "node --experimental-vm-modules bin/coralite.js -t tests/fixtures/templates -p tests/fixtures/pages -o dist -i 'data-dev=true'",
34
+ "html": "coralite -t tests/fixtures/templates -p tests/fixtures/pages -o dist -i 'data-dev=true'",
35
35
  "server": "sirv dist --dev --port 3000"
36
36
  },
37
37
  "bin": "bin/coralite.js",
@@ -56,6 +56,7 @@
56
56
  "@stylistic/eslint-plugin-js": "^2.12.1",
57
57
  "@stylistic/eslint-plugin-plus": "^2.12.1",
58
58
  "@types/node": "^22.10.5",
59
+ "coralite": "link:",
59
60
  "highlight.js": "^11.11.1",
60
61
  "kleur": "^4.1.5",
61
62
  "sirv-cli": "^3.0.0"
@@ -0,0 +1,6 @@
1
+ #! /bin/bash
2
+
3
+ export VERSION=$(git tag --sort=-committerdate | head -1)
4
+ export PREVIOUS_VERSION=$(git tag --sort=-committerdate | head -2 | awk '{split($0, tags, "\n")} END {print tags[1]}')
5
+ export CHANGES=$(git log --pretty="- %h%d %s - (*%an*)" $VERSION...$PREVIOUS_VERSION)
6
+ printf "# 🎁 Release notes (\`$VERSION\`)\n\n## Changes\n$CHANGES\n\n## Metadata\n\`\`\`\nThis version -------- $VERSION\nPrevious version ---- $PREVIOUS_VERSION\nTotal commits ------- $(echo "$CHANGES" | wc -l)\n\`\`\`\n" > change-logs.md
package/types/index.js CHANGED
@@ -123,6 +123,7 @@
123
123
  * @property {CoraliteDocumentRoot} root - Array of elements and text nodes in the document
124
124
  * @property {CoraliteElement[]} customElements - Custom elements defined in the document
125
125
  * @property {CoralitePath} path - Document's file path
126
+ * @property {IgnoreByAttribute} ignoreByAttribute - An array of attribute names and values to ignore by element type.
126
127
  */
127
128
 
128
129
  /**
@@ -136,3 +137,7 @@
136
137
  * @property {string} html - Raw HTML content of the render process as a string
137
138
  * @property {number} duration - The duration of the render process in milliseconds
138
139
  */
140
+
141
+ /**
142
+ * @typedef {Array<Array<string, string>>} IgnoreByAttribute - An array of attribute names and values to ignore by element type.
143
+ */