cayo 1.3.3 → 1.5.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/README.md +119 -23
- package/dist/cayo.svelte.js +23 -4
- package/dist/entry.svelte.js +1 -1
- package/dist/index.js +1 -0
- package/docs/config-reference.md +33 -0
- package/lib/core/bundle.js +65 -23
- package/lib/core/render/prerender.js +1 -1
- package/lib/core/render/renderer.js +40 -10
- package/lib/preprocessors/cayo-component.js +23 -0
- package/lib/preprocessors/index.js +10 -0
- package/package.json +2 -1
- package/scripts/build.js +2 -0
- package/src/cayo.svelte +20 -3
- package/src/entry.svelte +1 -1
- package/template/cayo.config.js +9 -1
- package/template/src/__template.svelte +5 -5
- package/template/src/pages/index.svelte +14 -1
package/README.md
CHANGED
|
@@ -143,20 +143,23 @@ The Template file is required, and used to render all of your pages. The output
|
|
|
143
143
|
|
|
144
144
|
This file is a Svelte component, so you can also import other Svelte components or add rendering logic. For example, you could render different markup wrapping your pages depending on the environment mode like `'development'` or `'production'` (see [config example](docs//config-reference.md#conditional-config)).
|
|
145
145
|
|
|
146
|
+
> **Template Placeholder Syntax**<br>
|
|
147
|
+
> Cayo uses HTML comment placeholders: `<!--[cayo-css]-->` for template injection. The `%cayo.*%` syntax is deprecated. See [placeholder syntax guide](#template-placeholder-syntax) below.
|
|
148
|
+
|
|
146
149
|
> **Note**<br>
|
|
147
|
-
> Despite being a Svelte component, the Template file does not support the `<slot>` element, because it itself is prerendered _before_ it is used to prerender page components. The placeholder
|
|
150
|
+
> Despite being a Svelte component, the Template file does not support the `<slot>` element, because it itself is prerendered _before_ it is used to prerender page components. The placeholder `<!--[cayo-body]-->` replaces the basic usage for `<slot>`.
|
|
148
151
|
|
|
149
152
|
Template files support the following placeholders:
|
|
150
153
|
|
|
151
|
-
-
|
|
154
|
+
- `<!--[cayo-body]-->` – the content of a page. Think of this as the `<slot>` of the Template Svelte component
|
|
152
155
|
|
|
153
|
-
-
|
|
156
|
+
- `<!--[cayo-script]-->` – where your [entry](#entries) for a page will be imported. This is needed if a page is to render a Cayo Component, but is otherwise optional
|
|
154
157
|
|
|
155
|
-
-
|
|
158
|
+
- `<!--[cayo-css]-->` – where CSS will be added (as `<link src="style.css">` or `<style>...</style>` depending on your [CSS config option](docs/config-reference.md#cssinternal))
|
|
156
159
|
|
|
157
|
-
-
|
|
160
|
+
- `<!--[cayo-title]-->` – add a default title to the page only if one is not already set on a specific page (via [`<svelte:head>`](https://svelte.dev/docs#template-syntax-svelte-head) or other some other method). The default title will be generated using the page's filename (e.g., `page.svelte` will have the title `Page`). This placeholder is optional
|
|
158
161
|
|
|
159
|
-
-
|
|
162
|
+
- `<!--[cayo-head]-->` – `<link>` and `<script>` elements needed by a page, plus any `<svelte:head>` content
|
|
160
163
|
|
|
161
164
|
#### Example
|
|
162
165
|
Technically all of the placeholders are optional, and don't have to be in any particular place within your markup.
|
|
@@ -166,13 +169,13 @@ Technically all of the placeholders are optional, and don't have to be in any pa
|
|
|
166
169
|
<!DOCTYPE html>
|
|
167
170
|
<html>
|
|
168
171
|
<head>
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
+
<!--[cayo-head]-->
|
|
173
|
+
<!--[cayo-title]-->
|
|
174
|
+
<!--[cayo-css]-->
|
|
172
175
|
</head>
|
|
173
176
|
<body>
|
|
174
|
-
|
|
175
|
-
|
|
177
|
+
<!--[cayo-body]-->
|
|
178
|
+
<!--[cayo-script]-->
|
|
176
179
|
</body>
|
|
177
180
|
</html>
|
|
178
181
|
```
|
|
@@ -183,11 +186,35 @@ Your template doesn't even need to be a valid HTML document—you could be outpu
|
|
|
183
186
|
<!-- src/__template.svelte -->
|
|
184
187
|
<!-- No html, head, or body elements... and that's okay! -->
|
|
185
188
|
<div>something I want on every page</div>
|
|
186
|
-
|
|
189
|
+
<!--[cayo-script]-->
|
|
190
|
+
<!--[cayo-css]-->
|
|
191
|
+
<!--[cayo-body]-->
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
#### Template Placeholder Syntax
|
|
195
|
+
|
|
196
|
+
Cayo supports the following placeholder syntaxes:
|
|
197
|
+
|
|
198
|
+
**Recommended syntax (HTML comments):**
|
|
199
|
+
```html
|
|
200
|
+
<!--[cayo-title]-->
|
|
201
|
+
<!--[cayo-head]-->
|
|
202
|
+
<!--[cayo-css]-->
|
|
203
|
+
<!--[cayo-body]-->
|
|
204
|
+
<!--[cayo-script]-->
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
**Deprecated syntax:**
|
|
208
|
+
```html
|
|
209
|
+
%cayo.title%
|
|
210
|
+
%cayo.head%
|
|
187
211
|
%cayo.css%
|
|
188
212
|
%cayo.body%
|
|
213
|
+
%cayo.script%
|
|
189
214
|
```
|
|
190
215
|
|
|
216
|
+
The HTML comment syntax is reliable since Cayo configures Svelte to preserve comments during SSR compilation. The `%cayo.*%` syntax is deprecated but still supported for backward compatibility.
|
|
217
|
+
|
|
191
218
|
### .cayo
|
|
192
219
|
|
|
193
220
|
Once you run your project, you'll see directory named `.cayo` in your project's root. This directory is used for Cayo's internal output. Its contents are served during `cayo dev`, and used to build your project during `cayo build`.
|
|
@@ -225,6 +252,39 @@ More on [Svelte options](docs/config-reference.md#svelte-options), [Vite options
|
|
|
225
252
|
> **Warning**<br>
|
|
226
253
|
> Vite plugins will be passed to Cayo, but it's possible that certain plugins may break Cayo if they deal with handling the input differently than vanilla Vite or generate additional output files. Cayo acts like a plugin itself, by handling your source files and transforming them into files that vanilla Vite expects (e.g., the built-in "file-based router" is similar to Vite multi-page plugins).
|
|
227
254
|
|
|
255
|
+
### Cayo Preprocessors
|
|
256
|
+
|
|
257
|
+
To use the improved `component` prop syntax with Cayo components (instead of just string paths), you need to configure the `cayoPreprocess` preprocessors:
|
|
258
|
+
|
|
259
|
+
```js
|
|
260
|
+
// cayo.config.js
|
|
261
|
+
import { cayoPreprocess } from 'cayo/build';
|
|
262
|
+
|
|
263
|
+
export default {
|
|
264
|
+
svelte: {
|
|
265
|
+
preprocess: [
|
|
266
|
+
cayoPreprocess(),
|
|
267
|
+
// ...other preprocessors
|
|
268
|
+
]
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
```
|
|
272
|
+
|
|
273
|
+
This preprocessor enhances Cayo's functionality by transforming imported component objects into the appropriate paths that Cayo can resolve. It enables the following syntax:
|
|
274
|
+
|
|
275
|
+
```svelte
|
|
276
|
+
<!-- Before: String-based approach -->
|
|
277
|
+
<Cayo src="counter.cayo.svelte" />
|
|
278
|
+
|
|
279
|
+
<!-- After: Component-based approach (with preprocessor) -->
|
|
280
|
+
<script>
|
|
281
|
+
import Counter from '$components/counter.cayo.svelte';
|
|
282
|
+
</script>
|
|
283
|
+
<Cayo component={Counter} />
|
|
284
|
+
```
|
|
285
|
+
|
|
286
|
+
The component preprocessor automatically handles alias resolution (like `$components/`) and provides better developer experience with IDE support, auto-completion, and build-time error checking. Additional preprocessors may be added in the future.
|
|
287
|
+
|
|
228
288
|
## Components
|
|
229
289
|
|
|
230
290
|
By default, all components are prerendered. This means their lifecycle ends after they finish one run cycle, and the UI state after the first cycle is rendered to static HTML. This also means that any JS you use within the component's `<script>` element "compiles away" after it's used to render the component. These components are essentially "server side rendered", but are done so locally within Cayo processes rather than on a production server.
|
|
@@ -248,6 +308,25 @@ The `<Cayo>` component doesn't actually render your Cayos—instead it creates _
|
|
|
248
308
|
### Basic Usage
|
|
249
309
|
|
|
250
310
|
Let's assume the component `components/counter.cayo.svelte` exists in your project, and has a prop `count`:
|
|
311
|
+
|
|
312
|
+
#### Component object syntax (recommended):
|
|
313
|
+
```svelte
|
|
314
|
+
<!-- Register your Cayo with the imported component -->
|
|
315
|
+
<script>
|
|
316
|
+
import { Cayo } from 'cayo';
|
|
317
|
+
import Counter from '$components/counter.cayo.svelte';
|
|
318
|
+
</script>
|
|
319
|
+
<!-- Basic usage -->
|
|
320
|
+
<Cayo component={Counter} />
|
|
321
|
+
<!-- Any additional props will be used to hydrate the Cayo on the client -->
|
|
322
|
+
<Cayo component={Counter} count={1} />
|
|
323
|
+
```
|
|
324
|
+
|
|
325
|
+
When using the `component` prop, you can import your Cayo components directly. This provides better developer experience with auto-completion and build-time error checking.
|
|
326
|
+
|
|
327
|
+
> **Note:** To use the `component` prop syntax, you must configure `cayoPreprocess` in your `cayo.config.js`. See [Cayo Preprocessors](#cayo-preprocessors) for setup instructions.
|
|
328
|
+
|
|
329
|
+
#### String path syntax (classic):
|
|
251
330
|
```svelte
|
|
252
331
|
<!-- Register your Cayo with the <Cayo> component -->
|
|
253
332
|
<script>
|
|
@@ -259,7 +338,7 @@ Let's assume the component `components/counter.cayo.svelte` exists in your proje
|
|
|
259
338
|
<Cayo src="counter.cayo.svelte" count={1} />
|
|
260
339
|
```
|
|
261
340
|
|
|
262
|
-
The `src` prop is
|
|
341
|
+
The `src` prop is used to identify which Cayo Component should be rendered later. The value of `src` needs to be the path of a Cayo, but must be relative to the components directory (e.g., `src/components` by default). For example, say your Cayo was `components/nested/counter.cayo.svelte`, your usage would need to change to `<Cayo src="nested/counter.cayo.svelte" />`.
|
|
263
342
|
|
|
264
343
|
The `<Cayo>` component can be rendered on a page or any other Svelte component except other Cayos.
|
|
265
344
|
|
|
@@ -292,11 +371,12 @@ And `page.svelte` registers that Cayo component, like so:
|
|
|
292
371
|
<!-- src/pages/page.svelte -->
|
|
293
372
|
<script>
|
|
294
373
|
import { Cayo, Entry } from 'cayo';
|
|
374
|
+
import Counter from '../components/counter.cayo.svelte';
|
|
295
375
|
</script>
|
|
296
376
|
<!-- Say you want to start the count as 1 instead of 0, you can pass that value as a prop -->
|
|
297
|
-
<Cayo
|
|
377
|
+
<Cayo component={Counter} count={1} />
|
|
298
378
|
<!-- Declare the entry -->
|
|
299
|
-
<Entry
|
|
379
|
+
<Entry />
|
|
300
380
|
```
|
|
301
381
|
|
|
302
382
|
The resulting output will be a placeholder for the component. By default, this placeholder is used as the target for that Svelte component to mount to:
|
|
@@ -336,19 +416,37 @@ An entry serves two purposes:
|
|
|
336
416
|
|
|
337
417
|
Since not every page will necessarily need Cayos, including an entry file at all is optional. You can define different entries per page, or even use the same file for all pages.
|
|
338
418
|
|
|
339
|
-
|
|
419
|
+
### Default Entry File
|
|
420
|
+
|
|
421
|
+
By default, the `<Entry>` component looks for `entry.js` in your `src` directory:
|
|
422
|
+
|
|
423
|
+
```svelte
|
|
424
|
+
<!-- src/pages/page.svelte -->
|
|
425
|
+
<script>
|
|
426
|
+
import { Entry } from 'cayo';
|
|
427
|
+
</script>
|
|
428
|
+
<!-- ...other page stuff -->
|
|
429
|
+
<Entry />
|
|
430
|
+
```
|
|
431
|
+
|
|
432
|
+
This will use `src/entry.js` as the entry file for the page.
|
|
433
|
+
|
|
434
|
+
### Custom Entry Files
|
|
435
|
+
|
|
436
|
+
You can specify a different entry file using the `src` prop:
|
|
437
|
+
|
|
340
438
|
```svelte
|
|
341
439
|
<!-- src/pages/page.svelte -->
|
|
342
440
|
<script>
|
|
343
441
|
import { Entry } from 'cayo';
|
|
344
442
|
</script>
|
|
345
443
|
<!-- ...other page stuff -->
|
|
346
|
-
<Entry src="
|
|
444
|
+
<Entry src="main.js" />
|
|
347
445
|
```
|
|
348
446
|
|
|
349
|
-
|
|
447
|
+
The `src` attribute should point at a JS file that is **relative to the [`src` directory](#source-directory)**, rather than relative to the page itself.
|
|
350
448
|
|
|
351
|
-
Note:
|
|
449
|
+
Note: You can use any filename and path structure you want within the `src` directory.
|
|
352
450
|
|
|
353
451
|
### Render Hook
|
|
354
452
|
|
|
@@ -419,7 +517,7 @@ Say you want to render something in a Cayo before it gets hydrated, like a "load
|
|
|
419
517
|
<!-- This will render inside the placeholder because the <Cayo> component renders a <slot> -->
|
|
420
518
|
Loading counter...
|
|
421
519
|
</Cayo>
|
|
422
|
-
<Entry
|
|
520
|
+
<Entry />
|
|
423
521
|
```
|
|
424
522
|
|
|
425
523
|
```js
|
|
@@ -489,9 +587,7 @@ Page:
|
|
|
489
587
|
<!-- src/pages/page.svelte -->
|
|
490
588
|
|
|
491
589
|
<!-- ...other page stuff -->
|
|
492
|
-
<
|
|
493
|
-
<script src="entry.js" data-cayo-entry />
|
|
494
|
-
</slot>
|
|
590
|
+
<Entry />
|
|
495
591
|
```
|
|
496
592
|
|
|
497
593
|
## Cayo & the Rest
|
package/dist/cayo.svelte.js
CHANGED
|
@@ -41,10 +41,28 @@ function checkBadProps(warnings, src, keys) {
|
|
|
41
41
|
/* src/cayo.svelte generated by Svelte v3.59.2 */
|
|
42
42
|
|
|
43
43
|
const Cayo = create_ssr_component(($$result, $$props, $$bindings, slots) => {
|
|
44
|
-
let $$restProps = compute_rest_props($$props, ["src","attributes"]);
|
|
45
|
-
let { src } = $$props;
|
|
44
|
+
let $$restProps = compute_rest_props($$props, ["src","component","attributes"]);
|
|
45
|
+
let { src = undefined } = $$props;
|
|
46
|
+
let { component = undefined } = $$props;
|
|
46
47
|
let { attributes } = $$props;
|
|
47
48
|
|
|
49
|
+
// Determine the actual source path
|
|
50
|
+
let actualSrc;
|
|
51
|
+
|
|
52
|
+
if (src) {
|
|
53
|
+
// Traditional string src prop
|
|
54
|
+
actualSrc = src;
|
|
55
|
+
} else if (component && component.__cayoPath) {
|
|
56
|
+
// Component object with extracted path
|
|
57
|
+
actualSrc = component.__cayoPath;
|
|
58
|
+
} else if (typeof component === 'string') {
|
|
59
|
+
// Component passed as string directly
|
|
60
|
+
actualSrc = component;
|
|
61
|
+
} else {
|
|
62
|
+
// Fallback error case
|
|
63
|
+
actualSrc = '';
|
|
64
|
+
}
|
|
65
|
+
|
|
48
66
|
// Save unserializable prop keys (during stringification)
|
|
49
67
|
// so we can report them later
|
|
50
68
|
const badProps = [];
|
|
@@ -62,10 +80,10 @@ const Cayo = create_ssr_component(($$result, $$props, $$bindings, slots) => {
|
|
|
62
80
|
// const props = toSource({...$$restProps})
|
|
63
81
|
const props = JSON.stringify({ ...$$restProps }, replacer);
|
|
64
82
|
|
|
65
|
-
const warnings = getWarnings(
|
|
83
|
+
const warnings = getWarnings(actualSrc, badProps);
|
|
66
84
|
|
|
67
85
|
const cayoInstanceData = {
|
|
68
|
-
'data-cayo-src': !warnings.invalidSrc ? `${
|
|
86
|
+
'data-cayo-src': !warnings.invalidSrc ? `${actualSrc}` : '',
|
|
69
87
|
'data-cayo-id': '', // will get set during prerender process based on the src
|
|
70
88
|
|
|
71
89
|
};
|
|
@@ -75,6 +93,7 @@ const Cayo = create_ssr_component(($$result, $$props, $$bindings, slots) => {
|
|
|
75
93
|
}
|
|
76
94
|
|
|
77
95
|
if ($$props.src === void 0 && $$bindings.src && src !== void 0) $$bindings.src(src);
|
|
96
|
+
if ($$props.component === void 0 && $$bindings.component && component !== void 0) $$bindings.component(component);
|
|
78
97
|
if ($$props.attributes === void 0 && $$bindings.attributes && attributes !== void 0) $$bindings.attributes(attributes);
|
|
79
98
|
|
|
80
99
|
return `<div${spread(
|
package/dist/entry.svelte.js
CHANGED
|
@@ -3,7 +3,7 @@ import { create_ssr_component, add_attribute } from 'svelte/internal';
|
|
|
3
3
|
/* src/entry.svelte generated by Svelte v3.59.2 */
|
|
4
4
|
|
|
5
5
|
const Entry = create_ssr_component(($$result, $$props, $$bindings, slots) => {
|
|
6
|
-
let { src } = $$props;
|
|
6
|
+
let { src = "entry.js" } = $$props;
|
|
7
7
|
if ($$props.src === void 0 && $$bindings.src && src !== void 0) $$bindings.src(src);
|
|
8
8
|
|
|
9
9
|
return `${slots.default
|
package/dist/index.js
CHANGED
package/docs/config-reference.md
CHANGED
|
@@ -275,6 +275,39 @@ export default {
|
|
|
275
275
|
```
|
|
276
276
|
---
|
|
277
277
|
|
|
278
|
+
### Enable Cayo Preprocessors
|
|
279
|
+
To use enhanced Cayo features like imported components instead of string paths in `<Cayo>` components, add the `cayoPreprocess` preprocessors:
|
|
280
|
+
|
|
281
|
+
```js
|
|
282
|
+
// cayo.config.js
|
|
283
|
+
import { cayoPreprocess } from 'cayo/build';
|
|
284
|
+
|
|
285
|
+
export default {
|
|
286
|
+
svelte: {
|
|
287
|
+
preprocess: [
|
|
288
|
+
cayoPreprocess(),
|
|
289
|
+
// other preprocessors...
|
|
290
|
+
],
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
```
|
|
294
|
+
|
|
295
|
+
This enables the improved component syntax:
|
|
296
|
+
```svelte
|
|
297
|
+
<!-- Instead of string paths -->
|
|
298
|
+
<Cayo src="counter.cayo.svelte" />
|
|
299
|
+
|
|
300
|
+
<!-- You can use imported components -->
|
|
301
|
+
<script>
|
|
302
|
+
import Counter from '$components/counter.cayo.svelte';
|
|
303
|
+
</script>
|
|
304
|
+
<Cayo component={Counter} />
|
|
305
|
+
```
|
|
306
|
+
|
|
307
|
+
This preprocessor provides enhanced Cayo functionality. The component preprocessor provides better developer experience with IDE support, auto-completion, and build-time error checking.
|
|
308
|
+
|
|
309
|
+
---
|
|
310
|
+
|
|
278
311
|
### Add `mdsvex`
|
|
279
312
|
Adding other Svelte preprocessors works similar to how it would in any other Vite + Svelte project.
|
|
280
313
|
|
package/lib/core/bundle.js
CHANGED
|
@@ -1,34 +1,63 @@
|
|
|
1
|
-
import fs
|
|
1
|
+
import fs from 'fs-extra';
|
|
2
2
|
import { rollup } from 'rollup';
|
|
3
3
|
import svelte from 'rollup-plugin-svelte';
|
|
4
4
|
import resolve from '@rollup/plugin-node-resolve';
|
|
5
|
+
import commonjs from '@rollup/plugin-commonjs';
|
|
5
6
|
import css from 'rollup-plugin-import-css';
|
|
6
7
|
import json from '@rollup/plugin-json';
|
|
7
8
|
|
|
8
9
|
function inputOptions(input) {
|
|
9
10
|
return {
|
|
10
11
|
input,
|
|
11
|
-
external:
|
|
12
|
+
external: (id) => id === 'svelte' || id.startsWith('svelte/'),
|
|
12
13
|
onwarn: function ( message ) {
|
|
13
14
|
if ( /external dependency/.test( message ) ) return;
|
|
14
15
|
},
|
|
15
16
|
};
|
|
16
17
|
}
|
|
17
18
|
|
|
19
|
+
function resolvePluginDefaults(overrides = {}) {
|
|
20
|
+
return {
|
|
21
|
+
browser: false,
|
|
22
|
+
exportConditions: ['svelte'],
|
|
23
|
+
extensions: ['.svelte'],
|
|
24
|
+
dedupe: ['svelte'],
|
|
25
|
+
...overrides,
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
function sveltePluginDefaults() {
|
|
30
|
+
return {
|
|
31
|
+
onwarn: (warning, handler) => {
|
|
32
|
+
console.log('Svelte processing:', warning.filename);
|
|
33
|
+
handler(warning);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
18
38
|
function defaultRollupPlugins() {
|
|
19
|
-
return [
|
|
39
|
+
return [
|
|
40
|
+
commonjs({
|
|
41
|
+
include: /node_modules/,
|
|
42
|
+
}),
|
|
43
|
+
css(),
|
|
44
|
+
json()
|
|
45
|
+
];
|
|
20
46
|
}
|
|
21
47
|
|
|
22
48
|
function userRollupPlugins(config) {
|
|
23
49
|
return config.vite.rollupOptions.plugins;
|
|
24
50
|
}
|
|
25
51
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
// User-defined preprocessors
|
|
29
|
-
let preprocessors = config.svelte.preprocess.length > 0
|
|
52
|
+
function getUserDefinedPreprocessors(config) {
|
|
53
|
+
return config.svelte.preprocess.length > 0
|
|
30
54
|
? config.svelte.preprocess
|
|
31
55
|
: [config.svelte.preprocess];
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export async function getDeps(input, config) {
|
|
59
|
+
let bundle;
|
|
60
|
+
let preprocessors = getUserDefinedPreprocessors(config);
|
|
32
61
|
|
|
33
62
|
const options = {
|
|
34
63
|
...inputOptions(input),
|
|
@@ -37,11 +66,10 @@ export async function getDeps(input, config) {
|
|
|
37
66
|
preprocess: [
|
|
38
67
|
...preprocessors,
|
|
39
68
|
],
|
|
69
|
+
...sveltePluginDefaults(),
|
|
40
70
|
}),
|
|
41
71
|
resolve({
|
|
42
|
-
|
|
43
|
-
exportConditions: ['svelte'],
|
|
44
|
-
extensions: ['.svelte'],
|
|
72
|
+
...resolvePluginDefaults(),
|
|
45
73
|
}),
|
|
46
74
|
...defaultRollupPlugins(),
|
|
47
75
|
...userRollupPlugins(config),
|
|
@@ -77,15 +105,26 @@ export async function getDeps(input, config) {
|
|
|
77
105
|
}
|
|
78
106
|
|
|
79
107
|
export async function build(input, config, type = 'page') {
|
|
80
|
-
const
|
|
108
|
+
const ssr = (type === 'page' || type === 'template');
|
|
109
|
+
const isCayo = (type === 'cayo');
|
|
81
110
|
const requiredCompilerOptions = {
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
111
|
+
// Generic defaults for all builds
|
|
112
|
+
preserveWhitespace: true,
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
if (ssr) {
|
|
116
|
+
// Pages & Templates (SSR): server-side rendered
|
|
117
|
+
requiredCompilerOptions.generate = 'ssr';
|
|
118
|
+
requiredCompilerOptions.hydratable = false;
|
|
119
|
+
|
|
120
|
+
if (type === 'template') {
|
|
121
|
+
// Templates need comments preserved for Cayo placeholders
|
|
122
|
+
requiredCompilerOptions.preserveComments = true;
|
|
123
|
+
}
|
|
124
|
+
} else {
|
|
125
|
+
// Cayo Components (DOM): client-side hydration
|
|
126
|
+
requiredCompilerOptions.generate = 'dom';
|
|
127
|
+
requiredCompilerOptions.hydratable = true;
|
|
89
128
|
}
|
|
90
129
|
|
|
91
130
|
let bundle;
|
|
@@ -94,18 +133,17 @@ export async function build(input, config, type = 'page') {
|
|
|
94
133
|
css: { code: '' },
|
|
95
134
|
dependencies: [],
|
|
96
135
|
};
|
|
97
|
-
|
|
98
|
-
let preprocessors = config.svelte.preprocess.length > 0
|
|
99
|
-
? config.svelte.preprocess
|
|
100
|
-
: [config.svelte.preprocess];
|
|
136
|
+
let preprocessors = getUserDefinedPreprocessors(config);
|
|
101
137
|
|
|
102
138
|
const options = {
|
|
103
139
|
...inputOptions(input),
|
|
104
140
|
plugins: [
|
|
141
|
+
...defaultRollupPlugins(),
|
|
105
142
|
svelte({
|
|
106
143
|
preprocess: [
|
|
107
144
|
...preprocessors,
|
|
108
145
|
],
|
|
146
|
+
...sveltePluginDefaults(),
|
|
109
147
|
compilerOptions: {
|
|
110
148
|
preserveWhitespace: true,
|
|
111
149
|
...config.svelte.compilerOptions,
|
|
@@ -113,7 +151,11 @@ export async function build(input, config, type = 'page') {
|
|
|
113
151
|
},
|
|
114
152
|
extensions: config.svelte.extensions,
|
|
115
153
|
}),
|
|
116
|
-
|
|
154
|
+
resolve({
|
|
155
|
+
...resolvePluginDefaults({
|
|
156
|
+
browser: isCayo,
|
|
157
|
+
}),
|
|
158
|
+
}),
|
|
117
159
|
...userRollupPlugins(config),
|
|
118
160
|
]
|
|
119
161
|
}
|
|
@@ -123,7 +123,7 @@ export async function processPage(content, page, _cayo, logger) {
|
|
|
123
123
|
} else {
|
|
124
124
|
if (cayoAssetCssElements) {
|
|
125
125
|
logger.log.info(
|
|
126
|
-
chalk.yellow.bold('Warning') + chalk.yellow(': No
|
|
126
|
+
chalk.yellow.bold('Warning') + chalk.yellow(': No <template cayo="css"> found in template, but there is CSS used in source files.'),
|
|
127
127
|
{ timestamp: true, clear: false, }
|
|
128
128
|
);
|
|
129
129
|
}
|
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
import logger from '../logger.js';
|
|
2
|
+
import chalk from 'chalk';
|
|
3
|
+
|
|
1
4
|
export class Renderer {
|
|
2
5
|
|
|
3
6
|
constructor(template) {
|
|
@@ -35,17 +38,44 @@ export class Renderer {
|
|
|
35
38
|
// Note: Q: why the `() => str` for 2nd replacement arg?
|
|
36
39
|
// A: In case there's dollar signs in that there string
|
|
37
40
|
// https://stackoverflow.com/questions/9423722/string-replace-weird-behavior-when-using-dollar-sign-as-replacement
|
|
41
|
+
// Check for deprecated %cayo.*% syntax and log deprecation warnings
|
|
42
|
+
// Use a more specific regex and avoid overlapping matches
|
|
43
|
+
const deprecatedPlaceholders = [];
|
|
44
|
+
const regex = /%cayo\.[a-zA-Z]+%/g;
|
|
45
|
+
let match;
|
|
46
|
+
while ((match = regex.exec(this.template.html)) !== null) {
|
|
47
|
+
deprecatedPlaceholders.push(match[0]);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
if (deprecatedPlaceholders.length > 0 && !this._deprecationWarningLogged) {
|
|
51
|
+
this._deprecationWarningLogged = true;
|
|
52
|
+
const uniquePlaceholders = [...new Set(deprecatedPlaceholders)];
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
logger.log.info(
|
|
56
|
+
chalk.yellow.bold('Deprecation Warning') + chalk.yellow(` [Page: ${page.name}]: Found deprecated placeholder syntax: ${uniquePlaceholders.join(', ')}. Please migrate to <template cayo="..."> syntax. \nMore info: https://github.com/matthew-ia/cayo#template-placeholder-migration`),
|
|
57
|
+
{ timestamp: true, clear: false }
|
|
58
|
+
);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
const finalHtml = this.template.html
|
|
62
|
+
// Strip placeholders wrapped in HTML comments
|
|
63
|
+
.replace(/<!--[\s\S]?%cayo\.\w+%[\s\S]*?(-->)/g, '')
|
|
64
|
+
// Inject markup in HTML comment placeholders
|
|
65
|
+
.replace(/<!--\s*\[cayo-css\]\s*-->/g, () => cssElements)
|
|
66
|
+
.replace(/<!--\s*\[cayo-head\]\s*-->/g, () => head)
|
|
67
|
+
.replace(/<!--\s*\[cayo-body\]\s*-->/g, () => html)
|
|
68
|
+
.replace(/<!--\s*\[cayo-title\]\s*-->/g, () => !head.includes('<title>') ? title() : '')
|
|
69
|
+
.replace(/<!--\s*\[cayo-script\]\s*-->/g, () => `<script type="module" src="./index.js"></script>`)
|
|
70
|
+
// Support deprecated %cayo.*% syntax for backward compatibility
|
|
71
|
+
.replace(/%cayo\.title%/g, () => !head.includes('<title>') ? title() : '')
|
|
72
|
+
.replace(/%cayo\.head%/g, () => head)
|
|
73
|
+
.replace(/%cayo\.body%/g, () => html)
|
|
74
|
+
.replace(/%cayo\.css%/g, () => cssElements)
|
|
75
|
+
.replace(/%cayo\.script%/g, () => `<script type="module" src="./index.js"></script>`);
|
|
76
|
+
|
|
38
77
|
return {
|
|
39
|
-
html:
|
|
40
|
-
// Strip placeholders wrapped in HTML comments
|
|
41
|
-
.replace(/<!--[\s\S]?%cayo\.\w+%[\s\S]*?(-->)/g, '')
|
|
42
|
-
// Inject markup in the cayo placeholders
|
|
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>`),
|
|
78
|
+
html: finalHtml,
|
|
49
79
|
css,
|
|
50
80
|
}
|
|
51
81
|
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Svelte preprocessor that transforms Cayo component imports
|
|
3
|
+
* from object references to string paths
|
|
4
|
+
*/
|
|
5
|
+
export function cayoComponentPreprocessor() {
|
|
6
|
+
return {
|
|
7
|
+
script({ content, attributes }) {
|
|
8
|
+
// Only process if the script contains .cayo.svelte imports
|
|
9
|
+
if (!content.includes('.cayo.svelte')) return;
|
|
10
|
+
|
|
11
|
+
// Transform: import Component from '$components/Component.cayo.svelte' or './components/Component.cayo.svelte'
|
|
12
|
+
// Into: import Component from '...'; Component.__cayoPath = 'Component.cayo.svelte';
|
|
13
|
+
const transformedContent = content.replace(
|
|
14
|
+
/import\s+(\w+)\s+from\s+['"]([^'"]*\/)?([^\/'"]+\.cayo\.svelte)['"]\s*;/g,
|
|
15
|
+
(match, varName, pathPrefix, filename) => {
|
|
16
|
+
return `${match}\n if (${varName}) ${varName}.__cayoPath = '${filename}';`;
|
|
17
|
+
}
|
|
18
|
+
);
|
|
19
|
+
|
|
20
|
+
return transformedContent !== content ? { code: transformedContent } : null;
|
|
21
|
+
}
|
|
22
|
+
};
|
|
23
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { cayoComponentPreprocessor } from './cayo-component.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Cayo preprocessor for Svelte
|
|
5
|
+
* Currently includes component import transformation
|
|
6
|
+
* Future preprocessors and config options can be added here
|
|
7
|
+
*/
|
|
8
|
+
export function cayoPreprocess(options = {}) {
|
|
9
|
+
return cayoComponentPreprocessor();
|
|
10
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cayo",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.5.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"scripts": {
|
|
6
6
|
"start": "node cayo dev --projectRoot test",
|
|
@@ -30,6 +30,7 @@
|
|
|
30
30
|
},
|
|
31
31
|
"homepage": "https://github.com/matthew-ia/cayo#readme",
|
|
32
32
|
"dependencies": {
|
|
33
|
+
"@rollup/plugin-commonjs": "^29.0.0",
|
|
33
34
|
"@rollup/plugin-json": "^4.1.0",
|
|
34
35
|
"@rollup/plugin-node-resolve": "^16.0.0",
|
|
35
36
|
"chalk": "^2.4.2",
|
package/scripts/build.js
CHANGED
|
@@ -36,6 +36,8 @@ function generateIndex(modules) {
|
|
|
36
36
|
for (const m of modules) {
|
|
37
37
|
js += `export { default as ${m[0]} } from '${m[1]}';\n`;
|
|
38
38
|
}
|
|
39
|
+
// Add preprocessor exports
|
|
40
|
+
js += `export { cayoPreprocess } from '../lib/preprocessors/index.js';\n`;
|
|
39
41
|
return { code: js };
|
|
40
42
|
}
|
|
41
43
|
|
package/src/cayo.svelte
CHANGED
|
@@ -1,8 +1,25 @@
|
|
|
1
1
|
<script>
|
|
2
2
|
import { getWarnings } from './cayo-warnings.js';
|
|
3
|
-
export let src;
|
|
3
|
+
export let src = undefined;
|
|
4
|
+
export let component = undefined; // New prop for component objects
|
|
4
5
|
export let attributes;
|
|
5
6
|
|
|
7
|
+
// Determine the actual source path
|
|
8
|
+
let actualSrc;
|
|
9
|
+
if (src) {
|
|
10
|
+
// Traditional string src prop
|
|
11
|
+
actualSrc = src;
|
|
12
|
+
} else if (component && component.__cayoPath) {
|
|
13
|
+
// Component object with extracted path
|
|
14
|
+
actualSrc = component.__cayoPath;
|
|
15
|
+
} else if (typeof component === 'string') {
|
|
16
|
+
// Component passed as string directly
|
|
17
|
+
actualSrc = component;
|
|
18
|
+
} else {
|
|
19
|
+
// Fallback error case
|
|
20
|
+
actualSrc = '';
|
|
21
|
+
}
|
|
22
|
+
|
|
6
23
|
// Save unserializable prop keys (during stringification)
|
|
7
24
|
// so we can report them later
|
|
8
25
|
const badProps = [];
|
|
@@ -21,9 +38,9 @@
|
|
|
21
38
|
|
|
22
39
|
// const props = toSource({...$$restProps})
|
|
23
40
|
const props = JSON.stringify({...$$restProps}, replacer);
|
|
24
|
-
const warnings = getWarnings(
|
|
41
|
+
const warnings = getWarnings(actualSrc, badProps);
|
|
25
42
|
const cayoInstanceData = {
|
|
26
|
-
'data-cayo-src': !warnings.invalidSrc ? `${
|
|
43
|
+
'data-cayo-src': !warnings.invalidSrc ? `${actualSrc}` : '',
|
|
27
44
|
'data-cayo-id': '', // will get set during prerender process based on the src
|
|
28
45
|
};
|
|
29
46
|
if (warnings) {
|
package/src/entry.svelte
CHANGED
package/template/cayo.config.js
CHANGED
|
@@ -3,12 +3,12 @@
|
|
|
3
3
|
<meta charset="UTF-8" />
|
|
4
4
|
<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>">
|
|
5
5
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
6
|
+
<template cayo="title"></template>
|
|
7
|
+
<template cayo="css"></template>
|
|
8
|
+
<template cayo="head"></template>
|
|
9
9
|
</head>
|
|
10
10
|
<body>
|
|
11
|
-
|
|
12
|
-
|
|
11
|
+
<template cayo="body"></template>
|
|
12
|
+
<template cayo="script"></template>
|
|
13
13
|
</body>
|
|
14
14
|
</html>
|
|
@@ -1,15 +1,28 @@
|
|
|
1
1
|
<script>
|
|
2
2
|
import { Cayo, Entry } from 'cayo';
|
|
3
|
+
import Counter from '../components/counter.cayo.svelte';
|
|
3
4
|
const heading = '🏝 Cayo';
|
|
4
5
|
</script>
|
|
5
6
|
|
|
6
7
|
<h1>{heading}</h1>
|
|
8
|
+
|
|
9
|
+
<p>Example with component import (recommended):</p>
|
|
10
|
+
<Cayo component={Counter} />
|
|
11
|
+
|
|
12
|
+
<p>Example with string path (classic):</p>
|
|
7
13
|
<Cayo src="counter.cayo.svelte" />
|
|
8
|
-
|
|
14
|
+
|
|
15
|
+
<Entry />
|
|
9
16
|
|
|
10
17
|
<style>
|
|
11
18
|
h1 {
|
|
12
19
|
text-align: center;
|
|
13
20
|
font-family:-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;
|
|
14
21
|
}
|
|
22
|
+
p {
|
|
23
|
+
text-align: center;
|
|
24
|
+
color: #888;
|
|
25
|
+
font-size: 0.9rem;
|
|
26
|
+
margin: 1rem 0 0.5rem 0;
|
|
27
|
+
}
|
|
15
28
|
</style>
|