cirrojs 0.0.5 → 0.0.7

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 CHANGED
@@ -13,6 +13,16 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
13
13
 
14
14
  ## [Unreleased]
15
15
 
16
+ ## [0.0.7] - 2026-06-19
17
+
18
+ ### Added
19
+ - The `Island` component now accepts an optional `className` prop, which is applied to its top-level wrapper element.
20
+
21
+ ## [0.0.6] - 2026-06-19
22
+
23
+ ### Fixed
24
+ - Fixed a bug that was causing duplicate CSS to be output.
25
+
16
26
  ## [0.0.5] - 2026-06-18
17
27
 
18
28
  ### Added
@@ -41,7 +51,9 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
41
51
  ## 0.0.1 - 2026-06-15
42
52
  - initial release
43
53
 
44
- [Unreleased]: https://github.com/osawa-naotaka/cirro/compare/v0.0.5...HEAD
54
+ [Unreleased]: https://github.com/osawa-naotaka/cirro/compare/v0.0.7...HEAD
55
+ [0.0.7]: https://github.com/osawa-naotaka/cirro/compare/v0.0.6...v0.0.7
56
+ [0.0.6]: https://github.com/osawa-naotaka/cirro/compare/v0.0.5...v0.0.6
45
57
  [0.0.5]: https://github.com/osawa-naotaka/cirro/compare/v0.0.4...v0.0.5
46
58
  [0.0.4]: https://github.com/osawa-naotaka/cirro/compare/v0.0.3...v0.0.4
47
59
  [0.0.3]: https://github.com/osawa-naotaka/cirro/compare/v0.0.2...v0.0.3
package/dist/cli.js CHANGED
@@ -1 +1 @@
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};
1
+ import{i as e,r as t,s as n,t as r}from"./router-52EuPj-F.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 r(S)){if(i.isCss){w(),o(i.render());let e=n(C()),r=c(g,t(i.url));await u(s(r),{recursive:!0}),await f(r,e),console.log(`wrote ${r} (url: ${i.url})`);continue}let r=`<!DOCTYPE html>${o(_(i.render(),x,i.cssPath))}`,a=c(g,e(i.url));await u(s(a),{recursive:!0}),await f(a,r),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=r(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=n(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};
package/dist/index.d.ts CHANGED
@@ -1,33 +1,5 @@
1
1
  import { ReactElement } from "react";
2
2
 
3
- //#region src/router.d.ts
4
- type Params = Record<string, string>;
5
- type StaticRoute = {
6
- path: string;
7
- component: (props: {
8
- params: Record<string, never>;
9
- }) => ReactElement;
10
- };
11
- type DynamicRoute<P extends Params = Params> = {
12
- path: (params: P) => string;
13
- cssPath: string;
14
- getStaticPaths: () => P[];
15
- component: (props: {
16
- params: P;
17
- }) => ReactElement;
18
- };
19
- type AnyRoute = StaticRoute | DynamicRoute<any>;
20
- declare function route<P extends Params>(def: DynamicRoute<P>): DynamicRoute<P>;
21
- declare function route(def: StaticRoute): StaticRoute;
22
- type ResolvedPage = {
23
- url: string;
24
- isCss: boolean;
25
- cssPath: string;
26
- render: () => ReactElement;
27
- };
28
- declare function expandRoutes(routes: AnyRoute[]): ResolvedPage[];
29
- declare function urlToFilePath(url: string): string;
30
- //#endregion
31
3
  //#region src/properties.d.ts
32
4
  type AlignContentBaseKeyword = "normal" | "start" | "center" | "end" | "flex-start" | "flex-end" | "baseline" | "first baseline" | "last baseline" | "space-between" | "space-around" | "space-evenly" | "stretch";
33
5
  type AlignContentKeyword = AlignContentBaseKeyword | ["safe", AlignContentBaseKeyword] | ["unsafe", AlignContentBaseKeyword];
@@ -489,7 +461,7 @@ type Properties = Partial<{
489
461
  }>;
490
462
  //#endregion
491
463
  //#region src/registry.d.ts
492
- type Registry = [string[], Partial<Properties>][];
464
+ type Registry = Map<string, [string[], Partial<Properties>]>;
493
465
  declare function initCssRegistry(): void;
494
466
  declare function getCssRegistry(): Registry;
495
467
  //#endregion
@@ -507,4 +479,32 @@ type GenCssFnOpt = {
507
479
  };
508
480
  declare function genCssFn(opt: GenCssFnOpt): CssFnT;
509
481
  //#endregion
482
+ //#region src/router.d.ts
483
+ type Params = Record<string, string>;
484
+ type StaticRoute = {
485
+ path: string;
486
+ component: (props: {
487
+ params: Record<string, never>;
488
+ }) => ReactElement;
489
+ };
490
+ type DynamicRoute<P extends Params = Params> = {
491
+ path: (params: P) => string;
492
+ cssPath: string;
493
+ getStaticPaths: () => P[];
494
+ component: (props: {
495
+ params: P;
496
+ }) => ReactElement;
497
+ };
498
+ type AnyRoute = StaticRoute | DynamicRoute<any>;
499
+ declare function route<P extends Params>(def: DynamicRoute<P>): DynamicRoute<P>;
500
+ declare function route(def: StaticRoute): StaticRoute;
501
+ type ResolvedPage = {
502
+ url: string;
503
+ isCss: boolean;
504
+ cssPath: string;
505
+ render: () => ReactElement;
506
+ };
507
+ declare function expandRoutes(routes: AnyRoute[]): ResolvedPage[];
508
+ declare function urlToFilePath(url: string): string;
509
+ //#endregion
510
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-DDEJecy6.js";export{o as css,i as expandRoutes,r as genCssFn,t as getCssRegistry,e as initCssRegistry,a as route,n as urlToFilePath};
1
+ import{a as e,c as t,i as n,l as r,n as i,o as a,t as o}from"./router-52EuPj-F.js";export{e as css,o as expandRoutes,a as genCssFn,t as getCssRegistry,r as initCssRegistry,i as route,n as urlToFilePath};
@@ -0,0 +1,4 @@
1
+ const e=new Map;function t(t,n,r){e.set(t,[n,r])}function n(){e.clear()}function r(){return e}function i(e,t){let n=t?.selector??`&`,r=t?.atrules??[],i=c({selector:n,atrules:r,properties:e}),a=`${t?.name??`cirro`}-${i.toString(16)}`;return s([...r,n],e,a),a}function a(e){let t=[];return e.layer&&t.push(`@layer ${e.layer}`),e.mediaAtRule&&t.push(`@media (${e.mediaAtRule})`),(e,n)=>i(e,{atrules:t,name:n?.name,selector:n?.selector})}function o(e){let t=`@charset "utf-8";
2
+ @layer base, font, low, main, high;
3
+ `;for(let[n,[r,i]]of e)t+=r.reduceRight((e,t)=>`${t} { ${e} }`,Object.entries(i).map(([e,t])=>`${e.replaceAll(`_`,`-`)}: ${t};`).join(` `)),t+=`
4
+ `;return t}function s(e,n,r){t(r,e.map(e=>e.replaceAll(`&`,`.${r}`)),n)}function c(...e){return l(e.map(e=>JSON.stringify(e)).join(``))}function l(e){let t=5381;for(let n of[...e])t=(t<<5)+t+n.charCodeAt(0)&4294967295;return t>>>0}function u(e){return e}function d(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:m(n.path,`index.css`),render:()=>n.component({params:{}})}),t.push({url:m(n.path,`index.css`),isCss:!0,cssPath:m(n.path,`index.css`),render:()=>n.component({params:{}})});return t}function f(e){return e===`/`?`index.html`:`${e.replace(/^\/+|\/+$/g,``)}/index.html`}function p(e){return e===`/`?`index.css`:`${e.replace(/^\/+|\/+$/g,``)}`}function m(...e){return e.reduce((e,t)=>e.endsWith(`/`)&&t.startsWith(`/`)?`${e}${t.substring(1)}`:e.endsWith(`/`)||t.startsWith(`/`)?`${e}${t}`:`${e}/${t}`,``)}export{i as a,r as c,f as i,n as l,u as n,a as o,p as r,o as s,d as t};
package/dist/server.d.ts CHANGED
@@ -7,11 +7,14 @@ import { Schema } from "hast-util-sanitize";
7
7
  type IslandRegistry = Record<string, ComponentType<any>>;
8
8
  declare function createIsland<R extends IslandRegistry>(islands: R): <K extends keyof R & string>({
9
9
  name,
10
- props
10
+ props,
11
+ className
11
12
  }: {
12
13
  name: K;
13
14
  props: ComponentProps<R[K]>;
15
+ className?: string;
14
16
  }) => import("react").DetailedReactHTMLElement<{
17
+ className: string | undefined;
15
18
  "data-island": K;
16
19
  "data-props": string;
17
20
  dangerouslySetInnerHTML: {
package/dist/server.js CHANGED
@@ -1 +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};
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,className:a}){let o=t(e(n[r],i));return e(`div`,{className:a,"data-island":r,"data-props":JSON.stringify(i),dangerouslySetInnerHTML:{__html:o}})}}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.5",
3
+ "version": "0.0.7",
4
4
  "description": "React islands SSG with strict CSP (no unsafe-inline). Vite-based, MPA-first.",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -1,4 +0,0 @@
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};