coralite 0.6.1 → 0.6.3

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
@@ -3,10 +3,10 @@
3
3
  coralite is a static site generator library built around the emerging [HTML modules proposal](https://github.com/WICG/webcomponents/blob/gh-pages/proposals/html-modules-explainer.md).
4
4
 
5
5
  - Getting started
6
- [Basic templating](./docs/basic-templating.md)
6
+ - [Basic templating](./docs/basic-templating.md)
7
7
  - Reference
8
- [Coralite CLI](./docs/coralite-cli.md)
9
- [Coralite](./docs/coralite.md)
8
+ - [Coralite CLI](./docs/coralite-cli.md)
9
+ - [Coralite](./docs/coralite.md)
10
10
 
11
11
  ## Installation
12
12
 
@@ -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,80 @@
1
+ # 🎁 Release notes (`v0.6.3`)
2
+
3
+ ## Changes
4
+ - 6fe640d (HEAD -> main, tag: v0.6.3, origin/main) test: cover ignore by attribute - (*[Thomas David](https://github.com/tjdav)*)
5
+ - a47ff8f types: add IgnoreByAttribute type - (*[Thomas David](https://github.com/tjdav)*)
6
+ - 8547c37 feat: ignore element by attributes inside meta and component parsers - (*[Thomas David](https://github.com/tjdav)*)
7
+ - f61ae88 docs: update ignore-attribute example with quotes - (*[Thomas David](https://github.com/tjdav)*)
8
+ - d4a277d docs: create consistent path names in example - (*[Thomas David](https://github.com/tjdav)*)
9
+ - 566463f docs: remove requirements section - (*[Thomas David](https://github.com/tjdav)*)
10
+ - 2493ab3 style: import type new line - (*[Thomas David](https://github.com/tjdav)*)
11
+ - 2e44174 ci: test before publish - (*[Thomas David](https://github.com/tjdav)*)
12
+ - c1d5ce7 fix: add template id to script module error - (*[Thomas David](https://github.com/tjdav)*)
13
+ - 4fabac1 ci: include self to test script - (*[Thomas David](https://github.com/tjdav)*)
14
+ - efd34d0 fix: add --experimental-vm-modules to shebang - (*[Thomas David](https://github.com/tjdav)*)
15
+ - 7da5d98 refactor: add type check before splicing children. - (*[Thomas David](https://github.com/tjdav)*)
16
+ - 2e39027 fix: catch bad options for aggregate function - (*[Thomas David](https://github.com/tjdav)*)
17
+
18
+ ## Metadata
19
+ ```
20
+ This version -------- v0.6.3
21
+ Previous version ---- v0.6.2
22
+ Total commits ------- 13
23
+ ```
24
+ # 🎁 Release notes (`v0.6.2`)
25
+
26
+ ## Changes
27
+ - be6c54c (HEAD -> main, tag: v0.6.2, origin/main) fix: update lock - (*[Thomas David](https://github.com/tjdav)*)
28
+ - 15d9b4e chore: version bump - (*[Thomas David](https://github.com/tjdav)*)
29
+ - fac695e fix: node v18 requires globalThis reference for crypto - (*[Thomas David](https://github.com/tjdav)*)
30
+ - d7c551e doc: format doc links - (*[Thomas David](https://github.com/tjdav)*)
31
+
32
+ ## Metadata
33
+ ```
34
+ This version -------- v0.6.2
35
+ Previous version ---- v0.6.1
36
+ Total commits ------- 4
37
+ ```
38
+ # 🎁 Release notes (`v0.6.1`)
39
+
40
+ ## Changes
41
+ - bcc1637 (HEAD -> main, tag: v0.6.1, origin/main) chore: version bump - (*[Thomas David](https://github.com/tjdav)*)
42
+ - 95cfdba docs: add doc links - (*[Thomas David](https://github.com/tjdav)*)
43
+ - 101a305 fix: render computedSlot nodes - (*[Thomas David](https://github.com/tjdav)*)
44
+ - 11a35d8 feat: dynamically import modules - (*[Thomas David](https://github.com/tjdav)*)
45
+ - e1364b9 docs: add CoraliteResult type - (*[Thomas David](https://github.com/tjdav)*)
46
+ - 11c6405 docs: add @example to coralite - (*[Thomas David](https://github.com/tjdav)*)
47
+ - a050263 docs: basic technical documentation - (*[Thomas David](https://github.com/tjdav)*)
48
+ - 83fdddd docs: update dry run option - (*[Thomas David](https://github.com/tjdav)*)
49
+
50
+ ## Metadata
51
+ ```
52
+ This version -------- v0.6.1
53
+ Previous version ---- v0.6.0
54
+ Total commits ------- 8
55
+ ```
56
+ # 🎁 Release notes (`v0.6.0`)
57
+
58
+ ## Changes
59
+ - 22d75e2 (HEAD -> main, tag: v0.6.0, origin/main) chore: version bump - (*[Thomas David](https://github.com/tjdav)*)
60
+ - c5cc7cc lint: ignore playwright-report - (*[Thomas David](https://github.com/tjdav)*)
61
+ - fdb3697 docs: add dry run option - (*[Thomas David](https://github.com/tjdav)*)
62
+ - 891db2e feat: export coralite utils - (*[Thomas David](https://github.com/tjdav)*)
63
+ - 9265681 test: cover ignore attribute - (*[Thomas David](https://github.com/tjdav)*)
64
+ - 5d44661 fix: allow missing component to compile - (*[Thomas David](https://github.com/tjdav)*)
65
+ - f3d6e65 docs: add remove prop to CoraliteElement - (*[Thomas David](https://github.com/tjdav)*)
66
+ - 229fef5 feat: new option to ignore element by attribute name value pair - (*[Thomas David](https://github.com/tjdav)*)
67
+ - c78dde1 chore: include kleur dep - (*[Thomas David](https://github.com/tjdav)*)
68
+ - b10bbe8 feat: update cli to use coralite module - (*[Thomas David](https://github.com/tjdav)*)
69
+ - 48fe816 docs: make defineComponent param tokens and slots optional - (*[Thomas David](https://github.com/tjdav)*)
70
+ - 02a5e8f feat: move coralite to a module - (*[Thomas David](https://github.com/tjdav)*)
71
+ - d336090 feat: get package.json util function - (*[Thomas David](https://github.com/tjdav)*)
72
+ - e210844 feat: add document used in error message - (*[Thomas David](https://github.com/tjdav)*)
73
+ - 1556a3b chore: version bump - (*[Thomas David](https://github.com/tjdav)*)
74
+
75
+ ## Metadata
76
+ ```
77
+ This version -------- v0.6.0
78
+ Previous version ---- v0.5.1
79
+ Total commits ------- 15
80
+ ```
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
  /**
@@ -98,7 +99,7 @@ export async function coralite ({
98
99
  // create templates
99
100
  for (let i = 0; i < htmlTemplates.length; i++) {
100
101
  const html = htmlTemplates[i]
101
- const coraliteModule = parseModule(html.content)
102
+ const coraliteModule = parseModule(html.content, ignoreByAttribute)
102
103
 
103
104
  coraliteModules[coraliteModule.id] = coraliteModule
104
105
  }
@@ -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
@@ -3,6 +3,7 @@ import { aggregate } from './html-module.js'
3
3
  import vm from 'node:vm'
4
4
  import { invalidCustomTags, validTags } from './tags.js'
5
5
 
6
+
6
7
  /**
7
8
  * @import {Module} from 'node:vm'
8
9
  * @import {
@@ -18,7 +19,8 @@ import { invalidCustomTags, validTags } from './tags.js'
18
19
  * CoraliteDocumentRoot,
19
20
  * CoraliteContentNode,
20
21
  * CoraliteModuleValues,
21
- * CoraliteAggregateTemplate
22
+ * CoraliteAggregateTemplate,
23
+ * IgnoreByAttribute
22
24
  * } from '#types'
23
25
  */
24
26
 
@@ -31,7 +33,7 @@ const customElementTagTokenRegExp = /^[^-].*[-._a-z0-9\u00B7\u00C0-\u00D6\u00D8-
31
33
  *
32
34
  * @param {HTMLData} html - The HTML data containing the content to parse
33
35
  * @param {CoralitePath} path - The path object containing the file path information
34
- * @param {Array<string[]>} [ignoreByAttribute] - Ignore element with attribute name value pair
36
+ * @param {IgnoreByAttribute} [ignoreByAttribute] - Ignore element with attribute name value pair
35
37
  * @returns {CoraliteDocument} An object representing the parsed document structure
36
38
  *
37
39
  * @example
@@ -75,17 +77,13 @@ export function parseHTMLDocument (html, path, ignoreByAttribute) {
75
77
  },
76
78
  onopentag (originalName, attributes) {
77
79
  const parent = stack[stack.length - 1]
78
- const element = createElement(originalName, attributes, customElements, parent)
79
-
80
- if (ignoreByAttribute) {
81
- for (let i = 0; i < ignoreByAttribute.length; i++) {
82
- const [key, value] = ignoreByAttribute[i]
83
-
84
- if (attributes[key] && attributes[key].includes(value)) {
85
- element.remove = true
86
- }
87
- }
88
- }
80
+ const element = createElement({
81
+ name: originalName,
82
+ attributes,
83
+ customElements,
84
+ parent,
85
+ ignoreByAttribute
86
+ })
89
87
 
90
88
  // push element to stack as it may have children
91
89
  stack.push(element)
@@ -98,10 +96,8 @@ export function parseHTMLDocument (html, path, ignoreByAttribute) {
98
96
  onclosetag () {
99
97
  const element = stack[stack.length - 1]
100
98
 
101
- // @ts-ignore
102
- if (element.remove) {
99
+ if (element.type === 'tag' && element.remove) {
103
100
  // remove element from tree
104
- // @ts-ignore
105
101
  element.parent.children.pop()
106
102
  }
107
103
 
@@ -148,7 +144,8 @@ export function parseHTMLDocument (html, path, ignoreByAttribute) {
148
144
  parentPath: html.parentPath,
149
145
  root,
150
146
  customElements,
151
- path
147
+ path,
148
+ ignoreByAttribute
152
149
  }
153
150
  }
154
151
 
@@ -156,6 +153,7 @@ export function parseHTMLDocument (html, path, ignoreByAttribute) {
156
153
  * Parses HTML string containing meta tags and extracts associated metadata.
157
154
  *
158
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)
159
157
  * @returns {Object.<string, CoraliteToken[]>}
160
158
  *
161
159
  * @example
@@ -170,7 +168,7 @@ export function parseHTMLDocument (html, path, ignoreByAttribute) {
170
168
  * //}
171
169
  * ```
172
170
  */
173
- export function parseHTMLMeta (string) {
171
+ export function parseHTMLMeta (string, ignoreByAttribute) {
174
172
  // stack to keep track of current element hierarchy
175
173
  const stack = []
176
174
  /** @type {Object.<string, CoraliteToken[]>} */
@@ -181,6 +179,15 @@ export function parseHTMLMeta (string) {
181
179
  onopentag (name, attributes) {
182
180
  if (name === 'meta') {
183
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
+
184
191
  if (attributes.property) {
185
192
  addMetadata(meta, attributes.property, attributes.content)
186
193
  }
@@ -217,6 +224,7 @@ export function parseHTMLMeta (string) {
217
224
  * Parses HTML string containing meta tags or generates Coralite module structure from markup.
218
225
  *
219
226
  * @param {string} string - HTML content containing meta tags or module markup
227
+ * @param {IgnoreByAttribute} ignoreByAttribute
220
228
  * @returns {CoraliteModule} - Parsed module information, including template, script, tokens, and slot configurations
221
229
  *
222
230
  * @example
@@ -244,7 +252,7 @@ export function parseHTMLMeta (string) {
244
252
  * //}
245
253
  * ```
246
254
  */
247
- export function parseModule (string) {
255
+ export function parseModule (string, ignoreByAttribute) {
248
256
  // root element reference
249
257
  /** @type {CoraliteDocumentRoot} */
250
258
  const root = {
@@ -268,7 +276,13 @@ export function parseModule (string) {
268
276
  const parser = new Parser({
269
277
  onopentag (originalName, attributes) {
270
278
  const parent = stack[stack.length -1]
271
- const element = createElement(originalName, attributes, customElements, parent)
279
+ const element = createElement({
280
+ name: originalName,
281
+ attributes,
282
+ customElements,
283
+ parent,
284
+ ignoreByAttribute
285
+ })
272
286
  const attributeNames = Object.keys(attributes)
273
287
 
274
288
  // push element to stack as it may have children
@@ -351,6 +365,13 @@ export function parseModule (string) {
351
365
  }
352
366
  },
353
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
+
354
375
  // remove current element from stack as we're done with its children
355
376
  stack.pop()
356
377
  },
@@ -387,7 +408,7 @@ export function parseModule (string) {
387
408
 
388
409
  } else if (node.name == 'script') {
389
410
  if (node.attribs.type !== 'module') {
390
- 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')
391
412
  }
392
413
  const scriptString = node.children[0]
393
414
 
@@ -456,10 +477,13 @@ export async function createComponent ({
456
477
  return console.warn('Could not find component "' + id +'" used in document "' + document.parentPath + '/' + document.name + '"')
457
478
  }
458
479
 
480
+ // clone the component to avoid mutations during replacement process.
459
481
  component = structuredClone(component)
482
+
460
483
  const template = component.template
461
484
  const computedTokens = []
462
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).
463
487
  for (let i = 0; i < component.tokens.attributes.length; i++) {
464
488
  const item = component.tokens.attributes[i]
465
489
 
@@ -479,7 +503,7 @@ export async function createComponent ({
479
503
 
480
504
  continue
481
505
  } else {
482
- console.error('Token "' + token.name +'" was empty used on "' + component.id + '"')
506
+ console.log('Token "' + token.name +'" was empty used on "' + component.id + '"')
483
507
  value = ''
484
508
  }
485
509
  }
@@ -523,7 +547,13 @@ export async function createComponent ({
523
547
 
524
548
  // merge values from component script
525
549
  if (component.script) {
526
- 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
+ })
527
557
 
528
558
  values = Object.assign(values, computedValues)
529
559
 
@@ -587,7 +617,9 @@ export async function createComponent ({
587
617
  }
588
618
 
589
619
  // replace custom element with component
590
- children.splice(childIndex, 1, ...component.children)
620
+ if (typeof component === 'object') {
621
+ children.splice(childIndex, 1, ...component.children)
622
+ }
591
623
  }
592
624
 
593
625
  const slots = component.slotElements[id]
@@ -638,16 +670,23 @@ export async function createComponent ({
638
670
  /**
639
671
  * Parses a Coralite module script and compiles it into JavaScript.
640
672
  *
641
- * @param {CoraliteModule} component - The Coralite module to parse
642
- * @param {CoraliteModuleValues} values - Replacement tokens for the component
643
- * @param {CoraliteElement} element - Element
644
- * @param {Object.<string, CoraliteModule>} components - Mapping of other components that might be referenced
645
- * @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
646
679
  * @returns {Promise<Object.<string,(string|(CoraliteElement|CoraliteTextNode)[])>>}
647
680
  */
648
- 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
+ }) {
649
688
  const contextifiedObject = vm.createContext({
650
- crypto,
689
+ crypto: globalThis.crypto,
651
690
  coralite: {
652
691
  tokens: values,
653
692
  /**
@@ -732,7 +771,7 @@ export async function parseScript (component, values, element, components, docum
732
771
 
733
772
  if (typeof options.template === 'string') {
734
773
  templateId = options.template
735
- } else {
774
+ } else if (typeof options.template === 'object') {
736
775
  templateId = options.template.item
737
776
  }
738
777
 
@@ -841,12 +880,20 @@ function addMetadata (meta, name, content) {
841
880
  }
842
881
 
843
882
  /**
844
- * @param {string} name
845
- * @param {Object.<string, string>} attributes
846
- * @param {CoraliteElement[]} customElements
847
- * @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
848
889
  */
849
- function createElement (name, attributes, customElements, parent) {
890
+ function createElement ({
891
+ name,
892
+ attributes,
893
+ customElements,
894
+ parent,
895
+ ignoreByAttribute
896
+ }) {
850
897
  const sanitisedName = name.toLowerCase()
851
898
 
852
899
  /** @type {CoraliteElement} */
@@ -859,6 +906,14 @@ function createElement (name, attributes, customElements, parent) {
859
906
  parentChildIndex: parent.children.length
860
907
  }
861
908
 
909
+ if (ignoreByAttribute) {
910
+ const ignore = findAttributesToIgnore(ignoreByAttribute, attributes)
911
+
912
+ if (ignore) {
913
+ element.remove = true
914
+ }
915
+ }
916
+
862
917
  if (!validTags[sanitisedName]) {
863
918
  if (invalidCustomTags[sanitisedName]) {
864
919
  throw new Error('Element name is reserved: "'+ sanitisedName +'"')
@@ -900,3 +955,22 @@ function createTextNode (data, parent) {
900
955
 
901
956
  return textNode
902
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.1",
3
+ "version": "0.6.3",
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,8 @@
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:",
60
+ "highlight.js": "^11.11.1",
59
61
  "kleur": "^4.1.5",
60
62
  "sirv-cli": "^3.0.0"
61
63
  },
@@ -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
+ */