@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 +4 -2
- package/dist/index.cjs +5 -5
- package/dist/index.d.cts +70 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.es.js +229 -246
- package/dist/ssr.d.cts +38 -0
- package/package.json +11 -6
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
|
[](https://www.npmjs.com/package/@barocss/server)
|
|
4
6
|
[](https://opensource.org/licenses/MIT)
|
|
5
7
|
[](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' },
|
|
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
|
-
|
|
2
|
-
`};function
|
|
3
|
-
`)}entryFor(
|
|
4
|
-
`+[...
|
|
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=
|
|
6
|
+
}`}};exports.SSR_STYLE_ATTRIBUTE=t,exports.ServerRuntime=g,exports.ssrStyleTag=m;
|
package/dist/index.d.cts
ADDED
|
@@ -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 {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
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
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
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
|
-
|
|
34
|
-
function
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
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
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
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
|
|
69
|
-
|
|
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
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
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
|
-
|
|
81
|
-
function
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
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
|
|
134
|
-
|
|
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
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
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.
|
|
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
|
-
"
|
|
15
|
-
|
|
16
|
-
|
|
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.
|
|
34
|
+
"@barocss/kit": "0.9.0"
|
|
30
35
|
},
|
|
31
36
|
"devDependencies": {
|
|
32
|
-
"vite": "^
|
|
37
|
+
"vite": "^8.3.1",
|
|
33
38
|
"vite-plugin-dts": "^4.5.4",
|
|
34
39
|
"vitest": "^5.0.2"
|
|
35
40
|
},
|