@teacss/inspector 0.4.7 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -3,7 +3,7 @@ import { IncomingMessage, ServerResponse } from "node:http";
3
3
  import { Plugin } from "vite";
4
4
  //#region src/types.d.ts
5
5
  /** A single matched token (utility/class) and what it produced. */
6
- interface MatchedToken {
6
+ export interface MatchedToken {
7
7
  /** The raw token as written in source, e.g. `bg-color:red-500`. */
8
8
  token: string;
9
9
  /** The generated CSS declarations (rule bodies joined), for preview. */
@@ -16,12 +16,12 @@ interface MatchedToken {
16
16
  modules: string[];
17
17
  }
18
18
  /** One output layer and its CSS. */
19
- interface LayerCss {
19
+ export interface LayerCss {
20
20
  name: string;
21
21
  css: string;
22
22
  }
23
23
  /** The common payload behind /overview, /module and /repl. */
24
- interface GenerateResultDTO {
24
+ export interface GenerateResultDTO {
25
25
  /** Full generated CSS (all layers concatenated in order). */
26
26
  css: string;
27
27
  /** Per-layer CSS, in layer order. */
@@ -30,7 +30,7 @@ interface GenerateResultDTO {
30
30
  matched: MatchedToken[];
31
31
  }
32
32
  /** A safe, acyclic summary of the resolved config (no live objects). */
33
- interface ConfigSummary {
33
+ export interface ConfigSummary {
34
34
  presets: string[];
35
35
  /** `[name, order]` pairs, sorted by order. */
36
36
  layers: [string, number][];
@@ -39,7 +39,7 @@ interface ConfigSummary {
39
39
  themeKeys: string[];
40
40
  }
41
41
  /** GET / — project + config overview chrome. */
42
- interface ProjectInfo {
42
+ export interface ProjectInfo {
43
43
  version: string;
44
44
  root: string;
45
45
  /** Scanned module ids (sorted). */
@@ -49,26 +49,26 @@ interface ProjectInfo {
49
49
  config: ConfigSummary;
50
50
  }
51
51
  /** GET /overview — whole-project generated CSS + analysis. */
52
- interface OverviewInfo extends GenerateResultDTO {
52
+ export interface OverviewInfo extends GenerateResultDTO {
53
53
  gzipSize: number;
54
54
  }
55
55
  /** GET /module?id= — a single module's source + what it generated. */
56
- interface ModuleInfo extends GenerateResultDTO {
56
+ export interface ModuleInfo extends GenerateResultDTO {
57
57
  id: string;
58
58
  code: string;
59
59
  gzipSize: number;
60
60
  }
61
61
  /** GET /repl?token= — generate CSS from arbitrary input. */
62
- type ReplResult = GenerateResultDTO;
62
+ export type ReplResult = GenerateResultDTO;
63
63
  /** Mount paths (also used to build client asset URLs). */
64
- declare const CLIENT_BASE = "__teacss";
65
- declare const API_BASE = "__teacss_api";
64
+ export declare const CLIENT_BASE = "__teacss";
65
+ export declare const API_BASE = "__teacss_api";
66
66
  //#endregion
67
67
  //#region src/analyzer.d.ts
68
68
  /** Map of source-module id → the tokens extracted from it. */
69
69
  type ModuleTokens = Map<string, Set<string>>;
70
70
  /** Coarse grouping family for a token: its property prefix, else the keyword stem. */
71
- declare function categoryOf(token: string): string;
71
+ export declare function categoryOf(token: string): string;
72
72
  interface GenerateDTOOptions {
73
73
  /** Module attribution source; when given, each matched token lists its files. */
74
74
  moduleTokens?: ModuleTokens;
@@ -83,7 +83,7 @@ interface GenerateDTOOptions {
83
83
  * per-layer CSS, and the matched tokens with declaration bodies, counts, and
84
84
  * (optionally) which modules used each.
85
85
  */
86
- declare function generateDTO(generator: TeacssGenerator, input: Set<string> | string, options?: GenerateDTOOptions): Promise<GenerateResultDTO>;
86
+ export declare function generateDTO(generator: TeacssGenerator, input: Set<string> | string, options?: GenerateDTOOptions): Promise<GenerateResultDTO>;
87
87
  //#endregion
88
88
  //#region src/index.d.ts
89
89
  /** One scanned module the inspector tracks: its source + the tokens it used. */
@@ -92,7 +92,7 @@ interface ModuleEntry {
92
92
  tokens: Set<string>;
93
93
  }
94
94
  /** The inspector's per-module state, shared between the plugin and the API. */
95
- interface InspectorStore {
95
+ export interface InspectorStore {
96
96
  /** Clean id (no `?query`) → entry. */
97
97
  modules: Map<string, ModuleEntry>;
98
98
  /** Bumped whenever `modules` or the config changes — keys the overview cache. */
@@ -103,13 +103,13 @@ interface InspectorStore {
103
103
  * live generator/context plus the per-module `store` the plugin tracks. Mount it
104
104
  * under `/${API_BASE}`. The `/overview` response is cached on the store version.
105
105
  */
106
- declare function createInspectorApi(ctx: TeacssPluginContext, store: InspectorStore): (req: IncomingMessage, res: ServerResponse, next: () => void) => Promise<void>;
106
+ export declare function createInspectorApi(ctx: TeacssPluginContext, store: InspectorStore): (req: IncomingMessage, res: ServerResponse, next: () => void) => Promise<void>;
107
107
  /**
108
108
  * Vite plugin: mounts the TeaCSS inspector on the dev server. Add it alongside
109
109
  * `teacss()` — it discovers the live context through that plugin's `teacss:api`
110
110
  * and serves the UI at `/${CLIENT_BASE}` with its JSON API at `/${API_BASE}`.
111
111
  * Dev-only (`apply: "serve"`).
112
112
  */
113
- declare function pluginInspector(): Plugin;
113
+ export declare function pluginInspector(): Plugin;
114
114
  //#endregion
115
- export { API_BASE, CLIENT_BASE, ConfigSummary, GenerateResultDTO, InspectorStore, LayerCss, MatchedToken, ModuleInfo, type ModuleTokens, OverviewInfo, ProjectInfo, ReplResult, categoryOf, createInspectorApi, generateDTO, pluginInspector };
115
+ export type { ModuleTokens };
package/dist/index.js CHANGED
@@ -1,2 +1,2 @@
1
- import{fileURLToPath as e}from"node:url";import{gzipSync as t}from"node:zlib";import{SKIP_END_COMMENT as n,SKIP_START_COMMENT as r}from"@teacss/core";import i from"sirv";import{BlockList as a,isIP as o}from"node:net";const s=new a;s.addSubnet(`127.0.0.0`,8,`ipv4`),s.addAddress(`::1`,`ipv6`);function c(e){if(!e)return!1;let t=e.startsWith(`[`)&&e.endsWith(`]`)?e.slice(1,-1):e,n=o(t);return n?s.check(t,n===4?`ipv4`:`ipv6`):!1}function l(e){if(!e)return;let t=e.trim().toLowerCase();if(!t)return;if(o(t))return t;if(t.startsWith(`[`)){let e=t.match(/^\[([^\]]+)\](?::(\d+))?$/);return!e||!u(e[2])?void 0:e[1]}let n=t.match(/^([^:]+)(?::(\d+))?$/);if(!(!n||!u(n[2])))return n[1].replace(/\.$/,``)}function u(e){return e===void 0||Number(e)<=65535}function d(e,t){let n=l(e);return(n===`localhost`||c(n))&&c(t)}function f(e){let t=e.indexOf(`@`),n=t>=0?e.slice(0,t):e,r=n.indexOf(`:`);if(r>=0)return n.slice(0,r);let i=n.indexOf(`-`);return(i>=0?n.slice(0,i):n)||`misc`}function p(e,t){let n=new Map;if(!t.size)return n;for(let[r,i]of e)for(let e of i){if(!t.has(e))continue;let i=n.get(e);i||(i=[],n.set(e,i)),i.push(r)}for(let e of n.values())e.length>1&&e.sort();return n}function m(e){let t=new Set;for(let n of e.values())for(let e of n)t.add(e);return t}async function h(e,t,n={}){let r=await e.generate(t,{extendedInfo:!0,preflights:!1,safelist:n.safelist??!1,id:n.id}),i=n.moduleTokens?p(n.moduleTokens,r.matched):void 0,a=[];for(let[e,t]of r.matched){let n=``;for(let e of t.data){let t=e[2];t&&(n+=n?` ${t}`:t)}let r=i?.get(e)??[];a.push({token:e,css:n,count:i?r.length:1,category:f(e),modules:r})}a.sort((e,t)=>t.count-e.count||e.token.localeCompare(t.token));let o=r.layers.map(e=>({name:e,css:r.getLayer(e)??``}));return{css:r.css,layers:o,matched:a}}const g=`__teacss`,_=`__teacss_api`,v=e=>e.split(`?`)[0],y=e=>e.replace(/([?&])(?:t|v)=[^&]+$/,``).replace(/\?$/,``);function b(e){let t=new Map;for(let[n,r]of e)t.set(n,r.tokens);return t}const x=RegExp(`(//\\s*?${r}\\s*?|\\/\\*\\s*?${r}\\s*?\\*\\/|<!--\\s*?${r}\\s*?-->)[\\s\\S]*?(//\\s*?${n}\\s*?|\\/\\*\\s*?${n}\\s*?\\*\\/|<!--\\s*?${n}\\s*?-->)`,`g`);function S(e){return!e.includes(r)||!e.includes(n)?e:e.replace(x,``)}function C(e){let t=e.config;return{presets:t.presets.map(e=>e.name).filter(e=>!!e),layers:Object.entries(t.layers).sort((e,t)=>e[1]-t[1]),rules:t.rules.length,shortcuts:Array.isArray(t.shortcuts)?t.shortcuts.length:Object.keys(t.shortcuts).length,themeKeys:Object.keys(t.theme)}}function w(e,t,n){return{version:t.version,root:e.root,modules:[...n.keys()].sort(),configSources:e.getConfigFileList?.()??[],config:C(t)}}const T=e=>t(Buffer.from(e)).length;function E(e,t){let n;return async(r,i,a)=>{let o=(e,t=200)=>{i.statusCode=t,i.setHeader(`Content-Type`,`application/json`),i.end(JSON.stringify(e))};if(!d(r.headers.host,r.socket?.remoteAddress))return o({error:`forbidden`},403);try{let i=new URL(r.url??`/`,`http://localhost`);await e.ready;let s=e.generator,{modules:c}=t;switch(i.pathname){case`/`:case``:return o(w(e,s,c));case`/overview`:{let r=t.version();if(n?.version===r)return o(n.data);let i=b(c),a=m(i);for(let t of e.tokens)a.add(t);let l=await h(s,a,{moduleTokens:i}),u={...l,gzipSize:T(l.css)};return n={version:r,data:u},o(u)}case`/repl`:{let e=i.searchParams.get(`token`)??``;return e.length>5e4?o({error:`input too large`},413):o(await h(s,e,{safelist:i.searchParams.get(`safelist`)===`true`}))}case`/module`:{let e=i.searchParams.get(`id`)??``,t=c.get(e);if(!t)return o({error:`module not found`},404);let n=await h(s,t.tokens,{id:e,moduleTokens:b(c)});return o({...n,id:e,code:t.code,gzipSize:T(n.css)})}default:return a()}}catch(e){o({error:e instanceof Error?e.message:String(e)},500)}}}function D(){let t=new Map,n=new Map,r=new Map,a=0,o=()=>{a++},s={modules:t,version:()=>a},c,l,u,d;function f(e){let r=n.get(e);if(!r?.size){n.delete(e),t.delete(e);return}if(r.size===1){t.set(e,r.values().next().value);return}let i=new Set;for(let e of r.values())for(let t of e.tokens)i.add(t);let a=r.get(e)?.code??[...r.values()].map(e=>e.code).join(`
1
+ import{fileURLToPath as e}from"node:url";import{gzipSync as t}from"node:zlib";import{SKIP_END_COMMENT as n,SKIP_START_COMMENT as r}from"@teacss/core";import i from"sirv";import{BlockList as a,isIP as o}from"node:net";const s=new a;s.addSubnet(`127.0.0.0`,8,`ipv4`),s.addAddress(`::1`,`ipv6`);function c(e){if(!e)return!1;let t=e.startsWith(`[`)&&e.endsWith(`]`)?e.slice(1,-1):e,n=o(t);return n?s.check(t,n===4?`ipv4`:`ipv6`):!1}function l(e){if(!e)return;let t=e.trim().toLowerCase();if(!t)return;if(o(t))return t;if(t.startsWith(`[`)){let e=t.match(/^\[([^\]]+)\](?::(\d+))?$/);return!e||!u(e[2])?void 0:e[1]}let n=t.match(/^([^:]+)(?::(\d+))?$/);if(n&&u(n[2]))return n[1].replace(/\.$/,``)}function u(e){return e===void 0||Number(e)<=65535}function d(e,t){let n=l(e);return(n===`localhost`||c(n))&&c(t)}function f(e){let t=e.indexOf(`@`),n=t>=0?e.slice(0,t):e,r=n.indexOf(`:`);if(r>=0)return n.slice(0,r);let i=n.indexOf(`-`);return(i>=0?n.slice(0,i):n)||`misc`}function p(e,t){let n=new Map;if(!t.size)return n;for(let[r,i]of e)for(let e of i){if(!t.has(e))continue;let i=n.get(e);i||(i=[],n.set(e,i)),i.push(r)}for(let e of n.values())e.length>1&&e.sort();return n}function m(e){let t=new Set;for(let n of e.values())for(let e of n)t.add(e);return t}async function h(e,t,n={}){let r=await e.generate(t,{extendedInfo:!0,preflights:!1,safelist:n.safelist??!1,id:n.id}),i=n.moduleTokens?p(n.moduleTokens,r.matched):void 0,a=[];for(let[e,t]of r.matched){let n=``;for(let e of t.data){let t=e[2];t&&(n+=n?` ${t}`:t)}let r=i?.get(e)??[];a.push({token:e,css:n,count:i?r.length:1,category:f(e),modules:r})}a.sort((e,t)=>t.count-e.count||e.token.localeCompare(t.token));let o=r.layers.map(e=>({name:e,css:r.getLayer(e)??``}));return{css:r.css,layers:o,matched:a}}const g=`__teacss`,_=`__teacss_api`,v=e=>e.split(`?`)[0],y=e=>e.replace(/([?&])(?:t|v)=[^&]+$/,``).replace(/\?$/,``);function b(e){let t=new Map;for(let[n,r]of e)t.set(n,r.tokens);return t}const x=RegExp(`(//\\s*?${r}\\s*?|\\/\\*\\s*?${r}\\s*?\\*\\/|<!--\\s*?${r}\\s*?-->)[\\s\\S]*?(//\\s*?${n}\\s*?|\\/\\*\\s*?${n}\\s*?\\*\\/|<!--\\s*?${n}\\s*?-->)`,`g`);function S(e){return!e.includes(r)||!e.includes(n)?e:e.replace(x,``)}function C(e){let t=e.config;return{presets:t.presets.map(e=>e.name).filter(e=>!!e),layers:Object.entries(t.layers).sort((e,t)=>e[1]-t[1]),rules:t.rules.length,shortcuts:Array.isArray(t.shortcuts)?t.shortcuts.length:Object.keys(t.shortcuts).length,themeKeys:Object.keys(t.theme)}}function w(e,t,n){return{version:t.version,root:e.root,modules:[...n.keys()].sort(),configSources:e.getConfigFileList?.()??[],config:C(t)}}const T=e=>t(Buffer.from(e)).length;function E(e,t){let n;return async(r,i,a)=>{let o=(e,t=200)=>{i.statusCode=t,i.setHeader(`Content-Type`,`application/json`),i.end(JSON.stringify(e))};if(!d(r.headers.host,r.socket?.remoteAddress))return o({error:`forbidden`},403);try{let i=new URL(r.url??`/`,`http://localhost`);await e.ready;let s=e.generator,{modules:c}=t;switch(i.pathname){case`/`:case``:return o(w(e,s,c));case`/overview`:{let r=t.version();if(n?.version===r)return o(n.data);let i=b(c),a=m(i);for(let t of e.tokens)a.add(t);let l=await h(s,a,{moduleTokens:i}),u={...l,gzipSize:T(l.css)};return n={version:r,data:u},o(u)}case`/repl`:{let e=i.searchParams.get(`token`)??``;return e.length>5e4?o({error:`input too large`},413):o(await h(s,e,{safelist:i.searchParams.get(`safelist`)===`true`}))}case`/module`:{let e=i.searchParams.get(`id`)??``,t=c.get(e);if(!t)return o({error:`module not found`},404);let n=await h(s,t.tokens,{id:e,moduleTokens:b(c)});return o({...n,id:e,code:t.code,gzipSize:T(n.css)})}default:return a()}}catch(e){o({error:e instanceof Error?e.message:String(e)},500)}}}function D(){let t=new Map,n=new Map,r=new Map,a=0,o=()=>{a++},s={modules:t,version:()=>a},c,l,u,d;function f(e){let r=n.get(e);if(!r?.size){n.delete(e),t.delete(e);return}if(r.size===1){t.set(e,r.values().next().value);return}let i=new Set;for(let e of r.values())for(let t of e.tokens)i.add(t);let a=r.get(e)?.code??[...r.values()].map(e=>e.code).join(`
2
2
  `);t.set(e,{code:a,tokens:i})}function p(e,t){return n.get(e)?.delete(t)?(f(e),!0):!1}function m(e){let i=v(e),a=y(e);if(a!==i){r.delete(a),p(i,a)&&o();return}for(let e of r.keys())v(e)===i&&r.delete(e);let s=n.delete(i),c=t.delete(i);(s||c)&&o()}function h(){d?.(),d=void 0,u?.watcher.off(`unlink`,m),u=void 0}function b(){r.clear();let e=t.size>0||n.size>0;t.clear(),n.clear(),e&&o()}function x(){h(),l?.(),l=void 0,b(),c=void 0}return{name:`teacss:inspector`,apply:`serve`,configResolved(e){l?.(),l=void 0;let t=(e.plugins.find(e=>e.name===`teacss:api`)?.api)?.getContext?.();c!==t&&(h(),b()),c=t,c?l=c.onInvalidate(o):e.logger.warn(`[teacss:inspector] no teacss() plugin found — the inspector is disabled.`)},async transform(e,t){let i=c;if(!i)return null;let a=v(t),s=y(t),l={};if(r.set(s,l),!i.filter(e,t))return r.delete(s),p(a,s)&&o(),null;try{await i.ready;let u=await i.generator.applyExtractors(S(e),t,new Set);if(c!==i||r.get(s)!==l)return null;if(u.size){let t=n.get(a);t||n.set(a,t=new Map),t.set(s,{code:e,tokens:u}),f(a),o()}else p(a,s)&&o();return null}finally{r.get(s)===l&&r.delete(s)}},async configureServer(t){let n=c;if(!n||(await n.ready,c!==n||u===t))return;if(h(),u=t,t.watcher.on(`unlink`,m),t.httpServer){let e=()=>{u===t&&x()};t.httpServer.once(`close`,e),d=()=>t.httpServer?.off(`close`,e)}let r=e(new URL(`./client`,import.meta.url));t.middlewares.use(`/${g}`,i(r,{single:!0,dev:!0})),t.middlewares.use(`/${_}`,E(n,s)),t.config.logger.info(`\n \x1b[32m➜\x1b[0m \x1b[36mTeaCSS Inspector\x1b[0m: \x1b[2mhttp://localhost:${t.config.server.port??5173}/${g}/\x1b[0m\n`)},closeBundle(){x()},devtools:{setup(e){e.docks.register({id:`teacss`,title:`TeaCSS`,icon:`mdi:tea`,type:`iframe`,url:`/${g}/`})}}}}export{_ as API_BASE,g as CLIENT_BASE,f as categoryOf,E as createInspectorApi,h as generateDTO,D as pluginInspector};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@teacss/inspector",
3
- "version": "0.4.7",
3
+ "version": "0.5.0",
4
4
  "description": "The inspector UI for TeaCSS — browse generated CSS, modules, and a live REPL.",
5
5
  "homepage": "https://css.teasim.com",
6
6
  "funding": "https://github.com/sponsors/billgo",
@@ -23,17 +23,17 @@
23
23
  "dev:client": "vite"
24
24
  },
25
25
  "dependencies": {
26
- "@teacss/core": "0.4.7",
26
+ "@teacss/core": "0.5.0",
27
27
  "sirv": "^3.0.2"
28
28
  },
29
29
  "devDependencies": {
30
- "@teacss/preset-standard": "0.4.7",
31
- "@types/react": "^19.2.17",
32
- "@types/react-dom": "^19.2.3",
33
- "@vitejs/devtools-kit": "^0.4.8",
30
+ "@teacss/preset-standard": "0.5.0",
31
+ "@types/react": "^19.2.18",
32
+ "@types/react-dom": "^19.2.7",
33
+ "@vitejs/devtools-kit": "^0.7.2",
34
34
  "react": "^19.2.8",
35
35
  "react-dom": "^19.2.8",
36
- "vite": "^8.1.5"
36
+ "vite": "^8.2.2"
37
37
  },
38
38
  "peerDependencies": {
39
39
  "vite": ">=5.0.0"