@barocss/server 0.8.1 → 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/README.md CHANGED
@@ -1,5 +1,7 @@
1
1
  # @barocss/server
2
2
 
3
+ > **Rendering untrusted class strings (AI output, CMS, users)?** See the [security guide](../../apps/barocss-docs/docs/guide/security.md).
4
+
3
5
  [![npm version](https://img.shields.io/npm/v/@barocss/server.svg)](https://www.npmjs.com/package/@barocss/server)
4
6
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
5
7
  [![TypeScript](https://img.shields.io/badge/TypeScript-5.0+-blue.svg)](https://www.typescriptlang.org/)
@@ -95,8 +97,8 @@ const config = {
95
97
  theme: { extend: { // your own theme: literal values, not var(--build-vars)
96
98
  colors: { brand: '#2563eb' },
97
99
  spacing: { gutter: '1.5rem' }, // named spacing: p-gutter
98
- borderRadius: { lg: '0.75rem' }, // override existing keys; new radius/font names go in utilities
99
- fontFamily: { sans: ['Inter', 'sans-serif'] },
100
+ borderRadius: { lg: '0.75rem', card: '1.25rem' }, // override rounded-lg; new keys work too: rounded-card
101
+ fontFamily: { sans: ['Inter', 'sans-serif'], display: ['Fraunces', 'serif'] }, // font-display
100
102
  } },
101
103
  utilities: { 'max-w-app': { 'max-width': '48rem', 'margin-inline': 'auto' } }, // static @utility rules; `@utility name-*` unsupported
102
104
  };
package/dist/index.cjs CHANGED
@@ -1,6 +1,6 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const h=require("@barocss/kit"),g="data-barocss-ssr",C={amp:"&",lt:"<",gt:">",quot:'"',apos:"'",nbsp:" ",colon:":",sol:"/",lsqb:"[",rsqb:"]",num:"#",percnt:"%",lpar:"(",rpar:")",comma:",",period:".",excl:"!",tab:" ",newline:`
2
- `};function S(c){return c.includes("&")?c.replace(/&(#x[0-9a-f]+|#\d+|[a-z]+);/gi,(s,t)=>{if(t[0]==="#"){const e=t[1]==="x"||t[1]==="X"?parseInt(t.slice(2),16):parseInt(t.slice(1),10);return e>0&&e<=1114111?String.fromCodePoint(e):s}return C[t.toLowerCase()]??s}):c}const u=/<[a-zA-Z][^\s/>]*/g,p=/\s+([^\s"'>/=]+)(?:\s*=\s*(?:"([^"]*)"|'([^']*)'|([^\s"'=<>`]+)))?|\s*\//y,d=/\s*>/y;function y(c){const s=c.toLowerCase(),t=/<!--|<(script|style)\b/g;let e="",i=0,r;for(;r=t.exec(s);){e+=c.slice(i,r.index)+" ";let n;if(r[1]){const o=s.indexOf("</"+r[1],r.index+r[0].length);n=o<0?-1:s.indexOf(">",o),n>=0&&(n+=1)}else{const o=s.indexOf("-->",r.index+4);n=o<0?-1:o+3}if(n<0)return e;i=t.lastIndex=n}return e+c.slice(i)}function w(c){const s=y(c),t=new Set;for(u.lastIndex=0;u.exec(s);){let e=u.lastIndex,i;const r=[];for(p.lastIndex=e;(i=p.exec(s))&&i[0];p.lastIndex=e)e=p.lastIndex,i[1]?.toLowerCase()==="class"&&r.push(i[2]??i[3]??i[4]??"");if(d.lastIndex=e,!d.test(s)){u.lastIndex=e;continue}u.lastIndex=d.lastIndex;for(const n of r)for(const o of S(n).split(/\s+/))o&&t.add(o)}return[...t]}function k(c){return c.replace(/\\([0-9a-fA-F]{1,6})\s?|\\(.)/g,(s,t,e)=>t?String.fromCodePoint(parseInt(t,16)):e)}function T(c){const s=[];let t=0,e=0;for(let i=0;i<c.length;i++){const r=c[i];r==="\\"?i++:r==="("||r==="["?t++:r===")"||r==="]"?t--:r===","&&t===0&&(s.push(c.slice(e,i)),e=i+1)}return s.push(c.slice(e)),s}const I=/^\s*(?::(?:where|is)\(\s*)?\.((?:\\[0-9a-fA-F]{1,6}\s?|\\.|[\w-]|[^\x00-\x7F])+)/,v=/(^|[\s,(]):(root|host)\b/;function A(c){const s={classes:new Set,vars:new Set,properties:new Set,keyframes:new Set,layerStatement:!1},t=[];let e="";const i=r=>{if(t.some(n=>v.test(n)))for(const n of r.matchAll(/(?:^|;)\s*(--[\w-]+)\s*:/g))s.vars.add(n[1])};for(let r=0;r<c.length;r++){const n=c[r];if(n==="/"&&c[r+1]==="*"){const o=c.indexOf("*/",r+2);r=o<0?c.length:o+1;continue}if(n==='"'||n==="'"){let o=r+1;for(;o<c.length&&c[o]!==n;)o+=c[o]==="\\"?2:1;e+=c.slice(r,o+1),r=o;continue}if(n==="\\"){e+=c.slice(r,r+2),r++;continue}if(n==="{"){const o=e.lastIndexOf(";");o>=0&&i(e.slice(0,o+1));const a=e.slice(o+1).trim();e="",t.push(a);const l=/^@([\w-]+)\s*([\s\S]*)$/.exec(a);if(l){const f=l[1].toLowerCase();f==="property"?s.properties.add(l[2].trim()):f.endsWith("keyframes")&&s.keyframes.add(l[2].trim().replace(/^["']|["']$/g,""))}else if(!a.startsWith("&"))for(const f of T(a)){const x=I.exec(f);x&&s.classes.add(k(x[1]))}continue}if(n==="}"){i(e),e="",t.pop();continue}if(n===";"&&t.length===0){/^\s*@layer\b/.test(e)&&(s.layerStatement=!0),e="";continue}e+=n}return s}function R(c,s={}){const t=s.nonce?` nonce="${s.nonce.replace(/[&"<>]/g,e=>`&#${e.charCodeAt(0)};`)}"`:"";return`<style ${g}${t}>${c.replace(/<\/(style)/gi,"<\\/$1")}</style>`}const m=c=>[...c.matchAll(/var\((--[\w-]+)/g)].map(s=>s[1]);class E{constructor(s={},t={}){this.classCache=new Map,this.themeDefs=null,this.skipCache=new Map,this.cacheSize=Math.max(0,t.cacheSize??1e4),this.setConfig(s)}setConfig(s){this.context=h.createContext(s),this.classCache.clear(),this.themeDefs=null}parseClass(s){return h.parseClassToAst(s,this.context)}generateCss(s){return this.sheet(s.split(/\s+/).filter(Boolean))}generateCssForHtml(s,t={}){const e=typeof s=="string"?w(s):[...new Set(s.flatMap(n=>n.split(/\s+/)).filter(Boolean))],i=t.skip;if(i===void 0)return this.sheet(e);if(typeof i=="string"){const n=this.skipDefs(i);return this.sheet(e.filter(o=>!n.classes.has(o)),n)}const r=i instanceof Set?i:new Set(i);return this.sheet(e.filter(n=>!r.has(n)))}skipDefs(s){let t=this.skipCache.get(s);return t||(this.skipCache.size>=4&&this.skipCache.delete(this.skipCache.keys().next().value),this.skipCache.set(s,t=A(s))),t}sheet(s,t){const e=s.map(a=>this.entryFor(a));let i=this.uniqueRoots(e.flatMap(a=>a.roots));t&&(i=i.filter(({css:a,dedupeKey:l})=>{if(l.startsWith("--"))return!t.properties.has(l);const f=/^\s*@(?:-[\w]+-)?keyframes\s+([^\s{]+)/.exec(a)?.[1];return!f||!t.keyframes.has(f)}));const r=this.sortRules(e.filter(a=>a.css)),n=[...i.flatMap(a=>a.refs),...r.flatMap(a=>a.refs)],o=this.themeVarsBlock(n,t?.vars);return[...o?[o]:[],...i.map(a=>a.css),...r.map(a=>a.css)].join(`
3
- `)}entryFor(s){const t=this.classCache.get(s);if(t)return this.classCache.delete(s),this.classCache.set(s,t),t;const e={css:"",key:null,refs:[],roots:[]};for(const{css:i,rootCssList:r}of h.generateCssRules(s,this.context)){i&&(e.css=i);for(const n of r){if(!n)continue;const o=/^\s*@property\s+(--[\w-]+)/.exec(n)?.[1]??n;e.roots.push({css:n,dedupeKey:o,refs:m(n)})}}return e.css&&(e.key=h.ruleSortKey(e.css),e.refs=m(e.css)),this.cacheSize>0&&(this.classCache.size>=this.cacheSize&&this.classCache.delete(this.classCache.keys().next().value),this.classCache.set(s,e)),e}generateCssForClasses(s){return s.map(t=>({className:t,css:this.generateCss(t)}))}uniqueRoots(s){const t=new Set;return s.filter(({dedupeKey:e})=>!t.has(e)&&!!t.add(e))}sortRules(s){return s.map((t,e)=>({entry:t,i:e})).sort((t,e)=>h.compareKeys(t.entry.key,e.entry.key)||t.i-e.i).map(({entry:t})=>t)}themeVarsBlock(s,t){const e=s;if(e.length===0)return"";let i=this.themeDefs;if(!i){i=this.themeDefs=new Map;for(const n of this.context.themeToCssVars().matchAll(/^\s*(--[\w-]+):\s*(.+);$/gm))i.set(n[1],n[2])}const r=new Map;for(;e.length;){const n=e.pop(),o=i.get(n);o===void 0||r.has(n)||t?.has(n)||(r.set(n,o),e.push(...m(o)))}return r.size===0?"":`:root,:host {
4
- `+[...r].map(([n,o])=>` ${n}: ${o};`).join(`
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});let e=require("@barocss/kit");var t=`data-barocss-ssr`,n={amp:`&`,lt:`<`,gt:`>`,quot:`"`,apos:`'`,nbsp:`\xA0`,colon:`:`,sol:`/`,lsqb:`[`,rsqb:`]`,num:`#`,percnt:`%`,lpar:`(`,rpar:`)`,comma:`,`,period:`.`,excl:`!`,tab:` `,newline:`
2
+ `};function r(e){return e.includes(`&`)?e.replace(/&(#x[0-9a-f]+|#\d+|[a-z]+);/gi,(e,t)=>{if(t[0]===`#`){let n=t[1]===`x`||t[1]===`X`?parseInt(t.slice(2),16):parseInt(t.slice(1),10);return n>0&&n<=1114111?String.fromCodePoint(n):e}return n[t.toLowerCase()]??e}):e}var i=/<[a-zA-Z][^\s/>]*/g,a=/\s+([^\s"'>/=]+)(?:\s*=\s*(?:"([^"]*)"|'([^']*)'|([^\s"'=<>`]+)))?|\s*\//y,o=/\s*>/y;function s(e){let t=e.toLowerCase(),n=/<!--|<(script|style)\b/g,r=``,i=0,a;for(;a=n.exec(t);){r+=e.slice(i,a.index)+` `;let o;if(a[1]){let e=t.indexOf(`</`+a[1],a.index+a[0].length);o=e<0?-1:t.indexOf(`>`,e),o>=0&&(o+=1)}else{let e=t.indexOf(`-->`,a.index+4);o=e<0?-1:e+3}if(o<0)return r;i=n.lastIndex=o}return r+e.slice(i)}function c(e){let t=s(e),n=new Set;for(i.lastIndex=0;i.exec(t);){let e=i.lastIndex,s,c=[];for(a.lastIndex=e;(s=a.exec(t))&&s[0];a.lastIndex=e)e=a.lastIndex,s[1]?.toLowerCase()===`class`&&c.push(s[2]??s[3]??s[4]??``);if(o.lastIndex=e,!o.test(t)){i.lastIndex=e;continue}i.lastIndex=o.lastIndex;for(let e of c)for(let t of r(e).split(/\s+/))t&&n.add(t)}return[...n]}function l(e){return e.replace(/\\([0-9a-fA-F]{1,6})\s?|\\(.)/g,(e,t,n)=>t?String.fromCodePoint(parseInt(t,16)):n)}function u(e){let t=[],n=0,r=0;for(let i=0;i<e.length;i++){let a=e[i];a===`\\`?i++:a===`(`||a===`[`?n++:a===`)`||a===`]`?n--:a===`,`&&n===0&&(t.push(e.slice(r,i)),r=i+1)}return t.push(e.slice(r)),t}var d=/^\s*(?::(?:where|is)\(\s*)?\.((?:\\[0-9a-fA-F]{1,6}\s?|\\.|[\w-]|[^\x00-\x7F])+)/,f=/(^|[\s,(]):(root|host)\b/;function p(e){let t={classes:new Set,vars:new Set,properties:new Set,keyframes:new Set,layerStatement:!1},n=[],r=``,i=e=>{if(n.some(e=>f.test(e)))for(let n of e.matchAll(/(?:^|;)\s*(--[\w-]+)\s*:/g))t.vars.add(n[1])};for(let a=0;a<e.length;a++){let o=e[a];if(o===`/`&&e[a+1]===`*`){let t=e.indexOf(`*/`,a+2);a=t<0?e.length:t+1;continue}if(o===`"`||o===`'`){let t=a+1;for(;t<e.length&&e[t]!==o;)t+=e[t]===`\\`?2:1;r+=e.slice(a,t+1),a=t;continue}if(o===`\\`){r+=e.slice(a,a+2),a++;continue}if(o===`{`){let e=r.lastIndexOf(`;`);e>=0&&i(r.slice(0,e+1));let a=r.slice(e+1).trim();r=``,n.push(a);let o=/^@([\w-]+)\s*([\s\S]*)$/.exec(a);if(o){let e=o[1].toLowerCase();e===`property`?t.properties.add(o[2].trim()):e.endsWith(`keyframes`)&&t.keyframes.add(o[2].trim().replace(/^["']|["']$/g,``))}else if(!a.startsWith(`&`))for(let e of u(a)){let n=d.exec(e);n&&t.classes.add(l(n[1]))}continue}if(o===`}`){i(r),r=``,n.pop();continue}if(o===`;`&&n.length===0){/^\s*@layer\b/.test(r)&&(t.layerStatement=!0),r=``;continue}r+=o}return t}function m(e,n={}){return`<style ${t}${n.nonce?` nonce="${n.nonce.replace(/[&"<>]/g,e=>`&#${e.charCodeAt(0)};`)}"`:``}>${e.replace(/<\/(style)/gi,`<\\/$1`)}</style>`}var h=e=>[...e.matchAll(/var\((--[\w-]+)/g)].map(e=>e[1]),g=class{constructor(e={},t={}){this.classCache=new Map,this.themeDefs=null,this.skipCache=new Map,this.cacheSize=Math.max(0,t.cacheSize??1e4),this.setConfig(e)}setConfig(t){this.context=(0,e.createContext)(t),this.classCache.clear(),this.themeDefs=null}parseClass(t){return(0,e.parseClassToAst)(t,this.context)}generateCss(e){return this.sheet(e.split(/\s+/).filter(Boolean))}generateCssForHtml(e,t={}){let n=typeof e==`string`?c(e):[...new Set(e.flatMap(e=>e.split(/\s+/)).filter(Boolean))],r=t.skip;if(r===void 0)return this.sheet(n);if(typeof r==`string`){let e=this.skipDefs(r);return this.sheet(n.filter(t=>!e.classes.has(t)),e)}let i=r instanceof Set?r:new Set(r);return this.sheet(n.filter(e=>!i.has(e)))}skipDefs(e){let t=this.skipCache.get(e);return t||(this.skipCache.size>=4&&this.skipCache.delete(this.skipCache.keys().next().value),this.skipCache.set(e,t=p(e))),t}sheet(e,t){let n=e.map(e=>this.entryFor(e)),r=this.uniqueRoots(n.flatMap(e=>e.roots));t&&(r=r.filter(({css:e,dedupeKey:n})=>{if(n.startsWith(`--`))return!t.properties.has(n);let r=/^\s*@(?:-[\w]+-)?keyframes\s+([^\s{]+)/.exec(e)?.[1];return!r||!t.keyframes.has(r)}));let i=this.sortRules(n.filter(e=>e.css)),a=[...r.flatMap(e=>e.refs),...i.flatMap(e=>e.refs)],o=this.themeVarsBlock(a,t?.vars);return[...o?[o]:[],...r.map(e=>e.css),...i.map(e=>e.css)].join(`
3
+ `)}entryFor(t){let n=this.classCache.get(t);if(n)return this.classCache.delete(t),this.classCache.set(t,n),n;let r={css:``,key:null,refs:[],roots:[]},i=[];try{i=(0,e.generateCssRules)(t,this.context)}catch(n){(0,e.isDebug)()&&console.warn(`[barocss/server] class generation failed:`,t,n)}for(let{css:e,rootCssList:t}of i){e&&(r.css=e);for(let e of t){if(!e)continue;let t=/^\s*@property\s+(--[\w-]+)/.exec(e)?.[1]??e;r.roots.push({css:e,dedupeKey:t,refs:h(e)})}}return r.css&&(r.key=(0,e.ruleSortKey)(r.css),r.refs=h(r.css)),this.cacheSize>0&&(this.classCache.size>=this.cacheSize&&this.classCache.delete(this.classCache.keys().next().value),this.classCache.set(t,r)),r}generateCssForClasses(e){return e.map(e=>({className:e,css:this.generateCss(e)}))}uniqueRoots(e){let t=new Set;return e.filter(({dedupeKey:e})=>!t.has(e)&&!!t.add(e))}sortRules(t){return t.map((e,t)=>({entry:e,i:t})).sort((t,n)=>(0,e.compareKeys)(t.entry.key,n.entry.key)||t.i-n.i).map(({entry:e})=>e)}themeVarsBlock(e,t){let n=e;if(n.length===0)return``;let r=this.themeDefs;if(!r){r=this.themeDefs=new Map;for(let e of this.context.themeToCssVars().matchAll(/^\s*(--[\w-]+):\s*(.+);$/gm))r.set(e[1],e[2])}let i=new Map;for(;n.length;){let e=n.pop(),a=r.get(e);a===void 0||i.has(e)||t?.has(e)||(i.set(e,a),n.push(...h(a)))}return i.size===0?``:`:root,:host {
4
+ `+[...i].map(([e,t])=>` ${e}: ${t};`).join(`
5
5
  `)+`
6
- }`}}exports.SSR_STYLE_ATTRIBUTE=g;exports.ServerRuntime=E;exports.ssrStyleTag=R;
6
+ }`}};exports.SSR_STYLE_ATTRIBUTE=t,exports.ServerRuntime=g,exports.ssrStyleTag=m;
@@ -0,0 +1,70 @@
1
+ import { Config } from '@barocss/kit';
2
+ export { ssrStyleTag, SSR_STYLE_ATTRIBUTE } from './ssr.cjs';
3
+ /** #268: what `generateCssForHtml` leaves out: build CSS text, or class names. */
4
+ export interface GenerateCssForHtmlOptions {
5
+ /**
6
+ * Build CSS text (the stylesheet the page already links) or a set of class names. With CSS, the
7
+ * classes leading its selectors are skipped, and so are the theme vars its `:root`/`:host` blocks
8
+ * declare, its `@property` and `@keyframes` names. With class names only classes are skipped.
9
+ */
10
+ skip?: string | Iterable<string>;
11
+ }
12
+ export interface ServerRuntimeOptions {
13
+ /** Max classes kept in the per-class generation cache (LRU). Default 10000; 0 disables caching. */
14
+ cacheSize?: number;
15
+ }
16
+ export declare class ServerRuntime {
17
+ private context;
18
+ private readonly cacheSize;
19
+ /** class -> generated entry; Map insertion order doubles as LRU order (#272). */
20
+ private classCache;
21
+ /** Theme var definitions parsed once from themeToCssVars() (#272). */
22
+ private themeDefs;
23
+ /** #268: parsed skip CSS by text. */
24
+ private skipCache;
25
+ constructor(config?: Config, options?: ServerRuntimeOptions);
26
+ /** Replace the config (theme included). Drops every cached result derived from the previous one. */
27
+ setConfig(config: Config): void;
28
+ /**
29
+ * Parse a class name and return its AST
30
+ */
31
+ parseClass(className: string): import('@barocss/kit').AstNode[];
32
+ /**
33
+ * Generate CSS for a class name (or whitespace-separated class names) as one complete sheet (#267):
34
+ * one `:root,:host` block defining every theme var the output references, each root/@property block
35
+ * once, then the class rules in Tailwind variant order (base < sm < md < lg ...).
36
+ */
37
+ generateCss(className: string): string;
38
+ /**
39
+ * #268: the complete sheet (#267 order) for the classes one server response uses, minus what the
40
+ * page's build CSS already provides. `htmlOrClasses` is HTML (classes are read from `class`
41
+ * attributes; `<script>`/`<style>` contents and comments ignored) or a class list. Stateless per
42
+ * call: it returns this request's delta, never classes emitted for earlier requests. Wrap the result
43
+ * with `ssrStyleTag()` so `@barocss/browser` adopts it.
44
+ */
45
+ generateCssForHtml(htmlOrClasses: string | string[], opts?: GenerateCssForHtmlOptions): string;
46
+ /** Parsed build CSS, memoised by text (a server passes the same build CSS on every request). */
47
+ private skipDefs;
48
+ private sheet;
49
+ /** Generate (or reuse) one class's rules. Same per-class output generateCssRules gives for a class list. */
50
+ private entryFor;
51
+ /**
52
+ * CSS per class, in input order. Each entry is self-contained (its own `:root,:host` vars block,
53
+ * @property blocks and variant-sorted rules), so entries repeat shared blocks and are not ordered
54
+ * against each other. For one complete sheet use `generateCss(classes.join(' '))`.
55
+ */
56
+ generateCssForClasses(classes: string[]): {
57
+ className: string;
58
+ css: string;
59
+ }[];
60
+ /** Dedupe root-level blocks by content, and @property blocks by property name. */
61
+ private uniqueRoots;
62
+ /** Stable sort by the #254 variant key shared with @barocss/browser. */
63
+ private sortRules;
64
+ /**
65
+ * #228 generalised (#267): define every var(--x) the output references that the theme defines
66
+ * (radius, text, spacing, shadow, font, colour ...), including vars those definitions reference.
67
+ * themeToCssVars() already omits self-referencing entries (#260).
68
+ */
69
+ private themeVarsBlock;
70
+ }
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { Config } from '@barocss/kit';
2
- export { ssrStyleTag, SSR_STYLE_ATTRIBUTE } from './ssr';
2
+ export { ssrStyleTag, SSR_STYLE_ATTRIBUTE } from './ssr.js';
3
3
  /** #268: what `generateCssForHtml` leaves out: build CSS text, or class names. */
4
4
  export interface GenerateCssForHtmlOptions {
5
5
  /**
package/dist/index.es.js CHANGED
@@ -1,255 +1,238 @@
1
- import { createContext as x, parseClassToAst as C, generateCssRules as g, ruleSortKey as w, compareKeys as y } from "@barocss/kit";
2
- const S = "data-barocss-ssr", k = {
3
- amp: "&",
4
- lt: "<",
5
- gt: ">",
6
- quot: '"',
7
- apos: "'",
8
- nbsp: " ",
9
- colon: ":",
10
- sol: "/",
11
- lsqb: "[",
12
- rsqb: "]",
13
- num: "#",
14
- percnt: "%",
15
- lpar: "(",
16
- rpar: ")",
17
- comma: ",",
18
- period: ".",
19
- excl: "!",
20
- tab: " ",
21
- newline: `
22
- `
1
+ import { compareKeys as e, createContext as t, generateCssRules as n, isDebug as r, parseClassToAst as i, ruleSortKey as a } from "@barocss/kit";
2
+ //#region src/ssr.ts
3
+ var o = "data-barocss-ssr", s = {
4
+ amp: "&",
5
+ lt: "<",
6
+ gt: ">",
7
+ quot: "\"",
8
+ apos: "'",
9
+ nbsp: "\xA0",
10
+ colon: ":",
11
+ sol: "/",
12
+ lsqb: "[",
13
+ rsqb: "]",
14
+ num: "#",
15
+ percnt: "%",
16
+ lpar: "(",
17
+ rpar: ")",
18
+ comma: ",",
19
+ period: ".",
20
+ excl: "!",
21
+ tab: " ",
22
+ newline: "\n"
23
23
  };
24
- function I(c) {
25
- return c.includes("&") ? c.replace(/&(#x[0-9a-f]+|#\d+|[a-z]+);/gi, (s, t) => {
26
- if (t[0] === "#") {
27
- const e = t[1] === "x" || t[1] === "X" ? parseInt(t.slice(2), 16) : parseInt(t.slice(1), 10);
28
- return e > 0 && e <= 1114111 ? String.fromCodePoint(e) : s;
29
- }
30
- return k[t.toLowerCase()] ?? s;
31
- }) : c;
24
+ function c(e) {
25
+ return e.includes("&") ? e.replace(/&(#x[0-9a-f]+|#\d+|[a-z]+);/gi, (e, t) => {
26
+ if (t[0] === "#") {
27
+ let n = t[1] === "x" || t[1] === "X" ? parseInt(t.slice(2), 16) : parseInt(t.slice(1), 10);
28
+ return n > 0 && n <= 1114111 ? String.fromCodePoint(n) : e;
29
+ }
30
+ return s[t.toLowerCase()] ?? e;
31
+ }) : e;
32
32
  }
33
- const h = /<[a-zA-Z][^\s/>]*/g, p = /\s+([^\s"'>/=]+)(?:\s*=\s*(?:"([^"]*)"|'([^']*)'|([^\s"'=<>`]+)))?|\s*\//y, u = /\s*>/y;
34
- function T(c) {
35
- const s = c.toLowerCase(), t = /<!--|<(script|style)\b/g;
36
- let e = "", i = 0, o;
37
- for (; o = t.exec(s); ) {
38
- e += c.slice(i, o.index) + " ";
39
- let n;
40
- if (o[1]) {
41
- const r = s.indexOf("</" + o[1], o.index + o[0].length);
42
- n = r < 0 ? -1 : s.indexOf(">", r), n >= 0 && (n += 1);
43
- } else {
44
- const r = s.indexOf("-->", o.index + 4);
45
- n = r < 0 ? -1 : r + 3;
46
- }
47
- if (n < 0) return e;
48
- i = t.lastIndex = n;
49
- }
50
- return e + c.slice(i);
33
+ var l = /<[a-zA-Z][^\s/>]*/g, u = /\s+([^\s"'>/=]+)(?:\s*=\s*(?:"([^"]*)"|'([^']*)'|([^\s"'=<>`]+)))?|\s*\//y, d = /\s*>/y;
34
+ function f(e) {
35
+ let t = e.toLowerCase(), n = /<!--|<(script|style)\b/g, r = "", i = 0, a;
36
+ for (; a = n.exec(t);) {
37
+ r += e.slice(i, a.index) + " ";
38
+ let o;
39
+ if (a[1]) {
40
+ let e = t.indexOf("</" + a[1], a.index + a[0].length);
41
+ o = e < 0 ? -1 : t.indexOf(">", e), o >= 0 && (o += 1);
42
+ } else {
43
+ let e = t.indexOf("-->", a.index + 4);
44
+ o = e < 0 ? -1 : e + 3;
45
+ }
46
+ if (o < 0) return r;
47
+ i = n.lastIndex = o;
48
+ }
49
+ return r + e.slice(i);
51
50
  }
52
- function A(c) {
53
- const s = T(c), t = /* @__PURE__ */ new Set();
54
- for (h.lastIndex = 0; h.exec(s); ) {
55
- let e = h.lastIndex, i;
56
- const o = [];
57
- for (p.lastIndex = e; (i = p.exec(s)) && i[0]; p.lastIndex = e)
58
- e = p.lastIndex, i[1]?.toLowerCase() === "class" && o.push(i[2] ?? i[3] ?? i[4] ?? "");
59
- if (u.lastIndex = e, !u.test(s)) {
60
- h.lastIndex = e;
61
- continue;
62
- }
63
- h.lastIndex = u.lastIndex;
64
- for (const n of o) for (const r of I(n).split(/\s+/)) r && t.add(r);
65
- }
66
- return [...t];
51
+ function p(e) {
52
+ let t = f(e), n = /* @__PURE__ */ new Set();
53
+ for (l.lastIndex = 0; l.exec(t);) {
54
+ let e = l.lastIndex, r, i = [];
55
+ for (u.lastIndex = e; (r = u.exec(t)) && r[0]; u.lastIndex = e) e = u.lastIndex, r[1]?.toLowerCase() === "class" && i.push(r[2] ?? r[3] ?? r[4] ?? "");
56
+ if (d.lastIndex = e, !d.test(t)) {
57
+ l.lastIndex = e;
58
+ continue;
59
+ }
60
+ l.lastIndex = d.lastIndex;
61
+ for (let e of i) for (let t of c(e).split(/\s+/)) t && n.add(t);
62
+ }
63
+ return [...n];
67
64
  }
68
- function v(c) {
69
- return c.replace(/\\([0-9a-fA-F]{1,6})\s?|\\(.)/g, (s, t, e) => t ? String.fromCodePoint(parseInt(t, 16)) : e);
65
+ function m(e) {
66
+ return e.replace(/\\([0-9a-fA-F]{1,6})\s?|\\(.)/g, (e, t, n) => t ? String.fromCodePoint(parseInt(t, 16)) : n);
70
67
  }
71
- function R(c) {
72
- const s = [];
73
- let t = 0, e = 0;
74
- for (let i = 0; i < c.length; i++) {
75
- const o = c[i];
76
- o === "\\" ? i++ : o === "(" || o === "[" ? t++ : o === ")" || o === "]" ? t-- : o === "," && t === 0 && (s.push(c.slice(e, i)), e = i + 1);
77
- }
78
- return s.push(c.slice(e)), s;
68
+ function h(e) {
69
+ let t = [], n = 0, r = 0;
70
+ for (let i = 0; i < e.length; i++) {
71
+ let a = e[i];
72
+ a === "\\" ? i++ : a === "(" || a === "[" ? n++ : a === ")" || a === "]" ? n-- : a === "," && n === 0 && (t.push(e.slice(r, i)), r = i + 1);
73
+ }
74
+ return t.push(e.slice(r)), t;
79
75
  }
80
- const D = /^\s*(?::(?:where|is)\(\s*)?\.((?:\\[0-9a-fA-F]{1,6}\s?|\\.|[\w-]|[^\x00-\x7F])+)/, E = /(^|[\s,(]):(root|host)\b/;
81
- function $(c) {
82
- const s = { classes: /* @__PURE__ */ new Set(), vars: /* @__PURE__ */ new Set(), properties: /* @__PURE__ */ new Set(), keyframes: /* @__PURE__ */ new Set(), layerStatement: !1 }, t = [];
83
- let e = "";
84
- const i = (o) => {
85
- if (t.some((n) => E.test(n)))
86
- for (const n of o.matchAll(/(?:^|;)\s*(--[\w-]+)\s*:/g)) s.vars.add(n[1]);
87
- };
88
- for (let o = 0; o < c.length; o++) {
89
- const n = c[o];
90
- if (n === "/" && c[o + 1] === "*") {
91
- const r = c.indexOf("*/", o + 2);
92
- o = r < 0 ? c.length : r + 1;
93
- continue;
94
- }
95
- if (n === '"' || n === "'") {
96
- let r = o + 1;
97
- for (; r < c.length && c[r] !== n; ) r += c[r] === "\\" ? 2 : 1;
98
- e += c.slice(o, r + 1), o = r;
99
- continue;
100
- }
101
- if (n === "\\") {
102
- e += c.slice(o, o + 2), o++;
103
- continue;
104
- }
105
- if (n === "{") {
106
- const r = e.lastIndexOf(";");
107
- r >= 0 && i(e.slice(0, r + 1));
108
- const a = e.slice(r + 1).trim();
109
- e = "", t.push(a);
110
- const l = /^@([\w-]+)\s*([\s\S]*)$/.exec(a);
111
- if (l) {
112
- const f = l[1].toLowerCase();
113
- f === "property" ? s.properties.add(l[2].trim()) : f.endsWith("keyframes") && s.keyframes.add(l[2].trim().replace(/^["']|["']$/g, ""));
114
- } else if (!a.startsWith("&"))
115
- for (const f of R(a)) {
116
- const m = D.exec(f);
117
- m && s.classes.add(v(m[1]));
118
- }
119
- continue;
120
- }
121
- if (n === "}") {
122
- i(e), e = "", t.pop();
123
- continue;
124
- }
125
- if (n === ";" && t.length === 0) {
126
- /^\s*@layer\b/.test(e) && (s.layerStatement = !0), e = "";
127
- continue;
128
- }
129
- e += n;
130
- }
131
- return s;
76
+ var g = /^\s*(?::(?:where|is)\(\s*)?\.((?:\\[0-9a-fA-F]{1,6}\s?|\\.|[\w-]|[^\x00-\x7F])+)/, _ = /(^|[\s,(]):(root|host)\b/;
77
+ function v(e) {
78
+ let t = {
79
+ classes: /* @__PURE__ */ new Set(),
80
+ vars: /* @__PURE__ */ new Set(),
81
+ properties: /* @__PURE__ */ new Set(),
82
+ keyframes: /* @__PURE__ */ new Set(),
83
+ layerStatement: !1
84
+ }, n = [], r = "", i = (e) => {
85
+ if (n.some((e) => _.test(e))) for (let n of e.matchAll(/(?:^|;)\s*(--[\w-]+)\s*:/g)) t.vars.add(n[1]);
86
+ };
87
+ for (let a = 0; a < e.length; a++) {
88
+ let o = e[a];
89
+ if (o === "/" && e[a + 1] === "*") {
90
+ let t = e.indexOf("*/", a + 2);
91
+ a = t < 0 ? e.length : t + 1;
92
+ continue;
93
+ }
94
+ if (o === "\"" || o === "'") {
95
+ let t = a + 1;
96
+ for (; t < e.length && e[t] !== o;) t += e[t] === "\\" ? 2 : 1;
97
+ r += e.slice(a, t + 1), a = t;
98
+ continue;
99
+ }
100
+ if (o === "\\") {
101
+ r += e.slice(a, a + 2), a++;
102
+ continue;
103
+ }
104
+ if (o === "{") {
105
+ let e = r.lastIndexOf(";");
106
+ e >= 0 && i(r.slice(0, e + 1));
107
+ let a = r.slice(e + 1).trim();
108
+ r = "", n.push(a);
109
+ let o = /^@([\w-]+)\s*([\s\S]*)$/.exec(a);
110
+ if (o) {
111
+ let e = o[1].toLowerCase();
112
+ e === "property" ? t.properties.add(o[2].trim()) : e.endsWith("keyframes") && t.keyframes.add(o[2].trim().replace(/^["']|["']$/g, ""));
113
+ } else if (!a.startsWith("&")) for (let e of h(a)) {
114
+ let n = g.exec(e);
115
+ n && t.classes.add(m(n[1]));
116
+ }
117
+ continue;
118
+ }
119
+ if (o === "}") {
120
+ i(r), r = "", n.pop();
121
+ continue;
122
+ }
123
+ if (o === ";" && n.length === 0) {
124
+ /^\s*@layer\b/.test(r) && (t.layerStatement = !0), r = "";
125
+ continue;
126
+ }
127
+ r += o;
128
+ }
129
+ return t;
132
130
  }
133
- function M(c, s = {}) {
134
- const t = s.nonce ? ` nonce="${s.nonce.replace(/[&"<>]/g, (e) => `&#${e.charCodeAt(0)};`)}"` : "";
135
- return `<style ${S}${t}>${c.replace(/<\/(style)/gi, "<\\/$1")}</style>`;
131
+ function y(e, t = {}) {
132
+ return `<style ${o}${t.nonce ? ` nonce="${t.nonce.replace(/[&"<>]/g, (e) => `&#${e.charCodeAt(0)};`)}"` : ""}>${e.replace(/<\/(style)/gi, "<\\/$1")}</style>`;
136
133
  }
137
- const d = (c) => [...c.matchAll(/var\((--[\w-]+)/g)].map((s) => s[1]);
138
- class z {
139
- constructor(s = {}, t = {}) {
140
- this.classCache = /* @__PURE__ */ new Map(), this.themeDefs = null, this.skipCache = /* @__PURE__ */ new Map(), this.cacheSize = Math.max(0, t.cacheSize ?? 1e4), this.setConfig(s);
141
- }
142
- /** Replace the config (theme included). Drops every cached result derived from the previous one. */
143
- setConfig(s) {
144
- this.context = x(s), this.classCache.clear(), this.themeDefs = null;
145
- }
146
- /**
147
- * Parse a class name and return its AST
148
- */
149
- parseClass(s) {
150
- return C(s, this.context);
151
- }
152
- /**
153
- * Generate CSS for a class name (or whitespace-separated class names) as one complete sheet (#267):
154
- * one `:root,:host` block defining every theme var the output references, each root/@property block
155
- * once, then the class rules in Tailwind variant order (base < sm < md < lg ...).
156
- */
157
- generateCss(s) {
158
- return this.sheet(s.split(/\s+/).filter(Boolean));
159
- }
160
- /**
161
- * #268: the complete sheet (#267 order) for the classes one server response uses, minus what the
162
- * page's build CSS already provides. `htmlOrClasses` is HTML (classes are read from `class`
163
- * attributes; `<script>`/`<style>` contents and comments ignored) or a class list. Stateless per
164
- * call: it returns this request's delta, never classes emitted for earlier requests. Wrap the result
165
- * with `ssrStyleTag()` so `@barocss/browser` adopts it.
166
- */
167
- generateCssForHtml(s, t = {}) {
168
- const e = typeof s == "string" ? A(s) : [...new Set(s.flatMap((n) => n.split(/\s+/)).filter(Boolean))], i = t.skip;
169
- if (i === void 0) return this.sheet(e);
170
- if (typeof i == "string") {
171
- const n = this.skipDefs(i);
172
- return this.sheet(e.filter((r) => !n.classes.has(r)), n);
173
- }
174
- const o = i instanceof Set ? i : new Set(i);
175
- return this.sheet(e.filter((n) => !o.has(n)));
176
- }
177
- /** Parsed build CSS, memoised by text (a server passes the same build CSS on every request). */
178
- skipDefs(s) {
179
- let t = this.skipCache.get(s);
180
- return t || (this.skipCache.size >= 4 && this.skipCache.delete(this.skipCache.keys().next().value), this.skipCache.set(s, t = $(s))), t;
181
- }
182
- sheet(s, t) {
183
- const e = s.map((a) => this.entryFor(a));
184
- let i = this.uniqueRoots(e.flatMap((a) => a.roots));
185
- t && (i = i.filter(({ css: a, dedupeKey: l }) => {
186
- if (l.startsWith("--")) return !t.properties.has(l);
187
- const f = /^\s*@(?:-[\w]+-)?keyframes\s+([^\s{]+)/.exec(a)?.[1];
188
- return !f || !t.keyframes.has(f);
189
- }));
190
- const o = this.sortRules(e.filter((a) => a.css)), n = [...i.flatMap((a) => a.refs), ...o.flatMap((a) => a.refs)], r = this.themeVarsBlock(n, t?.vars);
191
- return [...r ? [r] : [], ...i.map((a) => a.css), ...o.map((a) => a.css)].join(`
192
- `);
193
- }
194
- /** Generate (or reuse) one class's rules. Same per-class output generateCssRules gives for a class list. */
195
- entryFor(s) {
196
- const t = this.classCache.get(s);
197
- if (t)
198
- return this.classCache.delete(s), this.classCache.set(s, t), t;
199
- const e = { css: "", key: null, refs: [], roots: [] };
200
- for (const { css: i, rootCssList: o } of g(s, this.context)) {
201
- i && (e.css = i);
202
- for (const n of o) {
203
- if (!n) continue;
204
- const r = /^\s*@property\s+(--[\w-]+)/.exec(n)?.[1] ?? n;
205
- e.roots.push({ css: n, dedupeKey: r, refs: d(n) });
206
- }
207
- }
208
- return e.css && (e.key = w(e.css), e.refs = d(e.css)), this.cacheSize > 0 && (this.classCache.size >= this.cacheSize && this.classCache.delete(this.classCache.keys().next().value), this.classCache.set(s, e)), e;
209
- }
210
- /**
211
- * CSS per class, in input order. Each entry is self-contained (its own `:root,:host` vars block,
212
- * @property blocks and variant-sorted rules), so entries repeat shared blocks and are not ordered
213
- * against each other. For one complete sheet use `generateCss(classes.join(' '))`.
214
- */
215
- generateCssForClasses(s) {
216
- return s.map((t) => ({ className: t, css: this.generateCss(t) }));
217
- }
218
- /** Dedupe root-level blocks by content, and @property blocks by property name. */
219
- uniqueRoots(s) {
220
- const t = /* @__PURE__ */ new Set();
221
- return s.filter(({ dedupeKey: e }) => !t.has(e) && !!t.add(e));
222
- }
223
- /** Stable sort by the #254 variant key shared with @barocss/browser. */
224
- sortRules(s) {
225
- return s.map((t, e) => ({ entry: t, i: e })).sort((t, e) => y(t.entry.key, e.entry.key) || t.i - e.i).map(({ entry: t }) => t);
226
- }
227
- /**
228
- * #228 generalised (#267): define every var(--x) the output references that the theme defines
229
- * (radius, text, spacing, shadow, font, colour ...), including vars those definitions reference.
230
- * themeToCssVars() already omits self-referencing entries (#260).
231
- */
232
- themeVarsBlock(s, t) {
233
- const e = s;
234
- if (e.length === 0) return "";
235
- let i = this.themeDefs;
236
- if (!i) {
237
- i = this.themeDefs = /* @__PURE__ */ new Map();
238
- for (const n of this.context.themeToCssVars().matchAll(/^\s*(--[\w-]+):\s*(.+);$/gm)) i.set(n[1], n[2]);
239
- }
240
- const o = /* @__PURE__ */ new Map();
241
- for (; e.length; ) {
242
- const n = e.pop(), r = i.get(n);
243
- r === void 0 || o.has(n) || t?.has(n) || (o.set(n, r), e.push(...d(r)));
244
- }
245
- return o.size === 0 ? "" : `:root,:host {
246
- ` + [...o].map(([n, r]) => ` ${n}: ${r};`).join(`
247
- `) + `
248
- }`;
249
- }
250
- }
251
- export {
252
- S as SSR_STYLE_ATTRIBUTE,
253
- z as ServerRuntime,
254
- M as ssrStyleTag
134
+ //#endregion
135
+ //#region src/index.ts
136
+ var b = (e) => [...e.matchAll(/var\((--[\w-]+)/g)].map((e) => e[1]), x = class {
137
+ constructor(e = {}, t = {}) {
138
+ this.classCache = /* @__PURE__ */ new Map(), this.themeDefs = null, this.skipCache = /* @__PURE__ */ new Map(), this.cacheSize = Math.max(0, t.cacheSize ?? 1e4), this.setConfig(e);
139
+ }
140
+ setConfig(e) {
141
+ this.context = t(e), this.classCache.clear(), this.themeDefs = null;
142
+ }
143
+ parseClass(e) {
144
+ return i(e, this.context);
145
+ }
146
+ generateCss(e) {
147
+ return this.sheet(e.split(/\s+/).filter(Boolean));
148
+ }
149
+ generateCssForHtml(e, t = {}) {
150
+ let n = typeof e == "string" ? p(e) : [...new Set(e.flatMap((e) => e.split(/\s+/)).filter(Boolean))], r = t.skip;
151
+ if (r === void 0) return this.sheet(n);
152
+ if (typeof r == "string") {
153
+ let e = this.skipDefs(r);
154
+ return this.sheet(n.filter((t) => !e.classes.has(t)), e);
155
+ }
156
+ let i = r instanceof Set ? r : new Set(r);
157
+ return this.sheet(n.filter((e) => !i.has(e)));
158
+ }
159
+ skipDefs(e) {
160
+ let t = this.skipCache.get(e);
161
+ return t || (this.skipCache.size >= 4 && this.skipCache.delete(this.skipCache.keys().next().value), this.skipCache.set(e, t = v(e))), t;
162
+ }
163
+ sheet(e, t) {
164
+ let n = e.map((e) => this.entryFor(e)), r = this.uniqueRoots(n.flatMap((e) => e.roots));
165
+ t && (r = r.filter(({ css: e, dedupeKey: n }) => {
166
+ if (n.startsWith("--")) return !t.properties.has(n);
167
+ let r = /^\s*@(?:-[\w]+-)?keyframes\s+([^\s{]+)/.exec(e)?.[1];
168
+ return !r || !t.keyframes.has(r);
169
+ }));
170
+ let i = this.sortRules(n.filter((e) => e.css)), a = [...r.flatMap((e) => e.refs), ...i.flatMap((e) => e.refs)], o = this.themeVarsBlock(a, t?.vars);
171
+ return [
172
+ ...o ? [o] : [],
173
+ ...r.map((e) => e.css),
174
+ ...i.map((e) => e.css)
175
+ ].join("\n");
176
+ }
177
+ entryFor(e) {
178
+ let t = this.classCache.get(e);
179
+ if (t) return this.classCache.delete(e), this.classCache.set(e, t), t;
180
+ let i = {
181
+ css: "",
182
+ key: null,
183
+ refs: [],
184
+ roots: []
185
+ }, o = [];
186
+ try {
187
+ o = n(e, this.context);
188
+ } catch (t) {
189
+ r() && console.warn("[barocss/server] class generation failed:", e, t);
190
+ }
191
+ for (let { css: e, rootCssList: t } of o) {
192
+ e && (i.css = e);
193
+ for (let e of t) {
194
+ if (!e) continue;
195
+ let t = /^\s*@property\s+(--[\w-]+)/.exec(e)?.[1] ?? e;
196
+ i.roots.push({
197
+ css: e,
198
+ dedupeKey: t,
199
+ refs: b(e)
200
+ });
201
+ }
202
+ }
203
+ return i.css && (i.key = a(i.css), i.refs = b(i.css)), this.cacheSize > 0 && (this.classCache.size >= this.cacheSize && this.classCache.delete(this.classCache.keys().next().value), this.classCache.set(e, i)), i;
204
+ }
205
+ generateCssForClasses(e) {
206
+ return e.map((e) => ({
207
+ className: e,
208
+ css: this.generateCss(e)
209
+ }));
210
+ }
211
+ uniqueRoots(e) {
212
+ let t = /* @__PURE__ */ new Set();
213
+ return e.filter(({ dedupeKey: e }) => !t.has(e) && !!t.add(e));
214
+ }
215
+ sortRules(t) {
216
+ return t.map((e, t) => ({
217
+ entry: e,
218
+ i: t
219
+ })).sort((t, n) => e(t.entry.key, n.entry.key) || t.i - n.i).map(({ entry: e }) => e);
220
+ }
221
+ themeVarsBlock(e, t) {
222
+ let n = e;
223
+ if (n.length === 0) return "";
224
+ let r = this.themeDefs;
225
+ if (!r) {
226
+ r = this.themeDefs = /* @__PURE__ */ new Map();
227
+ for (let e of this.context.themeToCssVars().matchAll(/^\s*(--[\w-]+):\s*(.+);$/gm)) r.set(e[1], e[2]);
228
+ }
229
+ let i = /* @__PURE__ */ new Map();
230
+ for (; n.length;) {
231
+ let e = n.pop(), a = r.get(e);
232
+ a === void 0 || i.has(e) || t?.has(e) || (i.set(e, a), n.push(...b(a)));
233
+ }
234
+ return i.size === 0 ? "" : ":root,:host {\n" + [...i].map(([e, t]) => ` ${e}: ${t};`).join("\n") + "\n}";
235
+ }
255
236
  };
237
+ //#endregion
238
+ export { o as SSR_STYLE_ATTRIBUTE, x as ServerRuntime, y as ssrStyleTag };
package/dist/ssr.d.cts ADDED
@@ -0,0 +1,38 @@
1
+ /**
2
+ * #268: SSR helpers: class extraction from HTML, parsing a build stylesheet into what it already
3
+ * defines (classes, theme vars, @property, @keyframes, @layer order), and the marked <style> tag the
4
+ * browser runtime recognises. Text only: no DOM, no CSS parser dependency.
5
+ */
6
+ /** Attribute that marks the server sheet. `@barocss/browser` adopts the rules of `<style data-barocss-ssr>`. */
7
+ export declare const SSR_STYLE_ATTRIBUTE = "data-barocss-ssr";
8
+ /** Decode the HTML character references an attribute value may contain. */
9
+ export declare function decodeHtmlEntities(s: string): string;
10
+ /**
11
+ * Class names from every `class` attribute in `html`, first-seen order, deduplicated. Handles double,
12
+ * single and unquoted values, any whitespace and character references; ignores comments and the
13
+ * contents of `<script>` and `<style>`.
14
+ */
15
+ export declare function extractClasses(html: string): string[];
16
+ /** What a build stylesheet already defines. */
17
+ export interface CssDefinitions {
18
+ /** Classes that lead a selector (the #210 rule: `.p-4`, `.md\:p-4` in @media, `.hover\:x:hover`). */
19
+ classes: Set<string>;
20
+ /** Custom properties declared in `:root` / `:host` blocks. */
21
+ vars: Set<string>;
22
+ /** `@property` names. */
23
+ properties: Set<string>;
24
+ /** `@keyframes` names. */
25
+ keyframes: Set<string>;
26
+ /** Whether the sheet has a top-level `@layer a, b;` order statement. */
27
+ layerStatement: boolean;
28
+ }
29
+ /**
30
+ * Parse CSS text (e.g. Tailwind or BaroCSS build output) into the names it defines. A small brace
31
+ * scanner that honours comments, strings and escapes; nested rules and @layer/@media/@supports groups
32
+ * are walked. Same leading-class rule as the browser's #210 `skipExisting`.
33
+ */
34
+ export declare function parseCssDefinitions(css: string): CssDefinitions;
35
+ /** `<style data-barocss-ssr>` around `css`; a `</style` inside the CSS is neutralised. */
36
+ export declare function ssrStyleTag(css: string, options?: {
37
+ nonce?: string;
38
+ }): string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@barocss/server",
3
- "version": "0.8.1",
3
+ "version": "0.9.0",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "git+https://github.com/barocss/barocss.git",
@@ -11,9 +11,14 @@
11
11
  "types": "./dist/index.d.ts",
12
12
  "exports": {
13
13
  ".": {
14
- "types": "./dist/index.d.ts",
15
- "import": "./dist/index.es.js",
16
- "require": "./dist/index.cjs"
14
+ "import": {
15
+ "types": "./dist/index.d.ts",
16
+ "default": "./dist/index.es.js"
17
+ },
18
+ "require": {
19
+ "types": "./dist/index.d.cts",
20
+ "default": "./dist/index.cjs"
21
+ }
17
22
  }
18
23
  },
19
24
  "files": [
@@ -26,10 +31,10 @@
26
31
  },
27
32
  "dependencies": {
28
33
  "jsdom": "^26.1.0",
29
- "@barocss/kit": "0.8.1"
34
+ "@barocss/kit": "0.9.0"
30
35
  },
31
36
  "devDependencies": {
32
- "vite": "^7.1.3",
37
+ "vite": "^8.3.1",
33
38
  "vite-plugin-dts": "^4.5.4",
34
39
  "vitest": "^5.0.2"
35
40
  },