cayo 0.9.9 → 0.9.11

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 (121) 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.json +7 -0
  38. package/template/public/vite.svg +1 -0
  39. package/{tests/basic cases (old)/src/__index.svelte → template/src/__template.svelte} +3 -6
  40. package/template/src/components/counter.cayo.svelte +27 -0
  41. package/template/src/index.js +4 -0
  42. package/template/src/pages/index.svelte +15 -0
  43. package/template/src/style.css +13 -0
  44. package/lib/cli.js +0 -69
  45. package/lib/codegen.js +0 -79
  46. package/lib/components/Cayo.svelte +0 -25
  47. package/lib/config.js +0 -155
  48. package/lib/files.js +0 -84
  49. package/lib/prerender.js +0 -181
  50. package/lib/renderer.js +0 -49
  51. package/lib/runtime.js +0 -6
  52. package/lib/utils.js +0 -126
  53. package/lib/vite.config.js +0 -16
  54. package/notes.md +0 -3
  55. package/test/cayo.config.js +0 -35
  56. package/test/public/assets/cow.js +0 -1
  57. package/test/public/images/app-icon.png +0 -0
  58. package/test/src/__layout.svelte +0 -20
  59. package/test/src/components/Cool.cayo.svelte +0 -5
  60. package/test/src/components/Some.svelte +0 -1
  61. package/test/src/components/Test.cayo.svelte +0 -5
  62. package/test/src/index.js +0 -17
  63. package/test/src/main2.js +0 -1
  64. package/test/src/pages/hey.svelte +0 -8
  65. package/test/src/pages/howdy.svelte +0 -11
  66. package/test/src/pages/index.svelte +0 -38
  67. package/test/src/pages/some/page.svelte +0 -2
  68. package/tests/asset-dir/cayo.config.js +0 -38
  69. package/tests/asset-dir/package-lock.json +0 -1435
  70. package/tests/asset-dir/package.json +0 -19
  71. package/tests/asset-dir/public/images/app-icon.png +0 -0
  72. package/tests/asset-dir/src/__layout.svelte +0 -20
  73. package/tests/asset-dir/src/components/CayoExample.svelte +0 -5
  74. package/tests/asset-dir/src/components/Some.cayo.svelte +0 -6
  75. package/tests/asset-dir/src/index.js +0 -5
  76. package/tests/asset-dir/src/pages/index.svelte +0 -19
  77. package/tests/base-path/cayo.config.js +0 -36
  78. package/tests/base-path/package-lock.json +0 -1435
  79. package/tests/base-path/package.json +0 -19
  80. package/tests/base-path/public/assets/cow.js +0 -1
  81. package/tests/base-path/public/images/app-icon.png +0 -0
  82. package/tests/base-path/src/__layout.svelte +0 -20
  83. package/tests/base-path/src/components/CayoExample.svelte +0 -5
  84. package/tests/base-path/src/components/Some.cayo.svelte +0 -6
  85. package/tests/base-path/src/index.js +0 -5
  86. package/tests/base-path/src/pages/howdy.svelte +0 -12
  87. package/tests/base-path/src/pages/index.svelte +0 -20
  88. package/tests/basic/notcayo.config.js +0 -35
  89. package/tests/basic/package-lock.json +0 -1435
  90. package/tests/basic/package.json +0 -19
  91. package/tests/basic/public/assets/cow.js +0 -1
  92. package/tests/basic/public/images/app-icon.png +0 -0
  93. package/tests/basic/src/__layout.svelte +0 -20
  94. package/tests/basic/src/components/Cool.cayo.svelte +0 -4
  95. package/tests/basic/src/components/Some.svelte +0 -1
  96. package/tests/basic/src/index.js +0 -5
  97. package/tests/basic/src/main2.js +0 -1
  98. package/tests/basic/src/pages/hey.svelte +0 -8
  99. package/tests/basic/src/pages/howdy.svelte +0 -11
  100. package/tests/basic/src/pages/index.svelte +0 -33
  101. package/tests/basic/src/pages/some/some.svelte +0 -2
  102. package/tests/basic cases (old)/src/components/Cool.cayo.svelte +0 -4
  103. package/tests/basic cases (old)/src/components/Some.svelte +0 -1
  104. package/tests/basic cases (old)/src/components/dir/Cool.cayo.svelte +0 -4
  105. package/tests/basic cases (old)/src/main.js +0 -1
  106. package/tests/basic cases (old)/src/main2.js +0 -1
  107. package/tests/basic cases (old)/src/pages/hey.svelte +0 -2
  108. package/tests/basic cases (old)/src/pages/howdy.svelte +0 -11
  109. package/tests/basic cases (old)/src/pages/index.svelte +0 -27
  110. package/tests/nested-pages/cayo.config.js +0 -35
  111. package/tests/nested-pages/package-lock.json +0 -1435
  112. package/tests/nested-pages/package.json +0 -19
  113. package/tests/nested-pages/public/assets/cow.js +0 -1
  114. package/tests/nested-pages/public/images/app-icon.png +0 -0
  115. package/tests/nested-pages/src/__layout.svelte +0 -20
  116. package/tests/nested-pages/src/components/Cool.cayo.svelte +0 -4
  117. package/tests/nested-pages/src/index.js +0 -5
  118. package/tests/nested-pages/src/main2.js +0 -1
  119. package/tests/nested-pages/src/pages/index.svelte +0 -18
  120. package/tests/nested-pages/src/pages/some/other/page.svelte +0 -7
  121. package/tests/nested-pages/src/pages/some/page.svelte +0 -6
@@ -0,0 +1,240 @@
1
+ import fs from 'fs-extra';
2
+ import path from 'path';
3
+ import { JSDOM } from 'jsdom';
4
+ import { Renderer } from './renderer.js';
5
+ import { compileCayos } from '../compile/cayos.js';
6
+ import { generateCayoRuntime, generateRuntimeIssuesScript } from '../codegen.js';
7
+ import { generateCayoComponentId } from '../utils.js';
8
+ import logger from '../logger.js';
9
+
10
+ export async function prerender(page, _cayo) {
11
+ const renderer = new Renderer(page.layout);
12
+ const componentList = new Set();
13
+
14
+ const content = await renderer.render(page, _cayo.config);
15
+ // Postprocess the content, get deps and inject dep references
16
+ const processed = await processPage(
17
+ content,
18
+ page,
19
+ _cayo,
20
+ logger
21
+ );
22
+
23
+ const { cayoInstances } = processed;
24
+
25
+ Object.keys(cayoInstances).forEach(component => componentList.add(component))
26
+
27
+ return {
28
+ ...processed,
29
+ components: [...componentList],
30
+ }
31
+ }
32
+
33
+ // Derive JS dependencies from the prerendered html
34
+ export async function processPage(content, page, _cayo, logger) {
35
+ const { config } = _cayo;
36
+ // JSDOM Initialization
37
+ const dom = new JSDOM(content.html);
38
+ const { document } = dom.window;
39
+ // For storing issues while we process the page
40
+ const warnings = {
41
+ cayos: {},
42
+ page: {},
43
+ };
44
+ const errors = {
45
+ cayos: {},
46
+ page: {},
47
+ };
48
+ // For generated file contents
49
+ let js = { code: '' };
50
+ let entry = { path: '' };
51
+ // Get component instance info
52
+ const cayoIds = [];
53
+ const cayoInstances = {};
54
+ const cayoAssets = {};
55
+ // Find all cayo instances in the markup
56
+ for (const el of document.querySelectorAll('[data-cayo-src]')) {
57
+ let src = el.dataset.cayoSrc;
58
+ if (src !== '') {
59
+ const { id, name } = generateCayoComponentId(src);
60
+ cayoIds.push(id);
61
+ el.dataset.cayoId = id;
62
+
63
+ // Get warnings added by the Cayo component during compile time
64
+ if (el.dataset.cayoWarn && el.dataset.cayoWarn !== '{}') {
65
+ warnings.cayos[id] = JSON.parse(el.dataset.cayoWarn);
66
+ }
67
+
68
+ // Add cayos to stats for dependency handling
69
+ let absoluteSrc = path.resolve(config.components, src);
70
+ if (_cayo.stats.cayoComponents[name]) {
71
+ _cayo.stats.cayoComponents[name].src = absoluteSrc;
72
+ _cayo.stats.cayoComponents[name].pages.add(page.sourcePath);
73
+ } else {
74
+ _cayo.stats.cayoComponents[name] = {
75
+ src: absoluteSrc,
76
+ pages: new Set([page.sourcePath]),
77
+ };
78
+ }
79
+ _cayo.stats.dependencies.pages[page.sourcePath].add(absoluteSrc);
80
+
81
+ // Compile cayos & keep track of them for this page
82
+ const [cayo] = await compileCayos({ [name]: _cayo.stats.cayoComponents[name] }, _cayo);
83
+ // Store references of each cayo instance on the page
84
+ if (cayoInstances[name]) {
85
+ cayoInstances[name].push(id);
86
+ } else {
87
+ cayoInstances[name] = [id];
88
+ }
89
+ // Include the assets needed by a cayo
90
+ // CSS is the only thing currently output other than the component JS
91
+ if (cayo && !cayoAssets[name]) {
92
+ cayoAssets[name] = {
93
+ css: {
94
+ code: cayo.output.css.code
95
+ }
96
+ };
97
+ }
98
+
99
+ } else {
100
+ // At least one error will be reported if the src is invalid
101
+ if (el.dataset.cayoWarn) {
102
+ warnings.cayos['undefined'] = JSON.parse(el.dataset.cayoWarn);
103
+ }
104
+ }
105
+ // Clean up data attributes we don't need during runtime
106
+ delete el.dataset.cayoSrc;
107
+ delete el.dataset.cayoWarn;
108
+ }
109
+
110
+ let cayoAssetCssElements = '';
111
+ for (const [name, cayo] of Object.entries(cayoAssets)) {
112
+ if (cayo.css.code !== '') {
113
+ cayoAssetCssElements += config.css.internal
114
+ ? `<style>/* ${name} CSS */${cayo.css.code}</style>\n`
115
+ : `<link rel="stylesheet" href="/${name}.css">\n`
116
+ }
117
+ }
118
+ const cayoAssetsCssMarker = document.querySelector('link[data-cayo-assets-css]');
119
+ cayoAssetsCssMarker.outerHTML = cayoAssetCssElements;
120
+
121
+ // Get user-specified entry placeholder
122
+ const entryScriptPlaceholder = document.querySelector('script[data-cayo-entry]');
123
+ let entryScriptSrc = entryScriptPlaceholder ? entryScriptPlaceholder.src : '';
124
+ // This is injected by Renderer.render based on the template
125
+ const entryScript = document.querySelector(`script[type="module"][src="./index.js"]`);
126
+
127
+ if (entryScriptSrc) {
128
+ // Remove user-specified entry file placeholder
129
+ entryScriptPlaceholder.remove();
130
+ // Validate the file path
131
+ const absoluteEntrySrcPath = path.resolve(config.src, entryScriptSrc);
132
+ if (!fs.pathExistsSync(absoluteEntrySrcPath)) {
133
+ let relativePath = entryScriptSrc.replace(config.projectRoot, '');
134
+ errors.page.entryFileDoesNotExist = {
135
+ title: `Bad entry file`,
136
+ src: page.sourcePath.replace(config.pages, ''),
137
+ message: `Entry file '${relativePath}' does not exist.`,
138
+ log: `Entry file '${entryScriptSrc}' does not exist.`,
139
+ }
140
+ // Remove the entry file script because the file doesn't exist
141
+ entryScript.remove();
142
+ } else {
143
+ entry.path = absoluteEntrySrcPath;
144
+ _cayo.stats.dependencies.pages[page.sourcePath].add(absoluteEntrySrcPath);
145
+ }
146
+ } else {
147
+ if (cayoIds.length > 0) {
148
+ let message = 'An entry file is required in order to render Cayos on the page.'
149
+ warnings.page.noEntryFile = {
150
+ title: `No entry file`,
151
+ src: page.sourcePath.replace(config.pages, ''),
152
+ message: message,
153
+ log: `No entry file found. ${message}`,
154
+ }
155
+ } else {
156
+ // Remove the entry point script tag because the page doesn't need any JS
157
+ entryScript.remove();
158
+ }
159
+ }
160
+
161
+ // Generate JS for cayos to run in the browser as needed
162
+ const cayoRuntimePath = page.url === '/' ? `/index.js` : `${page.url}/index.js`;
163
+ js = generateCayoRuntime(cayoInstances, cayoRuntimePath, _cayo);
164
+
165
+ // Indicate that we need to make this entry ready to render cayos later,
166
+ // if there are cayo instances on this page
167
+ if (cayoIds.length > 0) {
168
+ entry.renderCayos = true;
169
+ }
170
+
171
+ // Append runtime warnings
172
+ const {
173
+ script: warningScript,
174
+ logs: warningLogs
175
+ } = generateRuntimeIssuesScript({ config, document, page }, warnings, 'warning');
176
+ if (config.mode === 'development') {
177
+ document.body.appendChild(warningScript);
178
+ }
179
+ // Append runtime errors
180
+ const {
181
+ script: errorScript,
182
+ logs: errorLogs,
183
+ } = generateRuntimeIssuesScript({ config, document, page }, errors, 'error');
184
+ if (config.mode === 'development') {
185
+ document.body.appendChild(errorScript);;
186
+ }
187
+ // Log any runtime warnings and errors
188
+ for (const message of [...warningLogs, ...errorLogs]) {
189
+ logger.log.info(
190
+ message,
191
+ { timestamp: true, clear: false, }
192
+ );
193
+ }
194
+
195
+ // Construct the correct HTML string based on the document structure
196
+ // that was rendered from the source (jsdom wraps the source HTML in a document,
197
+ // which always includes `html`, `head`, and `body`, even if the source doesn't)
198
+ const tags = tagsExist(content.html);
199
+ let processedHTML = '';
200
+ if (tags.doctype) {
201
+ processedHTML += tags.doctype;
202
+ }
203
+ if (tags.html) {
204
+ processedHTML += document.documentElement.outerHTML;
205
+ } else {
206
+ if (tags.head) {
207
+ processedHTML += document.head.outerHTML;
208
+ } else {
209
+ processedHTML += document.head.innerHTML;
210
+ }
211
+
212
+ if (tags.body) {
213
+ processedHTML += document.body.outerHTML;
214
+ } else {
215
+ processedHTML += document.body.innerHTML;
216
+ }
217
+ }
218
+
219
+ return {
220
+ html: processedHTML,
221
+ css: content.css.code,
222
+ js,
223
+ cayoInstances,
224
+ cayoAssets,
225
+ entry,
226
+ };
227
+ }
228
+
229
+ function tagsExist(source) {
230
+ const doctype = source.match(/\<!DOCTYPE\s\w*\>/g);
231
+ const head = source.match(/\<head[\s\S]*\>(?<innerHTML>[\s\S]*)\<\/head\>/g);
232
+ const body = source.match(/\<body[\s\S]*\>(?<innerHTML>[\s\S]*)\<\/body\>/g);
233
+ const html = source.match(/\<html[\s\S]*\>(?<innerHTML>[\s\S]*)\<\/html\>/g);
234
+ return {
235
+ doctype: doctype === null ? false : doctype,
236
+ head: head === null ? false : true,
237
+ body: body === null ? false : true,
238
+ html: html === null ? false : true,
239
+ };
240
+ }
@@ -0,0 +1,52 @@
1
+ export class Renderer {
2
+
3
+ constructor(template) {
4
+ this.template = template;
5
+ }
6
+
7
+ async render(page, config) {
8
+ const { css: cssOptions } = config;
9
+ const Component = await page.load();
10
+ const res = Component.render();
11
+ const { html, css, head } = res;
12
+
13
+ let cssElements = '';
14
+ if (cssOptions.internal === false) {
15
+ if (this.template.css && this.template.css.code !== '') {
16
+ cssElements += `<link rel="stylesheet" href="/__index.css">\n`;
17
+ }
18
+ cssElements += `<link rel="stylesheet" href="./index.css">`;
19
+
20
+ } else {
21
+ if (this.template.css && this.template.css.code !== '') {
22
+ cssElements += `<style>/* Template CSS */${this.template.css.code}</style>\n`;
23
+ }
24
+ cssElements += `<style>${css.code}</style>`;
25
+ }
26
+
27
+ cssElements += '\n<link data-cayo-assets-css>';
28
+
29
+ const title = () => {
30
+ let title = page.name;
31
+ title = title.charAt(0).toUpperCase() + title.substring(1);
32
+ return `<title>${title}</title>`
33
+ }
34
+
35
+ // Note: Q: why the `() => str` for 2nd replacement arg?
36
+ // A: In case there's dollar signs in that there string
37
+ // https://stackoverflow.com/questions/9423722/string-replace-weird-behavior-when-using-dollar-sign-as-replacement
38
+ return {
39
+ html: this.template.html
40
+ // FIXME#83: this regex is bad; accidentally removes elements like head
41
+ // Ignore placeholders wrapped in HTML comments
42
+ // .replace(/<!--[^]*\%cayo\.\w+\%[^]*-->/g, '')
43
+ .replace('%cayo.title%', () => !head.includes('<title>') ? title() : '')
44
+ .replace('%cayo.head%', () => head)
45
+ .replace('%cayo.body%', () => html)
46
+ .replace('%cayo.css%', () => cssElements)
47
+ // Vite needs the entry file in this format
48
+ .replace('%cayo.script%', () => `<script type="module" src="./index.js"></script>`),
49
+ css,
50
+ }
51
+ }
52
+ }
@@ -0,0 +1,60 @@
1
+ import path from 'path';
2
+ import crypto from 'crypto';
3
+ import fs from 'fs-extra';
4
+
5
+ // https://github.com/sveltejs/svelte/blob/master/src/compiler/compile/utils/hash.ts
6
+ export function hash(str = '', bytes = 5) {
7
+ const random = crypto.randomBytes(bytes).toString('hex');
8
+ str += random;
9
+
10
+ str = str.replace(/\r/g, '');
11
+ let hash = 5381;
12
+ let i = str.length;
13
+
14
+ while (i--) hash = ((hash << bytes) - hash) ^ str.charCodeAt(i);
15
+ return (hash >>> 0).toString(36);
16
+ }
17
+
18
+ export function generateSafeName(inputPath) {
19
+ return inputPath
20
+ .replace(/^\.\//g, '')
21
+ .replace(/\/+/g, '__')
22
+ .replace(/\-+/g, '_');
23
+ }
24
+
25
+ export function generateCayoComponentId(componentPath) {
26
+ const name = generateSafeName(componentPath)
27
+ .replace('.cayo.svelte', '');
28
+
29
+ const id = `${name}-${hash(name)}`;
30
+
31
+ return {
32
+ id,
33
+ name,
34
+ };
35
+ }
36
+
37
+ // Credit: https://github.com/snowpackjs/astro
38
+ /** Add / to the end of string (but don’t double-up) */
39
+ export function addTrailingSlash(_path) {
40
+ return _path.replace(/\/?$/, '/');
41
+ }
42
+
43
+ export function normalizePath(root, _path) {
44
+ if (root === _path) return root;
45
+ return path.normalize(path.join(root, addTrailingSlash(_path)));
46
+ }
47
+
48
+ // TODO: need to use this somewhere?
49
+ export function getOutDir(config) {
50
+ return config.mode === 'production' ? config.buildOptions.outDir : config.cayoPath;
51
+ }
52
+
53
+ export async function debugStats(_cayo) {
54
+ const { stats, config } = _cayo;
55
+ fs.outputFile(path.resolve(config.cayoPath, './__cayo/stats.json'), JSON.stringify(
56
+ stats,
57
+ (key, value) => value instanceof Set ? [...value] : value,
58
+ 2
59
+ ));
60
+ }
package/package.json CHANGED
@@ -1,13 +1,24 @@
1
1
  {
2
2
  "name": "cayo",
3
- "version": "0.9.9",
3
+ "version": "0.9.11",
4
4
  "type": "module",
5
5
  "scripts": {
6
- "start": "node cayo dev --projectRoot test"
6
+ "start": "node cayo dev --projectRoot test",
7
+ "build": "node scripts/build"
8
+ },
9
+ "imports": {
10
+ "#core/*": "./lib/core/*"
7
11
  },
8
12
  "bin": {
9
13
  "cayo": "cayo.js"
10
14
  },
15
+ "svelte": "./dist/index.js",
16
+ "exports": {
17
+ ".": {
18
+ "default": "./dist/index.js"
19
+ },
20
+ "./package.json": "./package.json"
21
+ },
11
22
  "repository": {
12
23
  "type": "git",
13
24
  "url": "git+https://github.com/matthew-ia/cayo.git"
@@ -18,21 +29,21 @@
18
29
  "url": "https://github.com/matthew-ia/cayo/issues"
19
30
  },
20
31
  "homepage": "https://github.com/matthew-ia/cayo#readme",
21
- "devDependencies": {
22
- "@vitejs/plugin-legacy": "^1.6.2"
23
- },
24
32
  "dependencies": {
25
- "@sveltejs/vite-plugin-svelte": "^1.0.0-next.11",
33
+ "@rollup/plugin-json": "^4.1.0",
26
34
  "chalk": "^2.4.2",
27
35
  "chokidar": "^3.5.2",
28
36
  "deepmerge": "^4.2.2",
29
37
  "fast-glob": "^3.2.7",
30
38
  "fs-extra": "^10.0.0",
31
39
  "jsdom": "^18.0.0",
32
- "linkedom": "^0.13.0",
33
- "svelte": "^3.37.0",
34
- "svelte-preprocess": "^4.7.4",
35
- "vite": "^2.6.4",
40
+ "precinct": "^9.0.0",
41
+ "prettier": "^2.7.1",
42
+ "rollup": "^2.70.1",
43
+ "rollup-plugin-import-css": "^3.0.3",
44
+ "rollup-plugin-svelte": "^7.1.0",
45
+ "svelte": "^3.49.0",
46
+ "vite": "^3.1.2",
36
47
  "yargs-parser": "^20.2.9",
37
48
  "zod": "^3.10.3"
38
49
  }
@@ -0,0 +1,60 @@
1
+ #!/usr/bin/env node
2
+
3
+ // Build
4
+ // - Compile Svelte components to JS
5
+ // - Generate an index file for these components to be
6
+ // used as the Cayo package's exports
7
+
8
+ import fs from 'fs-extra';
9
+ import { validateConfig } from '../lib/core/config.js';
10
+ import { build } from '../lib/core/bundle.js';
11
+ import logger from '../lib/core/logger.js';
12
+ import chalk from 'chalk';
13
+ import path from 'path';
14
+
15
+ async function compileComponents(components, config) {
16
+ const output = {};
17
+ for (const component of components) {
18
+ try {
19
+ const inputPath = path.resolve(`./src/${component}.svelte`);
20
+ const outputPath = path.resolve(`./dist/${component}.svelte.js`);
21
+ const { js } = await build(inputPath, config);
22
+ await fs.outputFile(outputPath, js.code);
23
+ output[component] = { path: `./${component}.svelte.js` }
24
+ console.log(chalk.green.bold(`Compiled ${component}.svelte → ${component}.svelte.js`));
25
+ console.log(chalk.dim(`./dist/${component}.svelte.js`));
26
+ } catch (err) {
27
+ throw new Error(`Cayo Internal Error: Could not compile ./src/${component}.svelte`, { cause: err });
28
+ }
29
+ }
30
+
31
+ return output;
32
+ }
33
+
34
+ function generateIndex(modules) {
35
+ let js = '';
36
+ for (const m of modules) {
37
+ js += `export { default as ${m[0]} } from '${m[1]}';\n`;
38
+ }
39
+ return { code: js };
40
+ }
41
+
42
+ try {
43
+ const cayoConfig = await validateConfig({});
44
+ const output = await compileComponents(['cayo', 'entry'], cayoConfig);
45
+ const index = generateIndex([
46
+ // Tuples of modules to import in the index file
47
+ ['Cayo', output.cayo.path],
48
+ ['Entry', output.entry.path],
49
+ ]);
50
+ await fs.outputFile('./dist/index.js', index.code)
51
+ .then(() => {
52
+ console.log(chalk.green.bold(`✅ Components built.`));
53
+ console.log(chalk.dim(`./dist/index.js`));
54
+ });
55
+
56
+ } catch (err) {
57
+ logger.error(err);
58
+ console.error(err.stack);
59
+ process.exit(1);
60
+ }
@@ -0,0 +1,37 @@
1
+ export function getWarnings(src, badProps) {
2
+ const warnings = {};
3
+ checkInvalidSrc(warnings, src);
4
+ checkBadProps(warnings, src, badProps);
5
+ return warnings;
6
+ }
7
+
8
+ // Warning: invalid src prop')
9
+ function checkInvalidSrc(warnings, src) {
10
+ if (!src || typeof src !== 'string') {
11
+ warnings.invalidSrc = {
12
+ title: `Invalid src prop`,
13
+ src: !src ? 'undefined' : typeof src,
14
+ message: `The src prop is required and must be a string.`,
15
+ log: `Use of <Cayo> without a src prop found. No cayo instance will be rendered.`,
16
+ }
17
+ }
18
+ }
19
+
20
+ // Warning: unserializable props
21
+ function checkBadProps(warnings, src, keys) {
22
+ if (keys.length > 0) {
23
+ let propsStr = '';
24
+ for (let i = 0; i < keys.length; i++) {
25
+ propsStr += `'${keys[i]}'`;
26
+ if (i+1 < keys.length) {
27
+ propsStr += `, `;
28
+ }
29
+ }
30
+ warnings.badProps = {
31
+ title: `Bad props`,
32
+ src,
33
+ message: `Unserializable props found: ${propsStr}. Cayo component props must be serializable in order to be used for hydration.`,
34
+ log: `Unserializable instance props found: ${propsStr}.`,
35
+ }
36
+ }
37
+ }
@@ -0,0 +1,36 @@
1
+ <script>
2
+ export let src;
3
+ import { getWarnings } from './cayo-warnings.js';
4
+
5
+ // Save unserializable prop keys (during stringification)
6
+ // so we can report them later
7
+ const badProps = [];
8
+ function replacer(key, value) {
9
+ const type = typeof value;
10
+ if (
11
+ type === 'function' ||
12
+ type === 'undefined' ||
13
+ type === 'symbol'
14
+ ) {
15
+ badProps.push(key);
16
+ }
17
+
18
+ return value;
19
+ };
20
+
21
+ const json = JSON.stringify({...$$restProps}, replacer);
22
+ const warnings = getWarnings(src, badProps);
23
+ const cayoInstanceData = {
24
+ 'data-cayo-id': '',
25
+ 'data-cayo-src': !warnings.invalidSrc ? `${src}` : '',
26
+ 'data-cayo-props': json,
27
+ };
28
+ if (warnings) {
29
+ cayoInstanceData['data-cayo-warn'] = JSON.stringify(warnings);
30
+ }
31
+
32
+ </script>
33
+
34
+ <div {...cayoInstanceData}>
35
+ <slot/>
36
+ </div>
@@ -0,0 +1,6 @@
1
+ <script>
2
+ export let src;
3
+ </script>
4
+ <slot>
5
+ <script src="{src}" data-cayo-entry />
6
+ </slot>
@@ -0,0 +1,3 @@
1
+ export default {
2
+ // options...
3
+ }
@@ -0,0 +1,7 @@
1
+ {
2
+ "type": "module",
3
+ "scripts": {
4
+ "dev": "cayo dev",
5
+ "build": "cayo build"
6
+ }
7
+ }
@@ -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
+ }