cayo 0.9.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.
- package/LICENSE.md +21 -0
- package/README.md +6 -0
- package/cayo.js +295 -0
- package/jsconfig.json.txt +34 -0
- package/lib/cli.js +69 -0
- package/lib/codegen.js +77 -0
- package/lib/components/Cayo.svelte +24 -0
- package/lib/config.js +155 -0
- package/lib/files.js +84 -0
- package/lib/prerender.js +181 -0
- package/lib/renderer.js +45 -0
- package/lib/runtime.js +6 -0
- package/lib/utils.js +120 -0
- package/lib/vite.config.js +16 -0
- package/notes.md +3 -0
- package/package.json +39 -0
- package/test/cayo.config.js +35 -0
- package/test/public/assets/cow.js +1 -0
- package/test/public/images/app-icon.png +0 -0
- package/test/src/__layout.svelte +20 -0
- package/test/src/components/Cool.cayo.svelte +4 -0
- package/test/src/components/Some.svelte +1 -0
- package/test/src/index.js +5 -0
- package/test/src/main2.js +1 -0
- package/test/src/pages/hey.svelte +8 -0
- package/test/src/pages/howdy.svelte +11 -0
- package/test/src/pages/index.svelte +33 -0
- package/test/src/pages/some/page.svelte +2 -0
- package/tests/asset-dir/cayo.config.js +38 -0
- package/tests/asset-dir/package-lock.json +1435 -0
- package/tests/asset-dir/package.json +19 -0
- package/tests/asset-dir/public/images/app-icon.png +0 -0
- package/tests/asset-dir/src/__layout.svelte +20 -0
- package/tests/asset-dir/src/components/CayoExample.svelte +5 -0
- package/tests/asset-dir/src/components/Some.cayo.svelte +6 -0
- package/tests/asset-dir/src/index.js +5 -0
- package/tests/asset-dir/src/pages/index.svelte +19 -0
- package/tests/base-path/cayo.config.js +36 -0
- package/tests/base-path/package-lock.json +1435 -0
- package/tests/base-path/package.json +19 -0
- package/tests/base-path/public/assets/cow.js +1 -0
- package/tests/base-path/public/images/app-icon.png +0 -0
- package/tests/base-path/src/__layout.svelte +20 -0
- package/tests/base-path/src/components/CayoExample.svelte +5 -0
- package/tests/base-path/src/components/Some.cayo.svelte +6 -0
- package/tests/base-path/src/index.js +5 -0
- package/tests/base-path/src/pages/howdy.svelte +12 -0
- package/tests/base-path/src/pages/index.svelte +20 -0
- package/tests/basic/notcayo.config.js +35 -0
- package/tests/basic/package-lock.json +1435 -0
- package/tests/basic/package.json +19 -0
- package/tests/basic/public/assets/cow.js +1 -0
- package/tests/basic/public/images/app-icon.png +0 -0
- package/tests/basic/src/__layout.svelte +20 -0
- package/tests/basic/src/components/Cool.cayo.svelte +4 -0
- package/tests/basic/src/components/Some.svelte +1 -0
- package/tests/basic/src/index.js +5 -0
- package/tests/basic/src/main2.js +1 -0
- package/tests/basic/src/pages/hey.svelte +8 -0
- package/tests/basic/src/pages/howdy.svelte +11 -0
- package/tests/basic/src/pages/index.svelte +33 -0
- package/tests/basic/src/pages/some/some.svelte +2 -0
- package/tests/basic cases (old)/src/__index.svelte +18 -0
- package/tests/basic cases (old)/src/components/Cool.cayo.svelte +4 -0
- package/tests/basic cases (old)/src/components/Some.svelte +1 -0
- package/tests/basic cases (old)/src/components/dir/Cool.cayo.svelte +4 -0
- package/tests/basic cases (old)/src/main.js +1 -0
- package/tests/basic cases (old)/src/main2.js +1 -0
- package/tests/basic cases (old)/src/pages/hey.svelte +2 -0
- package/tests/basic cases (old)/src/pages/howdy.svelte +11 -0
- package/tests/basic cases (old)/src/pages/index.svelte +27 -0
- package/tests/nested-pages/cayo.config.js +35 -0
- package/tests/nested-pages/package-lock.json +1435 -0
- package/tests/nested-pages/package.json +19 -0
- package/tests/nested-pages/public/assets/cow.js +1 -0
- package/tests/nested-pages/public/images/app-icon.png +0 -0
- package/tests/nested-pages/src/__layout.svelte +20 -0
- package/tests/nested-pages/src/components/Cool.cayo.svelte +4 -0
- package/tests/nested-pages/src/index.js +5 -0
- package/tests/nested-pages/src/main2.js +1 -0
- package/tests/nested-pages/src/pages/index.svelte +18 -0
- package/tests/nested-pages/src/pages/some/other/page.svelte +7 -0
- package/tests/nested-pages/src/pages/some/page.svelte +6 -0
package/lib/files.js
ADDED
|
@@ -0,0 +1,84 @@
|
|
|
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
ADDED
|
@@ -0,0 +1,181 @@
|
|
|
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
|
+
}
|
package/lib/renderer.js
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import path from 'path';
|
|
2
|
+
|
|
3
|
+
export class Renderer {
|
|
4
|
+
|
|
5
|
+
constructor(template) {
|
|
6
|
+
this.template = template;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
render(page, config) {
|
|
10
|
+
const { css: cssOptions } = config;
|
|
11
|
+
|
|
12
|
+
const { Component } = page;
|
|
13
|
+
const { html, css, head } = Component.render();
|
|
14
|
+
|
|
15
|
+
// TODO: template function for page title
|
|
16
|
+
let title = page.meta.title ? `${page.meta.title} — Cayo` : 'Cayo';
|
|
17
|
+
|
|
18
|
+
let cssTag = '';
|
|
19
|
+
if (cssOptions.internal === false) {
|
|
20
|
+
if (this.template.css.code !== '') {
|
|
21
|
+
cssTag += `<link rel="stylesheet" href="/__index.css">\n`;
|
|
22
|
+
}
|
|
23
|
+
cssTag += `<link rel="stylesheet" href="./index.css">`;
|
|
24
|
+
} else {
|
|
25
|
+
if (this.template.css.code !== '') {
|
|
26
|
+
cssTag += `<style>/* Template CSS */${this.template.css.code}</style>\n`;
|
|
27
|
+
}
|
|
28
|
+
cssTag += `<style>${css.code}</style>`;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
return {
|
|
32
|
+
html: this.template.html
|
|
33
|
+
// Ignore placeholders wrapped in HTML comments
|
|
34
|
+
.replaceAll(/<!--[^]*\%cayo\.\w+\%[^]*-->/g, '')
|
|
35
|
+
// Replace placeholders in template
|
|
36
|
+
.replace('%cayo.title%', !head.includes('<title>') ? `<title>${title}</title>` : '')
|
|
37
|
+
.replace('%cayo.head%', head)
|
|
38
|
+
.replace('%cayo.body%', html)
|
|
39
|
+
.replace('%cayo.css%', cssTag)
|
|
40
|
+
.replace('%cayo.script%', `<script type="module" src="./index.js"></script>`)
|
|
41
|
+
,
|
|
42
|
+
css: css,
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
package/lib/runtime.js
ADDED
package/lib/utils.js
ADDED
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
import fs from 'fs-extra';
|
|
2
|
+
import fg from 'fast-glob';
|
|
3
|
+
import crypto from 'crypto';
|
|
4
|
+
import chalk from 'chalk';
|
|
5
|
+
import path from 'path';
|
|
6
|
+
|
|
7
|
+
export function getPageModules(modules, config) {
|
|
8
|
+
// TODO: build path from config
|
|
9
|
+
const extRegex = new RegExp(String.raw`(\.svelte)$`);
|
|
10
|
+
|
|
11
|
+
return Object.entries(modules).reduce((pages, [modulePath, page]) => {
|
|
12
|
+
// Make these paths actually useful
|
|
13
|
+
// /^(.+)\/pages/
|
|
14
|
+
// /^(\/\w+)*\/pages/
|
|
15
|
+
const filePath = modulePath.replace(/^(.+)\/pages\//, '').replace(extRegex, '')
|
|
16
|
+
const urlPath = filePath === 'index' ? filePath.replace(/index$/, '/') : `${filePath}/`
|
|
17
|
+
// name = name.split('.', 1)[0];
|
|
18
|
+
pages[urlPath] = {
|
|
19
|
+
Component: page.default,
|
|
20
|
+
meta: page.meta ? page.meta : {},
|
|
21
|
+
filePath,
|
|
22
|
+
modulePath,
|
|
23
|
+
urlPath
|
|
24
|
+
}
|
|
25
|
+
return pages;
|
|
26
|
+
}, {})
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export function getComponentModules(modules, config) {
|
|
30
|
+
|
|
31
|
+
return Object.entries(modules).reduce((components, [modulePath, component]) => {
|
|
32
|
+
const componentNameRegex = /\/(?<name>\w+)\.cayo\.svelte/; // Foo-{hash}
|
|
33
|
+
const name = modulePath.match(componentNameRegex).groups.name;
|
|
34
|
+
if (components[name]) {
|
|
35
|
+
config.logger.info(
|
|
36
|
+
chalk.red(
|
|
37
|
+
`Cayo component with name '${name}' already exists. Cayo components must have unique file names.`
|
|
38
|
+
) + chalk.dim(`\n\t\t\t${modulePath}`),
|
|
39
|
+
{ timestamp: true, clear: true, }
|
|
40
|
+
);
|
|
41
|
+
}
|
|
42
|
+
components[name] = {
|
|
43
|
+
Component: component.default,
|
|
44
|
+
modulePath,
|
|
45
|
+
}
|
|
46
|
+
return components;
|
|
47
|
+
}, {})
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export function hash(bytes = 5) {
|
|
51
|
+
return crypto.randomBytes(bytes).toString('hex');
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export async function getPageModulePaths(pagesPath) {
|
|
55
|
+
return await fg([path.resolve(pagesPath, './**/*.svelte')]);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export async function getComponentModulePaths(srcPath) {
|
|
59
|
+
return await fg([path.resolve(srcPath, './components/**/*.cayo.svelte')]);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
export async function createPageManifest(pagesPath, outDir) {
|
|
63
|
+
const pagePaths = await getPageModulePaths(pagesPath);
|
|
64
|
+
let importPages = `import { createRequire } from 'module';\n`
|
|
65
|
+
importPages += `const require = createRequire(import.meta.url);\n`
|
|
66
|
+
importPages += `require('svelte/register');\n`;
|
|
67
|
+
pagePaths.forEach((path, i) => {
|
|
68
|
+
importPages += `delete require.cache['${path}'];\n`
|
|
69
|
+
importPages += `const page_${i} = require('${path}');\n`;
|
|
70
|
+
});
|
|
71
|
+
importPages += 'export const pages = {\n';
|
|
72
|
+
pagePaths.forEach((path, i) => {
|
|
73
|
+
importPages += ` '${path}': page_${i},\n`;
|
|
74
|
+
})
|
|
75
|
+
importPages += '}\n';
|
|
76
|
+
return await fs.outputFile(path.resolve(outDir, './__cayo/pages.js'), importPages);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
export async function createComponentManifest(srcPath, outDir) {
|
|
80
|
+
const componentPaths = await getComponentModulePaths(srcPath);
|
|
81
|
+
let importComponents = `import { createRequire } from 'module';\n`;
|
|
82
|
+
importComponents += `const require = createRequire(import.meta.url);\n`;
|
|
83
|
+
importComponents += `require('svelte/register');\n`;
|
|
84
|
+
componentPaths.forEach((path, i) => {
|
|
85
|
+
importComponents += `delete require.cache['${path}'];\n`;
|
|
86
|
+
importComponents += `const component_${i} = require('${path}');\n`;
|
|
87
|
+
});
|
|
88
|
+
importComponents += 'export const components = {\n';
|
|
89
|
+
componentPaths.forEach((path, i) => {
|
|
90
|
+
importComponents += ` '${path}': component_${i},\n`;
|
|
91
|
+
})
|
|
92
|
+
importComponents += '}\n';
|
|
93
|
+
return await fs.outputFile(path.resolve(outDir, './__cayo/components.js'), importComponents);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
export async function createTemplateManifest(templatePath, outDir) {
|
|
98
|
+
let importTemplate = `import { createRequire } from 'module';\n`;
|
|
99
|
+
importTemplate += `const require = createRequire(import.meta.url);\n`;
|
|
100
|
+
importTemplate += `require('svelte/register');\n`;
|
|
101
|
+
importTemplate += `delete require.cache['${templatePath}'];\n`;
|
|
102
|
+
importTemplate += `export const Template = require('${templatePath}').default;\n`;
|
|
103
|
+
return await fs.outputFile(path.resolve(outDir, './__cayo/template.js'), importTemplate);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
// Credit: https://github.com/snowpackjs/astro
|
|
108
|
+
/** Add / to the end of string (but don’t double-up) */
|
|
109
|
+
export function addTrailingSlash(_path) {
|
|
110
|
+
return _path.replace(/\/?$/, '/');
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
export function normalizePath(root, _path) {
|
|
114
|
+
if (root === _path) return root;
|
|
115
|
+
return path.normalize(path.join(root, addTrailingSlash(_path)));
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
export function getOutDir(config) {
|
|
119
|
+
return config.mode === 'production' ? config.buildOptions.outDir : config.cayoPath;
|
|
120
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { defineConfig } from 'vite'
|
|
2
|
+
import { svelte } from '@sveltejs/vite-plugin-svelte'
|
|
3
|
+
import sveltePreprocess from 'svelte-preprocess'
|
|
4
|
+
|
|
5
|
+
export default defineConfig({
|
|
6
|
+
clearScreen: false,
|
|
7
|
+
plugins: [svelte({
|
|
8
|
+
preprocess: sveltePreprocess({ preserve: ['json'] }),
|
|
9
|
+
compilerOptions: {
|
|
10
|
+
hydratable: true,
|
|
11
|
+
},
|
|
12
|
+
})],
|
|
13
|
+
server: {
|
|
14
|
+
port: '5000',
|
|
15
|
+
}
|
|
16
|
+
});
|
package/notes.md
ADDED
package/package.json
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "cayo",
|
|
3
|
+
"version": "0.9.0",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"scripts": {
|
|
6
|
+
"start": "node cayo dev --projectRoot test"
|
|
7
|
+
},
|
|
8
|
+
"bin": {
|
|
9
|
+
"cayo": "cayo.js"
|
|
10
|
+
},
|
|
11
|
+
"repository": {
|
|
12
|
+
"type": "git",
|
|
13
|
+
"url": "git+https://github.com/matthew-ia/cayo.git"
|
|
14
|
+
},
|
|
15
|
+
"author": "Matthew I. Alicea",
|
|
16
|
+
"license": "MIT",
|
|
17
|
+
"bugs": {
|
|
18
|
+
"url": "https://github.com/matthew-ia/cayo/issues"
|
|
19
|
+
},
|
|
20
|
+
"homepage": "https://github.com/matthew-ia/cayo#readme",
|
|
21
|
+
"devDependencies": {
|
|
22
|
+
"@vitejs/plugin-legacy": "^1.6.2"
|
|
23
|
+
},
|
|
24
|
+
"dependencies": {
|
|
25
|
+
"@sveltejs/vite-plugin-svelte": "^1.0.0-next.11",
|
|
26
|
+
"chalk": "^2.4.2",
|
|
27
|
+
"chokidar": "^3.5.2",
|
|
28
|
+
"deepmerge": "^4.2.2",
|
|
29
|
+
"fast-glob": "^3.2.7",
|
|
30
|
+
"fs-extra": "^10.0.0",
|
|
31
|
+
"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",
|
|
36
|
+
"yargs-parser": "^20.2.9",
|
|
37
|
+
"zod": "^3.10.3"
|
|
38
|
+
}
|
|
39
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
|
|
2
|
+
// vite config example
|
|
3
|
+
import { defineConfig } from 'vite'
|
|
4
|
+
import { svelte } from '@sveltejs/vite-plugin-svelte'
|
|
5
|
+
import sveltePreprocess from 'svelte-preprocess'
|
|
6
|
+
// const viteConfig = defineConfig({
|
|
7
|
+
// // root: './.cayo/',
|
|
8
|
+
// plugins: [svelte({
|
|
9
|
+
// preprocess: sveltePreprocess({ preserve: ['json'] }),
|
|
10
|
+
// compilerOptions: {
|
|
11
|
+
// hydratable: true,
|
|
12
|
+
// },
|
|
13
|
+
// })],
|
|
14
|
+
// });
|
|
15
|
+
|
|
16
|
+
export default {
|
|
17
|
+
// projectRoot: '.',
|
|
18
|
+
// css: {
|
|
19
|
+
// internal: false,
|
|
20
|
+
// },
|
|
21
|
+
templateFileName: '__layout',
|
|
22
|
+
viteConfig: {
|
|
23
|
+
base: '/vite/',
|
|
24
|
+
plugins: [svelte({
|
|
25
|
+
preprocess: sveltePreprocess({ preserve: ['json'] }),
|
|
26
|
+
compilerOptions: {
|
|
27
|
+
hydratable: true,
|
|
28
|
+
},
|
|
29
|
+
})],
|
|
30
|
+
server: {
|
|
31
|
+
port: '5005',
|
|
32
|
+
},
|
|
33
|
+
},
|
|
34
|
+
base: '/cayo/'
|
|
35
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
console.log("I'm main");
|
|
Binary file
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
<!-- <!DOCTYPE html> -->
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8" />
|
|
5
|
+
<link rel="icon" href="/favicon.ico" />
|
|
6
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
7
|
+
%cayo.title%
|
|
8
|
+
%cayo.css%
|
|
9
|
+
%cayo.head%
|
|
10
|
+
</head>
|
|
11
|
+
<body class="hey">
|
|
12
|
+
<!--
|
|
13
|
+
TODO: Show how to condtionally render any of these pieces based on dev vs. prod
|
|
14
|
+
E.g., I need to remove head from prod, but want it there in dev
|
|
15
|
+
-->
|
|
16
|
+
%cayo.body%
|
|
17
|
+
%cayo.script%
|
|
18
|
+
</body>
|
|
19
|
+
|
|
20
|
+
</html>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
a
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
console.log("I'm main also");
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
<script context="module">
|
|
2
|
+
export const meta = {
|
|
3
|
+
title: 'Home',
|
|
4
|
+
};
|
|
5
|
+
</script>
|
|
6
|
+
<script>
|
|
7
|
+
import Cayo from '../../../lib/components/Cayo.svelte';
|
|
8
|
+
</script>
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
I'm index howdy ok<br>
|
|
12
|
+
<a href="/howdy/">Howdy</a><br>
|
|
13
|
+
<a href="/hey/" class="red">Hey</a>
|
|
14
|
+
<a href="/some/page/" class="red">Some</a>
|
|
15
|
+
|
|
16
|
+
<Cayo name="Cool" beans='ayo'></Cayo>
|
|
17
|
+
<Cayo name="Cool" beans='beeeeaaaaasnnss' />
|
|
18
|
+
<Cayo name="Cool" beans='NOT BEANS' />
|
|
19
|
+
|
|
20
|
+
<img src="/images/app-icon.png" alt="">
|
|
21
|
+
|
|
22
|
+
<slot name="entry">
|
|
23
|
+
<script src="/index.js" data-cayo-entry />
|
|
24
|
+
</slot>
|
|
25
|
+
|
|
26
|
+
<style>
|
|
27
|
+
.red {
|
|
28
|
+
color: red;
|
|
29
|
+
}
|
|
30
|
+
img {
|
|
31
|
+
width: 50px;
|
|
32
|
+
}
|
|
33
|
+
</style>
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
|
|
2
|
+
// vite config example
|
|
3
|
+
import { defineConfig } from 'vite'
|
|
4
|
+
import { svelte } from '@sveltejs/vite-plugin-svelte'
|
|
5
|
+
import sveltePreprocess from 'svelte-preprocess'
|
|
6
|
+
// const viteConfig = defineConfig({
|
|
7
|
+
// // root: './.cayo/',
|
|
8
|
+
// plugins: [svelte({
|
|
9
|
+
// preprocess: sveltePreprocess({ preserve: ['json'] }),
|
|
10
|
+
// compilerOptions: {
|
|
11
|
+
// hydratable: true,
|
|
12
|
+
// },
|
|
13
|
+
// })],
|
|
14
|
+
// });
|
|
15
|
+
|
|
16
|
+
export default {
|
|
17
|
+
// projectRoot: '.',
|
|
18
|
+
// css: {
|
|
19
|
+
// internal: false,
|
|
20
|
+
// },
|
|
21
|
+
templateFileName: '__layout',
|
|
22
|
+
viteConfig: {
|
|
23
|
+
// base: '/vite/',
|
|
24
|
+
plugins: [svelte({
|
|
25
|
+
preprocess: sveltePreprocess({ preserve: ['json'] }),
|
|
26
|
+
compilerOptions: {
|
|
27
|
+
hydratable: true,
|
|
28
|
+
},
|
|
29
|
+
})],
|
|
30
|
+
server: {
|
|
31
|
+
// port: '5005',
|
|
32
|
+
},
|
|
33
|
+
},
|
|
34
|
+
build: {
|
|
35
|
+
assetsDir: 'some/specific/path',
|
|
36
|
+
},
|
|
37
|
+
base: '/some/specific/path/',
|
|
38
|
+
}
|