cayo 0.9.10 → 1.0.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.
Files changed (122) hide show
  1. package/README.md +504 -5
  2. package/cayo.js +1 -298
  3. package/devlog.md +177 -0
  4. package/dist/cayo.svelte.js +80 -0
  5. package/dist/entry.svelte.js +16 -0
  6. package/dist/index.js +2 -0
  7. package/docs/config-reference.md +349 -0
  8. package/docs/how-cayo-works.md +28 -0
  9. package/docs/why-i-created-cayo.md +21 -0
  10. package/lib/cli/build.js +34 -0
  11. package/lib/cli/cli.js +152 -0
  12. package/lib/cli/dev.js +12 -0
  13. package/lib/cli/serve.js +25 -0
  14. package/lib/cli/watch.js +125 -0
  15. package/lib/core/bundle.js +155 -0
  16. package/lib/core/codegen.js +156 -0
  17. package/lib/core/compile/cayos.js +65 -0
  18. package/lib/core/compile/index.js +3 -0
  19. package/lib/core/compile/pages.js +61 -0
  20. package/lib/core/compile/template.js +24 -0
  21. package/lib/core/component.js +62 -0
  22. package/lib/core/config.js +206 -0
  23. package/lib/core/dependencies.js +167 -0
  24. package/lib/core/entry.js +24 -0
  25. package/lib/core/files.js +99 -0
  26. package/lib/core/logger.js +47 -0
  27. package/lib/core/page.js +59 -0
  28. package/lib/core/render/prerender.js +240 -0
  29. package/lib/core/render/renderer.js +52 -0
  30. package/lib/core/utils.js +60 -0
  31. package/package.json +21 -10
  32. package/scripts/build.js +60 -0
  33. package/src/cayo-warnings.js +37 -0
  34. package/src/cayo.svelte +36 -0
  35. package/src/entry.svelte +6 -0
  36. package/template/cayo.config.js +3 -0
  37. package/template/package-lock.json +4027 -0
  38. package/template/package.json +10 -0
  39. package/template/public/vite.svg +1 -0
  40. package/{tests/basic cases (old)/src/__index.svelte → template/src/__template.svelte} +3 -6
  41. package/template/src/components/counter.cayo.svelte +27 -0
  42. package/template/src/index.js +4 -0
  43. package/template/src/pages/index.svelte +15 -0
  44. package/template/src/style.css +13 -0
  45. package/lib/cli.js +0 -69
  46. package/lib/codegen.js +0 -79
  47. package/lib/components/Cayo.svelte +0 -25
  48. package/lib/config.js +0 -155
  49. package/lib/files.js +0 -84
  50. package/lib/prerender.js +0 -181
  51. package/lib/renderer.js +0 -49
  52. package/lib/runtime.js +0 -6
  53. package/lib/utils.js +0 -126
  54. package/lib/vite.config.js +0 -16
  55. package/notes.md +0 -3
  56. package/test/cayo.config.js +0 -35
  57. package/test/public/assets/cow.js +0 -1
  58. package/test/public/images/app-icon.png +0 -0
  59. package/test/src/__layout.svelte +0 -20
  60. package/test/src/components/Cool.cayo.svelte +0 -5
  61. package/test/src/components/Some.svelte +0 -1
  62. package/test/src/components/Test.cayo.svelte +0 -5
  63. package/test/src/index.js +0 -17
  64. package/test/src/main2.js +0 -1
  65. package/test/src/pages/hey.svelte +0 -8
  66. package/test/src/pages/howdy.svelte +0 -11
  67. package/test/src/pages/index.svelte +0 -38
  68. package/test/src/pages/some/page.svelte +0 -2
  69. package/tests/asset-dir/cayo.config.js +0 -38
  70. package/tests/asset-dir/package-lock.json +0 -1435
  71. package/tests/asset-dir/package.json +0 -19
  72. package/tests/asset-dir/public/images/app-icon.png +0 -0
  73. package/tests/asset-dir/src/__layout.svelte +0 -20
  74. package/tests/asset-dir/src/components/CayoExample.svelte +0 -5
  75. package/tests/asset-dir/src/components/Some.cayo.svelte +0 -6
  76. package/tests/asset-dir/src/index.js +0 -5
  77. package/tests/asset-dir/src/pages/index.svelte +0 -19
  78. package/tests/base-path/cayo.config.js +0 -36
  79. package/tests/base-path/package-lock.json +0 -1435
  80. package/tests/base-path/package.json +0 -19
  81. package/tests/base-path/public/assets/cow.js +0 -1
  82. package/tests/base-path/public/images/app-icon.png +0 -0
  83. package/tests/base-path/src/__layout.svelte +0 -20
  84. package/tests/base-path/src/components/CayoExample.svelte +0 -5
  85. package/tests/base-path/src/components/Some.cayo.svelte +0 -6
  86. package/tests/base-path/src/index.js +0 -5
  87. package/tests/base-path/src/pages/howdy.svelte +0 -12
  88. package/tests/base-path/src/pages/index.svelte +0 -20
  89. package/tests/basic/notcayo.config.js +0 -35
  90. package/tests/basic/package-lock.json +0 -1435
  91. package/tests/basic/package.json +0 -19
  92. package/tests/basic/public/assets/cow.js +0 -1
  93. package/tests/basic/public/images/app-icon.png +0 -0
  94. package/tests/basic/src/__layout.svelte +0 -20
  95. package/tests/basic/src/components/Cool.cayo.svelte +0 -4
  96. package/tests/basic/src/components/Some.svelte +0 -1
  97. package/tests/basic/src/index.js +0 -5
  98. package/tests/basic/src/main2.js +0 -1
  99. package/tests/basic/src/pages/hey.svelte +0 -8
  100. package/tests/basic/src/pages/howdy.svelte +0 -11
  101. package/tests/basic/src/pages/index.svelte +0 -33
  102. package/tests/basic/src/pages/some/some.svelte +0 -2
  103. package/tests/basic cases (old)/src/components/Cool.cayo.svelte +0 -4
  104. package/tests/basic cases (old)/src/components/Some.svelte +0 -1
  105. package/tests/basic cases (old)/src/components/dir/Cool.cayo.svelte +0 -4
  106. package/tests/basic cases (old)/src/main.js +0 -1
  107. package/tests/basic cases (old)/src/main2.js +0 -1
  108. package/tests/basic cases (old)/src/pages/hey.svelte +0 -2
  109. package/tests/basic cases (old)/src/pages/howdy.svelte +0 -11
  110. package/tests/basic cases (old)/src/pages/index.svelte +0 -27
  111. package/tests/nested-pages/cayo.config.js +0 -35
  112. package/tests/nested-pages/package-lock.json +0 -1435
  113. package/tests/nested-pages/package.json +0 -19
  114. package/tests/nested-pages/public/assets/cow.js +0 -1
  115. package/tests/nested-pages/public/images/app-icon.png +0 -0
  116. package/tests/nested-pages/src/__layout.svelte +0 -20
  117. package/tests/nested-pages/src/components/Cool.cayo.svelte +0 -4
  118. package/tests/nested-pages/src/index.js +0 -5
  119. package/tests/nested-pages/src/main2.js +0 -1
  120. package/tests/nested-pages/src/pages/index.svelte +0 -18
  121. package/tests/nested-pages/src/pages/some/other/page.svelte +0 -7
  122. package/tests/nested-pages/src/pages/some/page.svelte +0 -6
@@ -0,0 +1,10 @@
1
+ {
2
+ "type": "module",
3
+ "scripts": {
4
+ "dev": "cayo dev",
5
+ "build": "cayo build"
6
+ },
7
+ "devDependencies": {
8
+ "cayo": "^1.0.0"
9
+ }
10
+ }
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="31.88" height="32" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 257"><defs><linearGradient id="IconifyId1813088fe1fbc01fb466" x1="-.828%" x2="57.636%" y1="7.652%" y2="78.411%"><stop offset="0%" stop-color="#41D1FF"></stop><stop offset="100%" stop-color="#BD34FE"></stop></linearGradient><linearGradient id="IconifyId1813088fe1fbc01fb467" x1="43.376%" x2="50.316%" y1="2.242%" y2="89.03%"><stop offset="0%" stop-color="#FFEA83"></stop><stop offset="8.333%" stop-color="#FFDD35"></stop><stop offset="100%" stop-color="#FFA800"></stop></linearGradient></defs><path fill="url(#IconifyId1813088fe1fbc01fb466)" d="M255.153 37.938L134.897 252.976c-2.483 4.44-8.862 4.466-11.382.048L.875 37.958c-2.746-4.814 1.371-10.646 6.827-9.67l120.385 21.517a6.537 6.537 0 0 0 2.322-.004l117.867-21.483c5.438-.991 9.574 4.796 6.877 9.62Z"></path><path fill="url(#IconifyId1813088fe1fbc01fb467)" d="M185.432.063L96.44 17.501a3.268 3.268 0 0 0-2.634 3.014l-5.474 92.456a3.268 3.268 0 0 0 3.997 3.378l24.777-5.718c2.318-.535 4.413 1.507 3.936 3.838l-7.361 36.047c-.495 2.426 1.782 4.5 4.151 3.78l15.304-4.649c2.372-.72 4.652 1.36 4.15 3.788l-11.698 56.621c-.732 3.542 3.979 5.473 5.943 2.437l1.313-2.028l72.516-144.72c1.215-2.423-.88-5.186-3.54-4.672l-25.505 4.922c-2.396.462-4.435-1.77-3.759-4.114l16.646-57.705c.677-2.35-1.37-4.583-3.769-4.113Z"></path></svg>
@@ -2,17 +2,14 @@
2
2
  <html lang="en">
3
3
  <head>
4
4
  <meta charset="UTF-8" />
5
- <link rel="icon" href="/favicon.ico" />
5
+ <link rel="icon" href="data:image/svg+xml,<svg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 100 100%22><text y=%22.9em%22 font-size=%2290%22>🏝</text></svg>">
6
6
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
7
7
  %cayo.title%
8
+ %cayo.css%
8
9
  %cayo.head%
9
10
  </head>
10
11
  <body>
11
- <!--
12
- TODO: Show how to condtionally render any of these pieces based on dev vs. prod
13
- E.g., I need to remove head from prod, but want it there in dev
14
- -->
15
12
  %cayo.body%
16
13
  %cayo.script%
17
14
  </body>
18
- </html>
15
+ </html>
@@ -0,0 +1,27 @@
1
+ <script>
2
+ export let count = 0;
3
+ </script>
4
+
5
+ <div class="wrapper">
6
+ <button on:click={() => count++}>Count: {count}</button>
7
+ </div>
8
+
9
+ <style>
10
+ .wrapper {
11
+ display: flex;
12
+ justify-content: center;
13
+ }
14
+ button {
15
+ padding: .5rem;
16
+ background-color: transparent;
17
+ border: 1px solid rgba(81, 95, 240, .75);
18
+ color: white;
19
+ border-radius: 5px;
20
+ transition: .2s;
21
+ }
22
+ button:hover {
23
+ cursor: pointer;
24
+ border-color: rgb(81, 95, 240);
25
+ background-color: rgba(81, 95, 240, .25);
26
+ }
27
+ </style>
@@ -0,0 +1,4 @@
1
+ import './style.css';
2
+ window.addEventListener('load', () => {
3
+ renderCayos();
4
+ })
@@ -0,0 +1,15 @@
1
+ <script>
2
+ import { Cayo, Entry } from 'cayo';
3
+ const heading = '🏝 Cayo';
4
+ </script>
5
+
6
+ <h1>{heading}</h1>
7
+ <Cayo src="counter.cayo.svelte" />
8
+ <Entry src="index.js" />
9
+
10
+ <style>
11
+ h1 {
12
+ text-align: center;
13
+ font-family:-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;
14
+ }
15
+ </style>
@@ -0,0 +1,13 @@
1
+ body {
2
+ display: flex;
3
+ justify-content: center;
4
+ align-items: center;
5
+ flex-direction: column;
6
+ height: 100vh;
7
+ margin: 0;
8
+ background-color: #232731;
9
+ color: white;
10
+ }
11
+ h1 {
12
+ margin-top: 0;
13
+ }
package/lib/cli.js DELETED
@@ -1,69 +0,0 @@
1
- import { loadConfig } from './config.js';
2
- import yargs from 'yargs-parser';
3
- import { devServer } from './dev.js';
4
- import { build } from './build.js';
5
- import fs from 'fs-extra';
6
-
7
- // TODO: move this elsewhere
8
- if (!fs.existsSync(dotPath)) {
9
- await fs.mkdir(dotPath)
10
- }
11
-
12
- // Load config
13
-
14
- // Handle arguments
15
- function resolveArgs(argv) {
16
-
17
- const cmd = argv._[2]
18
- const options = {
19
- //TODO: support options from command line
20
- }
21
-
22
- switch (cmd) {
23
- case 'dev':
24
- return { cmd: 'dev', options };
25
- case 'build':
26
- return { cmd: 'build', options };
27
- default:
28
- return { cmd: 'help', options };
29
- }
30
- }
31
-
32
- function printHelp() {
33
- // TODO: help info
34
- console.log('help');
35
- }
36
-
37
- function run(command) {
38
- const { cmd, options } = command;
39
- try {
40
- // const { projectRoot, configPath } = options;
41
- const config = await loadConfig(options);
42
-
43
- // TODO: actually run command now
44
- } catch (err) {
45
- console.error(err);
46
- process.exit(1);
47
- }
48
- }
49
-
50
- // Run
51
- export async function cli(args) {
52
- const argv = yargs(args);
53
- const command = resolveArgs(argv);
54
- // TODO: do something with options
55
-
56
- switch(command.cmd) {
57
- case 'dev':
58
- // run server
59
- devServer();
60
- break;
61
- case 'build':
62
- // run build
63
- build();
64
- break;
65
- case 'help':
66
- default:
67
- printHelp();
68
- }
69
- }
package/lib/codegen.js DELETED
@@ -1,79 +0,0 @@
1
- import path from 'path';
2
-
3
- // Generate runtime helper that finds and parses a component instance's prop data
4
- export function generateGetProps() {
5
- return (
6
- `
7
- function getProps(cayoId) {
8
- const componentElement = document.querySelector(\`[data-cayo-id="\${cayoId}"]\`);
9
- const json = componentElement.dataset.cayoProps;
10
- return JSON.parse(json);
11
- }
12
- `
13
- );
14
- }
15
-
16
- export function generateCayoRuntime(components, config) {
17
- let code = '';
18
- let instances = '';
19
-
20
- if (Object.keys(components).length !== 0) {
21
- // TODO: add this path to config (internal only)
22
- // const componentPath = path.resolve(config.cayoPath, './__cayo/components');
23
- const componentPath = '/__cayo/components';
24
- Object.entries(components).forEach(([name, ids]) => {
25
- // Add component dependency import
26
- code += `import { ${name} } from '${componentPath}/${name}.js';\n`;
27
- // Generate component instances
28
- ids.forEach(id => {
29
- instances += generateComponentInstance(id, name)
30
- });
31
- });
32
-
33
- // Add getProps (used by component instances)
34
- code += generateGetProps();
35
- } else {
36
- instances += ` // No cayo component instances found in page HTML`;
37
- }
38
-
39
- // Add main render, which runs the component instantiations
40
- code += generateRender(instances);
41
-
42
- return { code };
43
- }
44
-
45
- function generateRender(contents) {
46
- return (
47
- `
48
- export default function render(cb) {
49
- var target = function (node) { return node; }
50
- if (cb) target = cb;
51
- ${contents}
52
- }
53
- `
54
- );
55
- }
56
-
57
- // Generate the code to wrap component instances in an event listener wrapper
58
- export function generateComponentInstanceWrapper(contents) {
59
- return (
60
- `
61
- document.addEventListener('DOMContentLoaded', function() {
62
- ${contents}
63
- });
64
- `
65
- );
66
- }
67
-
68
- // Generate the code for a component instance
69
- export function generateComponentInstance(cayoId, componentName) {
70
- return (
71
- `
72
- new ${componentName}({
73
- target: target(document.querySelector('[data-cayo-id="${cayoId}"]')),
74
- hydrate: true,
75
- props: getProps('${cayoId}'),
76
- });
77
- `
78
- );
79
- }
@@ -1,25 +0,0 @@
1
- <script>
2
- import * as crypto from 'crypto';
3
- // import { Boundary } from '@crownframework/svelte-error-boundary';
4
-
5
- export let name;
6
-
7
- // TODO: Consider error handling for required stuff
8
- // if (!name) throw new Error('No name for component');
9
- // try {
10
- // if (!name) throw new Error(`\x1b[31mCayo Component: 'name' prop is required and can't be an empty string`);
11
- // } catch (err) {
12
- // new Error(err);
13
- // }
14
-
15
- function hash() {
16
- return crypto.randomBytes(3).toString('hex');
17
- }
18
-
19
- const json = JSON.stringify($$restProps);
20
- </script>
21
-
22
- <div data-cayo-id={name ? `${name}-${hash()}` : ''} data-cayo-props={json}>
23
- <slot/>
24
- </div>
25
-
package/lib/config.js DELETED
@@ -1,155 +0,0 @@
1
- import path from 'path';
2
- import fs from 'fs-extra';
3
- import { z } from 'zod';
4
- import { normalizePath } from './utils.js';
5
- import { default as viteConfig } from './vite.config.js';
6
- import chalk from 'chalk';
7
- import merge from 'deepmerge';
8
-
9
- async function validateConfig(userConfig, base) {
10
- const ConfigSchema = z.object({
11
- projectRoot: z
12
- .string()
13
- .optional()
14
- .default('.')
15
- .transform(val => normalizePath(base, val)),
16
- src: z
17
- .string()
18
- .optional()
19
- .default('./src')
20
- .transform(val => normalizePath(base, val)),
21
- pages: z
22
- .string()
23
- .optional()
24
- .default('./src/pages')
25
- .transform(val => normalizePath(base, val)),
26
- publicDir: z
27
- .string()
28
- .optional()
29
- .default('./public')
30
- .transform(val => normalizePath(base, val)),
31
- base: z
32
- .string()
33
- .optional(),
34
- build: z
35
- .object({
36
- outDir: z
37
- .string()
38
- .optional()
39
- .default('./dist')
40
- .transform(val => normalizePath(base, val)),
41
- assetsDir: z
42
- .string()
43
- .optional()
44
- .default('assets'),
45
- // .transform(val => normalizePath(base, val)),
46
- legacy: z.
47
- boolean()
48
- .optional()
49
- .default(false),
50
- })
51
- .optional()
52
- .default({}),
53
- css: z
54
- .object({
55
- internal: z
56
- .boolean()
57
- .optional()
58
- .default(false),
59
- })
60
- .optional()
61
- .default({}),
62
- viteConfig: z
63
- .any({}),
64
- // .default(viteConfig),
65
- cayoPath: z
66
- .string()
67
- .optional()
68
- .default('.cayo/')
69
- .transform(val => normalizePath(base, val)),
70
- cayoComponentInfix: z
71
- .string()
72
- .optional()
73
- .default('cayo'),
74
- templateFileName: z
75
- .string()
76
- .default('__layout'),
77
- mode: z
78
- .string()
79
- .optional()
80
- .default('development'),
81
- });
82
-
83
- return await ConfigSchema.parseAsync(userConfig);
84
- }
85
-
86
- export function checkConfigPaths(config, logger) {
87
- let errorLogged = false;
88
- const log = (option, value) => {
89
- logger.warn(
90
- chalk.red(`Config Error: ${option}: '${value}' does not exist`),
91
- { timestamp: true, clear: false, }
92
- );
93
- errorLogged = true;
94
- }
95
- if (!fs.existsSync(config.projectRoot))
96
- log('config.projectRoot', config.projectRoot);
97
- if (!fs.existsSync(path.resolve(config.projectRoot, config.src)))
98
- log('config.src', config.projectRoot);
99
- if (!fs.existsSync(path.resolve(config.projectRoot, config.pages)))
100
- log('config.pages', config.pages);
101
- if (!fs.existsSync(path.resolve(config.projectRoot, config.publicDir)))
102
- log('config.publicDir', config.publicDir);
103
- if (!fs.existsSync(path.resolve(config.src, `${config.templateFileName}.svelte`)))
104
- log('config.templateFileName', `${config.templateFileName}(.svelte)`);
105
- if (!fs.existsSync(path.resolve(config.projectRoot, config.publicDir)))
106
- log('config.publicDir', config.publicDir);
107
-
108
- if(errorLogged) throw new Error('Config Error: fix the issues above in your config file');
109
- }
110
-
111
- export async function loadConfig(options) {
112
- const configFileName = 'cayo.config.js';
113
-
114
- // Use options passed to the CLI for projectRoot and configPath
115
- const root = options.projectRoot
116
- ? path.resolve(options.projectRoot)
117
- : process.cwd();
118
-
119
- const configPath = options.configPath
120
- ? path.resolve(root, options.configPath)
121
- : path.resolve(root, `./${configFileName}`);
122
-
123
- // Load config from user config file
124
- let userConfig = { projectRoot: root, mode: options.mode };
125
- if (fs.existsSync(configPath)) {
126
- userConfig = {
127
- ...(await import(configPath)).default,
128
- ...userConfig,
129
- };
130
- }
131
-
132
- const config = await validateConfig(userConfig, root);
133
- if (config.viteConfig) {
134
- const mergedViteConfig = merge(viteConfig, config.viteConfig, { arrayMerge: combineMerge });
135
- config.viteConfig = mergedViteConfig;
136
- }
137
-
138
- return config;
139
- }
140
-
141
- // Credit: https://github.com/TehShrike/deepmerge#arraymerge-example-combine-arrays
142
- function combineMerge(target, source, options) {
143
- const destination = target.slice()
144
-
145
- source.forEach((item, index) => {
146
- if (typeof destination[index] === 'undefined') {
147
- destination[index] = options.cloneUnlessOtherwiseSpecified(item, options)
148
- } else if (options.isMergeableObject(item)) {
149
- destination[index] = merge(target[index], item, options)
150
- } else if (target.indexOf(item) === -1) {
151
- destination.push(item)
152
- }
153
- })
154
- return destination
155
- }
package/lib/files.js DELETED
@@ -1,84 +0,0 @@
1
- import fs from 'fs-extra';
2
- import path from 'path';
3
- import chalk from 'chalk';
4
-
5
- // Write file content for a page
6
- export async function writePageFiles(page, outDir, logger, config) {
7
- const { html, css, js, entry } = page;
8
- const htmlPath = page.urlPath === '/' ? 'index.html' : `${page.filePath}/index.html`;
9
- // Write HTML
10
- await fs.outputFile(path.resolve(outDir, `${htmlPath}`), html)
11
- .then(() => logger.info(
12
- chalk.green('page build ') + chalk.dim(`${page.filePath}`),
13
- { timestamp: true })
14
- );
15
- // Write CSS
16
- if (css.code !== '' && !config.css.internal) {
17
- const cssPath = page.urlPath === '/' ? 'index.css' : `${page.filePath}/index.css`;
18
- await fs.outputFile(path.resolve(outDir, cssPath), css)
19
- .then(() => logger.info(
20
- chalk.green('css build ') + chalk.dim(`${page.filePath}`),
21
- { timestamp: true })
22
- );
23
- }
24
- // Write Cayo runtime JS
25
- if (js.code !== '') {
26
- let jsPath = page.urlPath === '/' ? 'cayo-runtime.js' : `${page.filePath}/cayo-runtime.js`;
27
- let content = '';
28
- content += js.code;
29
- await fs.outputFile(path.resolve(outDir, jsPath), content)
30
- .then(() => logger.info(
31
- chalk.green('cayo runtime build ') + chalk.dim(`${page.filePath}`),
32
- { timestamp: true })
33
- );
34
- }
35
-
36
- // Copy user entry JS
37
- if (entry.path !== '') {
38
- let entryRelativePath = page.urlPath === '/' ? `./index.js` : `${page.filePath}${path.sep}index.js`;
39
- await fs.copy(entry.path, path.resolve(outDir, entryRelativePath))
40
- .then(() => logger.info(
41
- chalk.green('entry build ') + chalk.dim(`${page.filePath}`),
42
- { timestamp: true })
43
- ).catch(err => console.error(err));
44
- }
45
- }
46
-
47
- export async function writeTemplateCSS(css, outDir, logger, config) {
48
- if (css.code !== '' && !config.css.internal) {
49
- const cssPath = `__index.css`;
50
- await fs.outputFile(path.resolve(outDir, cssPath), css.code)
51
- .then(() => logger.info(
52
- chalk.green('css build ') + chalk.dim(`${config.templateFileName}`),
53
- { timestamp: true })
54
- );
55
- }
56
- }
57
-
58
- export async function writeComponentFile(name, modulePath, outDir, logger) {
59
- let content = `export { default as ${name} } from '${modulePath}';\n`;
60
- await fs.outputFile(path.resolve(outDir, `./__cayo/components/${name}.js`), content)
61
- .then(() => logger.info(
62
- chalk.green('component dep ') + chalk.dim(`${name}`),
63
- { timestamp: true })
64
- );
65
- }
66
-
67
- export function cleanCayoPath(cayoPath) {
68
- fs.removeSync(cayoPath);
69
- fs.ensureDirSync(cayoPath);
70
- // if (!fs.existsSync(cayoPath)) {
71
- // try {
72
- // fs.mkdirSync(cayoPath)
73
- // } catch (err) {
74
- // console.error(err);
75
- // }
76
- // } else {
77
- // try {
78
- // fs.removeSync(cayoPath)
79
- // fs.mkdirSync(cayoPath);
80
- // } catch (err) {
81
- // console.error(err);
82
- // }
83
- // }
84
- }
package/lib/prerender.js DELETED
@@ -1,181 +0,0 @@
1
- import fs from 'fs-extra';
2
- import path from 'path';
3
- import { JSDOM } from 'jsdom';
4
- import { Renderer } from './renderer.js';
5
- import { generateCayoRuntime } from './codegen.js';
6
- import chalk from 'chalk';
7
-
8
- export function prerender(Template, pages, componentModules, config, logger) {
9
- const template = Template.render();
10
- const renderer = new Renderer(template);
11
- const componentList = new Set();
12
-
13
- // const prerendered = {};
14
- // Render page, parse html, and save its deps
15
- const prerendered = Object.entries(pages).reduce(
16
- (prerendered, [pathname, page]) => {
17
- // Render page
18
- const content = renderer.render(page, config);
19
- // Postprocess the content, get deps and inject dep references
20
- const { html, css, js, entry, components } = processPage(content, page, Object.keys(componentModules), config, logger);
21
- prerendered[pathname] = {
22
- html,
23
- css,
24
- js,
25
- entry,
26
- components,
27
- ...page,
28
- }
29
- Object.keys(components).forEach(component => componentList.add(component))
30
- return prerendered;
31
- }, {}
32
- );
33
-
34
- return {
35
- prerendered,
36
- componentList,
37
- template,
38
- }
39
- }
40
-
41
- // Derive JS dependencies from the prerendered html
42
- export function processPage(content, page, componentNames, config, logger) {
43
- const tags = findDocumentTags(content.html);
44
- const dom = new JSDOM(content.html);
45
- const { document } = dom.window;
46
-
47
- // Get component instance ids
48
- let cayoIds = [];
49
- document.querySelectorAll('[data-cayo-id]').forEach((el) => {
50
- if (el.dataset.cayoId !== '') {
51
- cayoIds.push(el.dataset.cayoId);
52
- } else {
53
- logger.info(
54
- chalk.red(`Cayo component instance without a name found`) + chalk.dim(` ${page.filePath}`),
55
- { timestamp: true, clear: true, }
56
- );
57
- }
58
- });
59
-
60
- // Get component list
61
- // TODO: make this regex allow '-' character, before the last one, to be part of the component name?
62
- const componentNameRegex = /(?<name>\w+)-/; // Foo-{hash}
63
- const components = cayoIds.reduce((components, id) => {
64
- let name = id.match(componentNameRegex).groups.name;
65
- if (!componentNames.includes(name)) {
66
- logger.warn(
67
- chalk.red(
68
- `Cayo component with name '${name}' does not exist but is trying to be rendered`
69
- ) + chalk.dim(` ${page.filePath}`),
70
- { timestamp: true, clear: true, }
71
- );
72
- return components;
73
- }
74
-
75
- if (!components[name]) {
76
- components[name] = [id]
77
- } else {
78
- components[name].push(id);
79
- }
80
- return components;
81
- }, {});
82
-
83
- // Get user-specified entry file name
84
- // TODO: can just be querySelector? should only be one instance. maybe warn if more than one.
85
- const entryScripts = document.querySelectorAll('script[data-cayo-entry]');
86
- let userEntryFile = entryScripts.length !== 0 ? entryScripts[0].src : '';
87
- // Remove user-specified entry file placeholder
88
- if (userEntryFile) {
89
- entryScripts.forEach((script) => {
90
- script.remove();
91
- });
92
- }
93
-
94
- // Build generated entry file contents
95
- let js = { code: '' };
96
- let entry = {
97
- path: '',
98
- }
99
-
100
- if (!userEntryFile) {
101
- // Remove the entry point script tag if the page doesn't need any JS
102
- // This is injected by Renderer.render based on the template
103
- const entryScript = document.querySelector(`script[type="module"][src="./index.js"]`);
104
- if (entryScript) {
105
- entryScript.remove();
106
- } else {
107
- logger.info(
108
- chalk.bgRed.white(`No entry placeholder in template file.`) + chalk.dim(` Cayo components will not render.`),
109
- { timestamp: true }
110
- );
111
- }
112
- }
113
-
114
- if (userEntryFile[0] === '/') {
115
- userEntryFile = userEntryFile.substring(1);
116
- } else if (userEntryFile && userEntryFile[0] !== '/') {
117
- logger.warn(
118
- chalk.red(
119
- `Entry file path '${userEntryFile}' requires a leading slash and to be relative to src`
120
- ) + chalk.dim(` ${page.filePath}`),
121
- { timestamp: true, clear: true, }
122
- );
123
- }
124
-
125
- if (userEntryFile) {
126
- const entryFilePath = path.resolve(
127
- config.src,
128
- userEntryFile
129
- );
130
-
131
- if (!fs.pathExistsSync(entryFilePath)) {
132
- console.error(`Can't read entry file ${userEntryFile} in ${page.modulePath}`);
133
- } else {
134
- entry.path = entryFilePath;
135
- }
136
- }
137
-
138
- js = generateCayoRuntime(components, config);
139
-
140
- // Construct the correct HTML string based on the document tags
141
- // that were rendered from the source (jsdom wraps the source HTML in a document,
142
- // which always includes `html`, `head`, and `body`, even if the source doesn't)
143
- let processedHTML = '';
144
- if (tags.html) {
145
- processedHTML = dom.window.document.documentElement.outerHTML;
146
-
147
- } else {
148
- if (tags.head) {
149
- processedHTML += dom.window.document.head.outerHTML;
150
- } else {
151
- processedHTML += dom.window.document.head.innerHTML;
152
- }
153
-
154
- if (tags.body) {
155
- processedHTML += dom.window.document.body.outerHTML;
156
- } else {
157
- processedHTML += dom.window.document.body.innerHTML;
158
- }
159
- }
160
-
161
- return {
162
- html: processedHTML,
163
- css: content.css.code,
164
- js,
165
- components,
166
- entry,
167
- };
168
- }
169
-
170
-
171
- function findDocumentTags(source) {
172
- const head = source.match(/\<head[\s\S]*\>(?<innerHTML>[\s\S]*)\<\/head\>/g);
173
- const body = source.match(/\<body[\s\S]*\>(?<innerHTML>[\s\S]*)\<\/body\>/g);
174
- const html = source.match(/\<html[\s\S]*\>(?<innerHTML>[\s\S]*)\<\/html\>/g);
175
-
176
- return {
177
- head: head === null ? false : true,
178
- body: body === null ? false : true,
179
- html: html === null ? false : true,
180
- };
181
- }