cirrojs 0.0.4 → 0.0.5
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/CHANGELOG.md +11 -1
- package/dist/cli.js +1 -1
- package/dist/css-DDEJecy6.js +4 -0
- package/dist/index.d.ts +8 -54
- package/dist/index.js +1 -1
- package/dist/server.d.ts +50 -0
- package/dist/server.js +1 -0
- package/package.json +5 -1
- package/dist/css-BpSvZXlg.js +0 -4
package/CHANGELOG.md
CHANGED
|
@@ -13,6 +13,15 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
|
|
|
13
13
|
|
|
14
14
|
## [Unreleased]
|
|
15
15
|
|
|
16
|
+
## [0.0.5] - 2026-06-18
|
|
17
|
+
|
|
18
|
+
### Added
|
|
19
|
+
- New `cirrojs/server` entry point exporting the server-only API (`createIsland`, `createMarkdown`, and the `MarkdownConfig`, `RenderResult`, `ToC` types).
|
|
20
|
+
|
|
21
|
+
### Changed
|
|
22
|
+
- Moved `createIsland` and `createMarkdown` from the main entry point (`cirrojs`) to `cirrojs/server` to keep server-only dependencies (`react-dom/server`, remark/rehype/prismjs) out of the client bundle.
|
|
23
|
+
- Changed the `genCssFn` signature to take a single `GenCssFnOpt` options object (`{ mediaAtRule?, layer? }`) instead of positional arguments.
|
|
24
|
+
|
|
16
25
|
## [0.0.4] - 2026-06-17
|
|
17
26
|
|
|
18
27
|
### Added
|
|
@@ -32,7 +41,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
|
|
|
32
41
|
## 0.0.1 - 2026-06-15
|
|
33
42
|
- initial release
|
|
34
43
|
|
|
35
|
-
[Unreleased]: https://github.com/osawa-naotaka/cirro/compare/v0.0.
|
|
44
|
+
[Unreleased]: https://github.com/osawa-naotaka/cirro/compare/v0.0.5...HEAD
|
|
45
|
+
[0.0.5]: https://github.com/osawa-naotaka/cirro/compare/v0.0.4...v0.0.5
|
|
36
46
|
[0.0.4]: https://github.com/osawa-naotaka/cirro/compare/v0.0.3...v0.0.4
|
|
37
47
|
[0.0.3]: https://github.com/osawa-naotaka/cirro/compare/v0.0.2...v0.0.3
|
|
38
48
|
[0.0.2]: https://github.com/osawa-naotaka/cirro/compare/v0.0.1...v0.0.2
|
package/dist/cli.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{c as e,l as t,o as n,r}from"./css-
|
|
1
|
+
import{c as e,l as t,o as n,r}from"./css-DDEJecy6.js";import{Fragment as i,createElement as a}from"react";import{renderToStaticMarkup as o}from"react-dom/server";import{dirname as s,join as c,resolve as l}from"node:path";import{mkdir as u,readFile as d,writeFile as f}from"node:fs/promises";import{build as p,createServer as m,createServerModuleRunner as h}from"vite";import{createServer as g}from"node:http";function _(e,t,n){return a(i,null,e,a(`script`,{async:!0,type:`module`,src:t,key:`cirro-client`}),a(`link`,{rel:`stylesheet`,href:n,precedence:`default`,key:`cirro-css`}))}function v(e){for(let t of e.plugins){let e=t.api;if(t.name===`cirro`&&e?.options)return e.options}throw Error(`cirro: plugin not found in Vite config (did you add cirro() to plugins?)`)}async function y(){await p();let i=await m({server:{middlewareMode:!0,hmr:!1},appType:`custom`}),a=h(i.environments.ssr);try{let p=i.config,m=v(p),h=p.root,g=l(h,p.build.outDir),y=l(h,m.routes),b=JSON.parse(await d(c(g,`.vite/manifest.json`),`utf-8`))[`virtual:cirro/client`];if(!b)throw Error(`cirro: manifest entry "virtual:cirro/client" not found`);let x=`/${b.file}`,{routes:S,getCssRegistry:C,initCssRegistry:w}=await a.import(y);for(let i of n(S)){if(i.isCss){w(),o(i.render());let t=r(C()),n=c(g,e(i.url));await u(s(n),{recursive:!0}),await f(n,t),console.log(`wrote ${n} (url: ${i.url})`);continue}let n=`<!DOCTYPE html>${o(_(i.render(),x,i.cssPath))}`,a=c(g,t(i.url));await u(s(a),{recursive:!0}),await f(a,n),console.log(`wrote ${a} (url: ${i.url})`)}}finally{await i.close()}}function b(e,t){let n=[t,t.replaceAll(`\\`,`/`)];for(let t of Object.values(e.environments)){let e=t.moduleGraph;if(!e)continue;let r=new Set,i=t=>{if(!r.has(t)){r.add(t),e.invalidateModule(t);for(let e of t.importers)i(e)}};for(let t of n){let n=e.getModulesByFile(t);if(n)for(let e of n)i(e)}}}async function x(e=5173){let t=await m({server:{middlewareMode:!0},appType:`custom`}),i=h(t.environments.ssr),a=v(t.config),c=t.config.root,u=l(c,a.routes),d=s(l(c,a.islands)).replaceAll(`\\`,`/`),f=g((e,a)=>{t.middlewares(e,a,async()=>{let s=e.url??`/`;try{let{routes:e,getCssRegistry:c,initCssRegistry:l}=await i.import(u),d=n(e);if(s.endsWith(`.css`)){let e=d.find(e=>e.isCss&&e.url===s);if(!e){a.statusCode=404,a.end();return}l(),o(e.render());let t=r(c());a.statusCode=200,a.setHeader(`Content-Type`,`text/css; charset=utf-8`),a.end(t);return}let f=new URL(s,`http://localhost`).pathname.replace(/\/+$/,``)||`/`,p=d.find(e=>(e.url.replace(/\/+$/,``)||`/`)===f);if(!p){a.statusCode=404,a.setHeader(`Content-Type`,`text/html; charset=utf-8`),a.end(`<!DOCTYPE html><meta charset="utf-8"><h1>404 Not Found</h1>`);return}let m=`<!DOCTYPE html>${o(_(p.render(),`/@id/__x00__virtual:cirro/client`,p.cssPath))}`;m=await t.transformIndexHtml(s,m),a.statusCode=200,a.setHeader(`Content-Type`,`text/html; charset=utf-8`),a.end(m)}catch(e){a.statusCode=500,a.end(String(e))}})}),p=`${l(c,a.watchDir??`./src`).replaceAll(`\\`,`/`).replace(/\/+$/,``)}/`;t.watcher.on(`change`,e=>{let n=e.replaceAll(`\\`,`/`);n.startsWith(d)||n.startsWith(p)&&(b(t,e),t.ws.send({type:`full-reload`}))}),f.listen(e,()=>{console.log(`cirro dev: http://localhost:${e}`)})}async function S(e){let t=e[0];t===`dev`?await x():t===`build`?await y():(console.error(`usage: cirro <dev|build>`),process.exit(1))}export{S as main};
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
function e(e){return e}function t(e){let t=[];for(let n of e)if(`getStaticPaths`in n){for(let e of n.getStaticPaths())t.push({url:n.path(e),isCss:!1,cssPath:n.cssPath,render:()=>n.component({params:e})});t.push({url:n.cssPath,isCss:!0,cssPath:n.cssPath,render:()=>n.component({params:n.getStaticPaths()[0]})})}else t.push({url:n.path,isCss:!1,cssPath:i(n.path,`index.css`),render:()=>n.component({params:{}})}),t.push({url:i(n.path,`index.css`),isCss:!0,cssPath:i(n.path,`index.css`),render:()=>n.component({params:{}})});return t}function n(e){return e===`/`?`index.html`:`${e.replace(/^\/+|\/+$/g,``)}/index.html`}function r(e){return e===`/`?`index.css`:`${e.replace(/^\/+|\/+$/g,``)}`}function i(...e){return e.reduce((e,t)=>e.endsWith(`/`)&&t.startsWith(`/`)?`${e}${t.substring(1)}`:e.endsWith(`/`)||t.startsWith(`/`)?`${e}${t}`:`${e}/${t}`,``)}let a=[];function o(e,t){a.push([e,t])}function s(){a=[]}function c(){return a}function l(e,t){let n=t?.selector??`&`,r=t?.atrules??[],i=p(e),a=`${t?.name??`cirro`}-${i.toString(16)}`;return f([...r,n],e,a),a}function u(e){let t=[];return e.layer&&t.push(`@layer ${e.layer}`),e.mediaAtRule&&t.push(`@media (${e.mediaAtRule})`),(e,n)=>l(e,{atrules:t,name:n?.name,selector:n?.selector})}function d(e){let t=`@charset "utf-8";
|
|
2
|
+
@layer base, font, low, main, high;
|
|
3
|
+
`;for(let[n,r]of e)t+=n.reduceRight((e,t)=>`${t} { ${e} }`,Object.entries(r).map(([e,t])=>`${e.replaceAll(`_`,`-`)}: ${t};`).join(` `)),t+=`
|
|
4
|
+
`;return t}function f(e,t,n){o(e.map(e=>e.replaceAll(`&`,`.${n}`)),t)}function p(...e){return m(e.map(e=>JSON.stringify(e)).join(``))}function m(e){let t=5381;for(let n of[...e])t=(t<<5)+t+n.charCodeAt(0)&4294967295;return t>>>0}export{s as a,r as c,c as i,n as l,u as n,t as o,d as r,e as s,l as t};
|
package/dist/index.d.ts
CHANGED
|
@@ -1,52 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { ToC, ToC as ToC$1 } from "remark-export-toc";
|
|
3
|
-
import { PluggableList } from "unified";
|
|
4
|
-
import { Schema } from "hast-util-sanitize";
|
|
1
|
+
import { ReactElement } from "react";
|
|
5
2
|
|
|
6
|
-
//#region src/island.d.ts
|
|
7
|
-
type IslandRegistry = Record<string, ComponentType<any>>;
|
|
8
|
-
declare function createIsland<R extends IslandRegistry>(islands: R): <K extends keyof R & string>({
|
|
9
|
-
name,
|
|
10
|
-
props
|
|
11
|
-
}: {
|
|
12
|
-
name: K;
|
|
13
|
-
props: ComponentProps<R[K]>;
|
|
14
|
-
}) => import("react").DetailedReactHTMLElement<{
|
|
15
|
-
"data-island": K;
|
|
16
|
-
"data-props": string;
|
|
17
|
-
dangerouslySetInnerHTML: {
|
|
18
|
-
__html: string;
|
|
19
|
-
};
|
|
20
|
-
}, HTMLElement>;
|
|
21
|
-
//#endregion
|
|
22
|
-
//#region src/markdown.d.ts
|
|
23
|
-
interface MarkdownConfig {
|
|
24
|
-
remarkPlugins?: PluggableList;
|
|
25
|
-
rehypePlugins?: PluggableList;
|
|
26
|
-
sanitizeSchema?: (defaults: Schema) => Schema;
|
|
27
|
-
toc?: boolean | {
|
|
28
|
-
prefix?: string;
|
|
29
|
-
startLevel?: number;
|
|
30
|
-
};
|
|
31
|
-
highlight?: boolean;
|
|
32
|
-
}
|
|
33
|
-
interface RenderResult {
|
|
34
|
-
body: ReactElement;
|
|
35
|
-
toc: ToC$1[];
|
|
36
|
-
}
|
|
37
|
-
declare function createMarkdown(config?: MarkdownConfig): {
|
|
38
|
-
Markdown: ({
|
|
39
|
-
source,
|
|
40
|
-
className
|
|
41
|
-
}: {
|
|
42
|
-
source: string;
|
|
43
|
-
className?: string;
|
|
44
|
-
}) => ReactElement;
|
|
45
|
-
render: (source: string, options?: {
|
|
46
|
-
className?: string;
|
|
47
|
-
}) => RenderResult;
|
|
48
|
-
};
|
|
49
|
-
//#endregion
|
|
50
3
|
//#region src/router.d.ts
|
|
51
4
|
type Params = Record<string, string>;
|
|
52
5
|
type StaticRoute = {
|
|
@@ -547,10 +500,11 @@ type CssOpt = {
|
|
|
547
500
|
selector?: string;
|
|
548
501
|
};
|
|
549
502
|
declare function css(properties: Properties, opt?: CssOpt): string;
|
|
550
|
-
type CssFnT = (properties: Properties, opt?:
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
503
|
+
type CssFnT = (properties: Properties, opt?: Omit<CssOpt, "atrules">) => string;
|
|
504
|
+
type GenCssFnOpt = {
|
|
505
|
+
mediaAtRule?: string;
|
|
506
|
+
layer?: string;
|
|
507
|
+
};
|
|
508
|
+
declare function genCssFn(opt: GenCssFnOpt): CssFnT;
|
|
555
509
|
//#endregion
|
|
556
|
-
export { type AnyRoute, type CssOpt, type DynamicRoute, type
|
|
510
|
+
export { type AnyRoute, type CssOpt, type DynamicRoute, type Params, type Properties, type ResolvedPage, type StaticRoute, css, expandRoutes, genCssFn, getCssRegistry, initCssRegistry, route, urlToFilePath };
|
package/dist/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{a as e,i as t,l as n,n as r,o as i,s as a,t as o}from"./css-
|
|
1
|
+
import{a as e,i as t,l as n,n as r,o as i,s as a,t as o}from"./css-DDEJecy6.js";export{o as css,i as expandRoutes,r as genCssFn,t as getCssRegistry,e as initCssRegistry,a as route,n as urlToFilePath};
|
package/dist/server.d.ts
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { ComponentProps, ComponentType, ReactElement } from "react";
|
|
2
|
+
import { ToC, ToC as ToC$1 } from "remark-export-toc";
|
|
3
|
+
import { PluggableList } from "unified";
|
|
4
|
+
import { Schema } from "hast-util-sanitize";
|
|
5
|
+
|
|
6
|
+
//#region src/island.d.ts
|
|
7
|
+
type IslandRegistry = Record<string, ComponentType<any>>;
|
|
8
|
+
declare function createIsland<R extends IslandRegistry>(islands: R): <K extends keyof R & string>({
|
|
9
|
+
name,
|
|
10
|
+
props
|
|
11
|
+
}: {
|
|
12
|
+
name: K;
|
|
13
|
+
props: ComponentProps<R[K]>;
|
|
14
|
+
}) => import("react").DetailedReactHTMLElement<{
|
|
15
|
+
"data-island": K;
|
|
16
|
+
"data-props": string;
|
|
17
|
+
dangerouslySetInnerHTML: {
|
|
18
|
+
__html: string;
|
|
19
|
+
};
|
|
20
|
+
}, HTMLElement>;
|
|
21
|
+
//#endregion
|
|
22
|
+
//#region src/markdown.d.ts
|
|
23
|
+
interface MarkdownConfig {
|
|
24
|
+
remarkPlugins?: PluggableList;
|
|
25
|
+
rehypePlugins?: PluggableList;
|
|
26
|
+
sanitizeSchema?: (defaults: Schema) => Schema;
|
|
27
|
+
toc?: boolean | {
|
|
28
|
+
prefix?: string;
|
|
29
|
+
startLevel?: number;
|
|
30
|
+
};
|
|
31
|
+
highlight?: boolean;
|
|
32
|
+
}
|
|
33
|
+
interface RenderResult {
|
|
34
|
+
body: ReactElement;
|
|
35
|
+
toc: ToC$1[];
|
|
36
|
+
}
|
|
37
|
+
declare function createMarkdown(config?: MarkdownConfig): {
|
|
38
|
+
Markdown: ({
|
|
39
|
+
source,
|
|
40
|
+
className
|
|
41
|
+
}: {
|
|
42
|
+
source: string;
|
|
43
|
+
className?: string;
|
|
44
|
+
}) => ReactElement;
|
|
45
|
+
render: (source: string, options?: {
|
|
46
|
+
className?: string;
|
|
47
|
+
}) => RenderResult;
|
|
48
|
+
};
|
|
49
|
+
//#endregion
|
|
50
|
+
export { type MarkdownConfig, type RenderResult, type ToC, createIsland, createMarkdown };
|
package/dist/server.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{createElement as e}from"react";import{renderToString as t}from"react-dom/server";import n from"rehype-prism";import r,{defaultSchema as i}from"rehype-sanitize";import a from"rehype-stringify";import o from"remark-export-toc";import s from"remark-parse";import c from"remark-rehype";import{unified as l}from"unified";import{jsx as u}from"react/jsx-runtime";function d(n){return function({name:r,props:i}){let a=t(e(n[r],i));return e(`div`,{"data-island":r,"data-props":JSON.stringify(i),dangerouslySetInnerHTML:{__html:a}})}}function f(e={}){let t={prefix:`heading`,startLevel:2,...typeof e.toc==`object`?e.toc:{}},d={...i,clobber:(i.clobber??[]).filter(e=>e!==`id`)},f=e.sanitizeSchema?e.sanitizeSchema(d):d,p=l().use(s).use(e.remarkPlugins??[]).use(e.toc?[[o,t]]:[]).use(c).use(e.rehypePlugins??[]).use(r,f).use(e.highlight?[n]:[]).use(a).freeze();function m(e,t){return u(`div`,{className:t,dangerouslySetInnerHTML:{__html:e}})}function h(e,t){let n=p.processSync(e),r=n.data.toc??[];return{body:m(String(n),t?.className),toc:r}}function g({source:e,className:t}){return h(e,{className:t}).body}return{Markdown:g,render:h}}export{d as createIsland,f as createMarkdown};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cirrojs",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.5",
|
|
4
4
|
"description": "React islands SSG with strict CSP (no unsafe-inline). Vite-based, MPA-first.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -19,6 +19,10 @@
|
|
|
19
19
|
"types": "./dist/index.d.ts",
|
|
20
20
|
"default": "./dist/index.js"
|
|
21
21
|
},
|
|
22
|
+
"./server": {
|
|
23
|
+
"types": "./dist/server.d.ts",
|
|
24
|
+
"default": "./dist/server.js"
|
|
25
|
+
},
|
|
22
26
|
"./vite": {
|
|
23
27
|
"types": "./dist/vite.d.ts",
|
|
24
28
|
"default": "./dist/vite.js"
|
package/dist/css-BpSvZXlg.js
DELETED
|
@@ -1,4 +0,0 @@
|
|
|
1
|
-
import{resolve as e}from"node:path";function t(e){return e}function n(t){let n=[];for(let r of t)if(`getStaticPaths`in r){for(let e of r.getStaticPaths())n.push({url:r.path(e),isCss:!1,cssPath:r.cssPath,render:()=>r.component({params:e})});n.push({url:r.cssPath,isCss:!0,cssPath:r.cssPath,render:()=>r.component({params:r.getStaticPaths()[0]})})}else n.push({url:r.path,isCss:!1,cssPath:e(r.path,`index.css`),render:()=>r.component({params:{}})}),n.push({url:e(r.path,`index.css`),isCss:!0,cssPath:e(r.path,`index.css`),render:()=>r.component({params:{}})});return n}function r(e){return e===`/`?`index.html`:`${e.replace(/^\/+|\/+$/g,``)}/index.html`}function i(e){return e===`/`?`index.css`:`${e.replace(/^\/+|\/+$/g,``)}`}let a=[];function o(e,t){a.push([e,t])}function s(){a=[]}function c(){return a}function l(e,t){let n=t?.selector??`&`,r=t?.atrules??[],i=p(e),a=`${t?.name??`cirro`}-${i.toString(16)}`;return f([...r,n],e,a),a}function u(e,t=`main`){return(n,r)=>l(n,{atrules:[`@layer ${t}`,`@media (${e})`],name:r?.name,selector:r?.selector})}function d(e){let t=`@charset "utf-8";
|
|
2
|
-
@layer base, font, low, main, high;
|
|
3
|
-
`;for(let[n,r]of e)t+=n.reduceRight((e,t)=>`${t} { ${e} }`,Object.entries(r).map(([e,t])=>`${e.replaceAll(`_`,`-`)}: ${t};`).join(` `)),t+=`
|
|
4
|
-
`;return t}function f(e,t,n){o(e.map(e=>e.replaceAll(`&`,`.${n}`)),t)}function p(...e){return m(e.map(e=>JSON.stringify(e)).join(``))}function m(e){let t=5381;for(let n of[...e])t=(t<<5)+t+n.charCodeAt(0)&4294967295;return t>>>0}export{s as a,i as c,c as i,r as l,u as n,n as o,d as r,t as s,l as t};
|