coralite 0.1.1 → 0.2.0

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.
@@ -0,0 +1,11 @@
1
+ Based on the provided Git diff above, create a git commit message by strictly following these rules:
2
+
3
+ 1. Use one of the predefined prefixes (feat, fix, perf, build, chore, ci, docs, style, refactor, test, types, wip) or a custom prefix for non-changelog related tasks.
4
+ 2. The commit message must have a header, which includes a type and subject, separated by a colon.
5
+ 3. Follow the imperative present tense for both the subject and body of the commit message:
6
+ - Use concise and descriptive subjects.
7
+ - Avoid including implementation details in the body unless necessary for understanding context.
8
+ 4. Include an optional footer to provide information about breaking changes using the format "BREAKING CHANGE:" followed by additional details.
9
+ 5. Limit line length to 72 characters and maintain consistent use of whitespace for better readability and uniformity.
10
+ 6. If changes are about JSDoc, the prefix should be 'types'.
11
+ 7. Use any suggestion below this to help with the context.
@@ -0,0 +1,46 @@
1
+ name: Publish
2
+
3
+ on:
4
+ release:
5
+ types: [created]
6
+
7
+ jobs:
8
+ build:
9
+ runs-on: ubuntu-latest
10
+ steps:
11
+ - name: Checkout
12
+ uses: actions/checkout@v4
13
+
14
+ - uses: pnpm/action-setup@v4
15
+ name: Install pnpm
16
+ with:
17
+ version: 9
18
+ run_install: false
19
+
20
+ - name: Install Node.js
21
+ uses: actions/setup-node@v4
22
+ with:
23
+ node-version: 22
24
+ cache: "pnpm"
25
+
26
+ - name: Install dependencies
27
+ run: pnpm install
28
+
29
+ - name: Lint
30
+ run: pnpm run lint
31
+
32
+
33
+ publish-npm:
34
+ needs: build
35
+ runs-on: ubuntu-latest
36
+ steps:
37
+ - uses: actions/checkout@v4
38
+ - uses: actions/setup-node@v4
39
+ with:
40
+ node-version: 20
41
+ registry-url: https://registry.npmjs.org/
42
+ - run: npm ci
43
+ - run: npm publish
44
+ env:
45
+ NODE_AUTH_TOKEN: ${{secrets.npm_token}}
46
+
@@ -0,0 +1,12 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <module type="WEB_MODULE" version="4">
3
+ <component name="NewModuleRootManager">
4
+ <content url="file://$MODULE_DIR$">
5
+ <excludeFolder url="file://$MODULE_DIR$/.tmp" />
6
+ <excludeFolder url="file://$MODULE_DIR$/temp" />
7
+ <excludeFolder url="file://$MODULE_DIR$/tmp" />
8
+ </content>
9
+ <orderEntry type="inheritedJdk" />
10
+ <orderEntry type="sourceFolder" forTests="false" />
11
+ </component>
12
+ </module>
@@ -0,0 +1,6 @@
1
+ <component name="InspectionProjectProfileManager">
2
+ <profile version="1.0">
3
+ <option name="myName" value="Project Default" />
4
+ <inspection_tool class="Eslint" enabled="true" level="WARNING" enabled_by_default="true" />
5
+ </profile>
6
+ </component>
@@ -0,0 +1,6 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <project version="4">
3
+ <component name="JavaScriptLibraryMappings">
4
+ <includedPredefinedLibrary name="Node.js Core" />
5
+ </component>
6
+ </project>
@@ -0,0 +1,8 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <project version="4">
3
+ <component name="ProjectModuleManager">
4
+ <modules>
5
+ <module fileurl="file://$PROJECT_DIR$/.idea/coralite.iml" filepath="$PROJECT_DIR$/.idea/coralite.iml" />
6
+ </modules>
7
+ </component>
8
+ </project>
package/.idea/vcs.xml ADDED
@@ -0,0 +1,6 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <project version="4">
3
+ <component name="VcsDirectoryMappings">
4
+ <mapping directory="" vcs="Git" />
5
+ </component>
6
+ </project>
package/README.md CHANGED
@@ -1,9 +1,58 @@
1
1
  # Coralite
2
2
 
3
- A simple static site generator based on `HTML modules`
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
  ## Installation
6
6
 
7
+ Before using the Coralite CLI, ensure that it's installed on your system. You can install it globally using **npm**:
8
+
9
+ ```bash
10
+ npm install -g coralite
11
+ # or
12
+ yarn global add coralite
13
+ # or
14
+ pnpm add -g coralite
15
+ ```
16
+ You can also install coralite as a development dependency:
17
+
18
+ ```bash
19
+ npm install --save-dev coralite
20
+ # or
21
+ yarn add -D coralite
22
+ # or
23
+ pnpm add -D coralite
24
+ ```
25
+
26
+ ## Basic Syntax
27
+
28
+ Coralite is executed using the following command:
29
+
30
+ ```bash
31
+ coralite [options]
32
+ ```
33
+
34
+ Replace `[options]` with the desired flags and arguments.
35
+
36
+ ## Required Options
37
+
38
+ To generate a website using Coralite, you must provide three essential options:
39
+
40
+ - **-c or --components**: The path to your components directory containing reusable UI elements (e.g., `-c ./src/components`).
41
+ - **-p or --pages**: The path to your pages directory where static HTML files reside (e.g., `-p ./src/pages`).
42
+ - **--output or -o**: The output directory for the generated site (e.g., `--output ./dist`).
43
+
44
+ Here's an example of how these options might look:
45
+
46
+ ```bash
47
+ coralite --components ./src/components --pages ./src/pages --output ./dist
48
+ ```
49
+
50
+ ## Optional Options
51
+
52
+ ### -d or --dry
53
+
54
+ 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:
55
+
56
+ ```bash
57
+ coralite --components ./src/components --pages ./src/pages --output ./dist --dry
7
58
  ```
8
- npm install coralite --save-dev
9
- ```
package/bin/coralite.js CHANGED
@@ -1,11 +1,14 @@
1
1
  #!/usr/bin/env node
2
2
 
3
- import { getHTML, getComponentFromString, mergeComponentToDocument, getSubDirectory } from '../lib/index.js'
3
+ import { render } from 'dom-serializer'
4
+ import { getHTML, parseHTMLDocument, parseModule, createComponent, getSubDirectory } from '#lib'
4
5
  import { Command } from 'commander'
5
- import { resolve, join } from 'node:path'
6
+ import { join } from 'node:path'
6
7
  import { existsSync, mkdirSync, writeFileSync, readFileSync } from 'node:fs'
7
8
 
8
- /** @import { CoraliteComponent } from '#types' */
9
+ /**
10
+ * @import { CoraliteModule } from '#types'
11
+ */
9
12
 
10
13
  const pkg = JSON.parse(readFileSync(`./package.json`, 'utf-8'))
11
14
  const program = new Command()
@@ -19,7 +22,7 @@ program
19
22
  .requiredOption('-o, --output <path>', 'Output directory for the generated site')
20
23
  .option('-d, --dry', 'Run in dry-run mode')
21
24
 
22
- program.parse()
25
+ program.parse(process.argv)
23
26
  program.on('error', (err) => {
24
27
  console.error(err)
25
28
  })
@@ -39,23 +42,43 @@ const htmlPages = await getHTML({
39
42
  recursive: true
40
43
  })
41
44
 
42
- /** @type {Object.<string, CoraliteComponent>} */
45
+ /** @type {Object.<string, CoraliteModule>} */
43
46
  const components = {}
44
47
 
48
+ // create components
45
49
  for (let i = 0; i < htmlComponents.length; i++) {
46
50
  const html = htmlComponents[i]
47
- const component = getComponentFromString(html.content)
51
+ const component = parseModule(html.content)
52
+
48
53
  components[component.id] = component
49
54
  }
50
55
 
51
56
  for (let i = 0; i < htmlPages.length; i++) {
52
57
  const html = htmlPages[i]
53
-
54
- const content = await mergeComponentToDocument(html, components, {
55
- pages: resolve(pagesPath),
56
- components: resolve(componentsPath)
58
+ const document = parseHTMLDocument(html, {
59
+ pages: pagesPath,
60
+ components: componentsPath
57
61
  })
58
62
 
63
+ for (let i = 0; i < document.customElements.length; i++) {
64
+ const customElement = document.customElements[i]
65
+ const component = await createComponent({
66
+ id: customElement.name,
67
+ values: customElement.attribs,
68
+ customElementSlots: document.customElementSlots,
69
+ components,
70
+ document
71
+ })
72
+
73
+ // replace custom element with component
74
+ customElement.parent.children.splice(customElement.parentChildIndex, 1, ...component.children)
75
+ component.parent = customElement.parent
76
+ }
77
+
78
+ // render document
79
+ // @ts-ignore
80
+ const content = render(document.root)
81
+
59
82
  if (!dryRun) {
60
83
  // get pages sub directory
61
84
  const subDir = getSubDirectory(pagesPath, html.parentPath)
@@ -0,0 +1,3 @@
1
+ export default {
2
+ extends: ['@commitlint/config-conventional']
3
+ }
package/jsconfig.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "compilerOptions": {
3
3
  "checkJs": true,
4
4
  "module": "NodeNext",
5
- "target": "ES2020",
5
+ "target": "ES2022",
6
6
  "moduleResolution": "nodenext",
7
7
  }
8
8
  }
@@ -0,0 +1,38 @@
1
+ /**
2
+ * @import { CoraliteElement, CoraliteTextNode } from '#types'
3
+ */
4
+
5
+ /**
6
+ * These exports are placeholder for types
7
+ * The HTML module code is run in the `parseScript` function in parse.js
8
+ */
9
+
10
+ /**
11
+ * @type {Object.<string, string>}
12
+ */
13
+ export const tokens = {}
14
+
15
+ /**
16
+ * Defines a Coralite component
17
+ *
18
+ * @param {Object} options
19
+ * @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
20
+ * @param {Object.<string, (string | function)>} options.tokens - A map where keys are token names and values are either strings or functions representing the corresponding tokens' content or behavior.
21
+ * @returns {Promise<Object.<string, string>>}
22
+ */
23
+ export async function defineComponent (options) {
24
+ /** @type {Object.<string, string>} */
25
+ return {}
26
+ }
27
+
28
+ /**
29
+ * Aggregates HTML content from specified paths into a single collection of components.
30
+ *
31
+ * @param {Object} options - Configuration object for the aggregation process
32
+ * @param {string} options.componentId - Unique identifier for the component used for each document
33
+ * @param {string} options.path - The path to aggregate, relative to pages directory
34
+ * @returns {Promise<(CoraliteElement | CoraliteTextNode)[]>}
35
+ */
36
+ export async function aggregate (options) {
37
+ return []
38
+ }
package/lib/get-html.js CHANGED
@@ -7,13 +7,21 @@ import { readdir, readFile } from 'node:fs/promises'
7
7
 
8
8
  /**
9
9
  * Get HTML
10
- * @param {Object} options - html directory
11
- * @param {string} options.path - html directory
12
- * @param {boolean} [options.recursive] - If true, reads the contents of a directory recursively. In recursive mode, it will list all files, sub files and directories. Default: false.
13
- * @param {string[]} [options.exclude = []] - Exclude file by name
14
- * @returns {Promise<HTMLData[]>}
10
+ * @param {Object} options - Options for searching HTML files
11
+ * @param {string} options.path - Path to the directory containing HTML files
12
+ * @param {boolean} [options.recursive=false] - Whether to search recursively in subdirectories
13
+ * @param {string[]} [options.exclude=[]] - Files or directories to exclude from search
14
+ * @returns {Promise<HTMLData[]>} Array of HTML file data including parent path, name, and content
15
+ *
16
+ * @example
17
+ * // Example usage:
18
+ * const htmlFiles = await getHTML({
19
+ * path: 'src',
20
+ * recursive: true,
21
+ * exclude: ['index.html', 'subdir/file2.html']
22
+ * })
15
23
  */
16
- export default function getHTML ({ path, recursive, exclude = [] }) {
24
+ export default function getHTML ({ path, recursive = false, exclude = [] }) {
17
25
  return new Promise((resolve, reject) => {
18
26
  const html = []
19
27
 
@@ -0,0 +1,75 @@
1
+ import { join } from 'node:path'
2
+ import getHTML from './get-html.js'
3
+ import { createComponent, parseHTMLMeta } from './parse.js'
4
+
5
+ /**
6
+ * @import { CoraliteTokenOptions, CoraliteModule, CoraliteDocument } from '#types'
7
+ */
8
+
9
+ /**
10
+ * Aggregates HTML content from specified paths into a single collection of components.
11
+ *
12
+ * @param {Object} options - Configuration object for the aggregation process
13
+ * @param {string} options.path - The path to aggregate, relative to pages directory
14
+ * @param {string} options.componentId - Unique identifier for the component
15
+ * @param {boolean} [options.recursive] - Whether to recursively search subdirectories
16
+ * @param {CoraliteTokenOptions} [options.tokens] - Token configuration options
17
+ * @param {Object.<string, string>} values - Default token values
18
+ * @param {Object.<string, CoraliteModule>} components - Available components library
19
+ * @param {CoraliteDocument} document - Current document being processed
20
+ *
21
+ * @example
22
+ * ```javascript
23
+ * // Aggregating content from pages under 'components' directory into a component with id 'my-component'
24
+ * aggregate({
25
+ * path: 'button',
26
+ * recursive: true,
27
+ * componentId: 'my-component'
28
+ * }, {
29
+ * className: 'btn'
30
+ * }, components, document);
31
+ * ```
32
+ */
33
+ export async function aggregate (options, values, components, document) {
34
+ const pages = await getHTML({
35
+ path: join(document.path.pages, options.path),
36
+ recursive: options.recursive,
37
+ exclude: [document.name]
38
+ })
39
+
40
+ let result = []
41
+
42
+ for (let i = 0; i < pages.length; i++) {
43
+ const page = pages[i]
44
+ const meta = parseHTMLMeta(page.content)
45
+ const pageValues = Object.assign({}, values)
46
+
47
+ for (const key in meta) {
48
+ if (Object.prototype.hasOwnProperty.call(meta, key)) {
49
+ const data = meta[key]
50
+
51
+ for (let i = 0; i < data.length; i++) {
52
+ const item = data[i]
53
+ let suffix = ''
54
+
55
+ if (i > 0) {
56
+ suffix = '_' + i
57
+ }
58
+
59
+ pageValues[item.name + suffix] = item.content
60
+ }
61
+ }
62
+ }
63
+
64
+ const component = await createComponent({
65
+ id: options.componentId,
66
+ values: pageValues,
67
+ components,
68
+ document
69
+ })
70
+
71
+ result = result.concat(component.children)
72
+ }
73
+
74
+ return result
75
+ }
package/lib/index.js CHANGED
@@ -1,19 +1,8 @@
1
- import getComponentFromString from './get-component-from-string.js'
2
1
  import getHTML from './get-html.js'
3
- import mergeComponentToDocument from './merge-component-to-document.js'
4
- import getTokensFromString from './get-tokens-from-string.js'
5
- import getScriptFromString from './get-script-from-string.js'
6
- import getMetadataFromDocument from './get-metadata-from-document.js'
7
- import getSubDirectory from './get-subdirectory.js'
8
- import evalComputedTokens from './eval-computed-tokens.js'
2
+
3
+ export * from './parse.js'
4
+ export * from './path-utils.js'
9
5
 
10
6
  export {
11
- evalComputedTokens,
12
- getSubDirectory,
13
- getMetadataFromDocument,
14
- getScriptFromString,
15
- getTokensFromString,
16
- getComponentFromString,
17
- mergeComponentToDocument,
18
7
  getHTML
19
8
  }