@jesscss/patch-css 2.0.0-alpha.1 → 2.0.0-alpha.10

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,35 @@
1
- # patch-css
1
+ # @jesscss/patch-css
2
2
 
3
- A small utility module to be loaded in the head of a document, without async or defer, to attach any cached stylesheets in localStorage.
3
+ **A tiny runtime helper that attaches cached stylesheets from `localStorage` in
4
+ the document head.**
4
5
 
5
- To refresh the cache, run `updateSheet` for every stylesheet.
6
+ `@jesscss/patch-css` is a small browser utility from the
7
+ [Jess](https://github.com/jesscss/jess) project. Loaded synchronously in the
8
+ `<head>` — without `async` or `defer` — it re-attaches any stylesheets that were
9
+ previously cached in `localStorage`, so styling is in place before first paint.
10
+
11
+ It exposes a single function, `updateSheet(text, id)`, which inserts (or updates)
12
+ a `<style>` element for the given id and writes the current stylesheet cache back
13
+ to `localStorage`. To refresh the cache, call `updateSheet` for each stylesheet.
14
+
15
+ ## Install
16
+
17
+ ```sh
18
+ npm install @jesscss/patch-css
19
+ ```
20
+
21
+ The `latest` and `alpha` dist-tags both point at the current alpha.
22
+
23
+ ## Status
24
+
25
+ Alpha, and an early utility surface — expect the shape to change. Please
26
+ [report bugs](https://github.com/jesscss/jess/issues).
27
+
28
+ ## Links
29
+
30
+ - Repository: <https://github.com/jesscss/jess>
31
+ - Documentation: <https://jesscss.github.io/> (currently pre-alpha content)
32
+
33
+ ## License
34
+
35
+ [MIT](https://github.com/jesscss/jess/blob/dev/LICENSE)
package/dist/index.js CHANGED
@@ -8,6 +8,7 @@
8
8
  const isBrowser = new Function('try { return this===window } catch(e) { return false }')();
9
9
 
10
10
  const sheetMap = {};
11
+
11
12
  /**
12
13
  * Insert a stylesheet by id
13
14
  */
package/lib/index.cjs ADDED
@@ -0,0 +1,50 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
+ //#region src/index.ts
3
+ /** Detect that we're in a browser */
4
+ const isBrowser = new Function("try { return this===window } catch(e) { return false }")();
5
+ const sheetMap = {};
6
+ /**
7
+ * Insert a stylesheet by id
8
+ */
9
+ const updateSheet = (text, id) => {
10
+ if (!isBrowser) return;
11
+ if (!id) throw new Error("ID is required.");
12
+ id = "id_" + id;
13
+ let el = document.getElementById(id);
14
+ if (!el) {
15
+ el = document.createElement("style");
16
+ el.setAttribute("id", id);
17
+ const head = document.getElementsByTagName("head")[0];
18
+ if (!head) throw new Error("Missing <head> element.");
19
+ el.innerHTML = text;
20
+ head.appendChild(el);
21
+ } else el.innerHTML = text;
22
+ sheetMap[id] = text;
23
+ localStorage.setItem("patchcss:sheets", JSON.stringify(sheetMap));
24
+ return el;
25
+ };
26
+ /**
27
+ * We don't set sheetMap to the cached value, because ids can
28
+ * change (maybe?), and we expect the host script to run
29
+ * updateSheet for every current value.
30
+ */
31
+ function getCachedSheets() {
32
+ const cache = localStorage.getItem("patchcss:sheets");
33
+ if (!cache) return;
34
+ const coll = JSON.parse(cache);
35
+ const head = document.getElementsByTagName("head")[0];
36
+ if (!head) return;
37
+ const fragment = document.createDocumentFragment();
38
+ for (let id in coll) if (coll.hasOwnProperty(id)) {
39
+ if (document.getElementById(id)) continue;
40
+ const el = document.createElement("style");
41
+ const text = coll[id];
42
+ el.setAttribute("id", id);
43
+ el.innerHTML = text ?? "";
44
+ fragment.appendChild(el);
45
+ }
46
+ head.appendChild(fragment);
47
+ }
48
+ if (isBrowser) getCachedSheets();
49
+ //#endregion
50
+ exports.updateSheet = updateSheet;
package/lib/index.js CHANGED
@@ -1,68 +1,49 @@
1
+ //#region src/index.ts
1
2
  /** Detect that we're in a browser */
2
- const isBrowser = new Function('try { return this===window } catch(e) { return false }')();
3
+ const isBrowser = new Function("try { return this===window } catch(e) { return false }")();
3
4
  const sheetMap = {};
4
5
  /**
5
- * Insert a stylesheet by id
6
- */
7
- export const updateSheet = (text, id) => {
8
- if (!isBrowser) {
9
- return;
10
- }
11
- if (!id) {
12
- throw new Error('ID is required.');
13
- }
14
- id = 'id_' + id;
15
- let el = document.getElementById(id);
16
- if (!el) {
17
- el = document.createElement('style');
18
- el.setAttribute('id', id);
19
- const head = document.getElementsByTagName('head')[0];
20
- if (!head) {
21
- throw new Error('Missing <head> element.');
22
- }
23
- el.innerHTML = text;
24
- head.appendChild(el);
25
- }
26
- else {
27
- el.innerHTML = text;
28
- }
29
- sheetMap[id] = text;
30
- localStorage.setItem('patchcss:sheets', JSON.stringify(sheetMap));
31
- return el;
6
+ * Insert a stylesheet by id
7
+ */
8
+ const updateSheet = (text, id) => {
9
+ if (!isBrowser) return;
10
+ if (!id) throw new Error("ID is required.");
11
+ id = "id_" + id;
12
+ let el = document.getElementById(id);
13
+ if (!el) {
14
+ el = document.createElement("style");
15
+ el.setAttribute("id", id);
16
+ const head = document.getElementsByTagName("head")[0];
17
+ if (!head) throw new Error("Missing <head> element.");
18
+ el.innerHTML = text;
19
+ head.appendChild(el);
20
+ } else el.innerHTML = text;
21
+ sheetMap[id] = text;
22
+ localStorage.setItem("patchcss:sheets", JSON.stringify(sheetMap));
23
+ return el;
32
24
  };
33
25
  /**
34
- * We don't set sheetMap to the cached value, because ids can
35
- * change (maybe?), and we expect the host script to run
36
- * updateSheet for every current value.
37
- */
26
+ * We don't set sheetMap to the cached value, because ids can
27
+ * change (maybe?), and we expect the host script to run
28
+ * updateSheet for every current value.
29
+ */
38
30
  function getCachedSheets() {
39
- const cache = localStorage.getItem('patchcss:sheets');
40
- if (!cache) {
41
- return;
42
- }
43
- const coll = JSON.parse(cache);
44
- const head = document.getElementsByTagName('head')[0];
45
- if (!head) {
46
- return;
47
- }
48
- const fragment = document.createDocumentFragment();
49
- for (let id in coll) {
50
- if (coll.hasOwnProperty(id)) {
51
- /** Sanity check, in case this script gets loaded twice */
52
- const exists = document.getElementById(id);
53
- if (exists) {
54
- continue;
55
- }
56
- const el = document.createElement('style');
57
- const text = coll[id];
58
- el.setAttribute('id', id);
59
- el.innerHTML = text ?? '';
60
- fragment.appendChild(el);
61
- }
62
- }
63
- head.appendChild(fragment);
31
+ const cache = localStorage.getItem("patchcss:sheets");
32
+ if (!cache) return;
33
+ const coll = JSON.parse(cache);
34
+ const head = document.getElementsByTagName("head")[0];
35
+ if (!head) return;
36
+ const fragment = document.createDocumentFragment();
37
+ for (let id in coll) if (coll.hasOwnProperty(id)) {
38
+ if (document.getElementById(id)) continue;
39
+ const el = document.createElement("style");
40
+ const text = coll[id];
41
+ el.setAttribute("id", id);
42
+ el.innerHTML = text ?? "";
43
+ fragment.appendChild(el);
44
+ }
45
+ head.appendChild(fragment);
64
46
  }
65
- if (isBrowser) {
66
- getCachedSheets();
67
- }
68
- //# sourceMappingURL=index.js.map
47
+ if (isBrowser) getCachedSheets();
48
+ //#endregion
49
+ export { updateSheet };
package/package.json CHANGED
@@ -1,19 +1,38 @@
1
1
  {
2
2
  "name": "@jesscss/patch-css",
3
- "version": "2.0.0-alpha.1",
3
+ "type": "module",
4
+ "version": "2.0.0-alpha.10",
5
+ "engines": {
6
+ "node": "^20.19.0 || >=22.12.0"
7
+ },
4
8
  "publishConfig": {
5
9
  "access": "public"
6
10
  },
7
11
  "description": "Attach stylesheets given an id",
8
- "main": "lib/index",
12
+ "main": "lib/index.cjs",
13
+ "module": "lib/index.js",
14
+ "types": "lib/index.d.ts",
15
+ "exports": {
16
+ ".": {
17
+ "types": "./lib/index.d.ts",
18
+ "import": "./lib/index.js",
19
+ "require": "./lib/index.cjs"
20
+ },
21
+ "./package.json": "./package.json"
22
+ },
23
+ "files": [
24
+ "lib",
25
+ "dist"
26
+ ],
9
27
  "author": "Matthew Dean",
10
28
  "license": "MIT",
11
29
  "scripts": {
12
30
  "ci": "pnpm build && pnpm test",
31
+ "test": "echo 'patch-css has no active test suite (see test:tofix)'",
13
32
  "dist": "rollup -c",
14
33
  "build": "pnpm clean && pnpm compile",
15
34
  "clean": "shx rm -rf ./dist ./lib tsconfig.tsbuildinfo",
16
- "compile": "tsc -p tsconfig.build.json && pnpm dist",
35
+ "compile": "tsdown --tsconfig tsconfig.build.json --no-dts && tsc -p tsconfig.build.json --emitDeclarationOnly && pnpm dist",
17
36
  "dev": "tsc -p tsconfig.build.json -w",
18
37
  "serve": "lite-server --baseDir=\"test\"",
19
38
  "test:tofix": "pnpm dist && jest",
package/bs-config.js DELETED
@@ -1,8 +0,0 @@
1
- module.exports = {
2
- open: false,
3
- server: {
4
- middleware: {
5
- 0: null
6
- }
7
- }
8
- }
package/eslint.config.mjs DELETED
@@ -1,16 +0,0 @@
1
- import rootConfig from '../../eslint.config.mjs';
2
- import tseslint from 'typescript-eslint';
3
-
4
- export default tseslint.config([
5
- ...rootConfig,
6
- {
7
- files: ['*.ts', '*.tsx'],
8
- languageOptions: {
9
- parser: tseslint.parser,
10
- parserOptions: {
11
- projectService: true,
12
- tsconfigRootDir: import.meta.dirname
13
- }
14
- }
15
- }
16
- ]);
package/lib/index.js.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,qCAAqC;AACrC,MAAM,SAAS,GAAG,IAAI,QAAQ,CAAC,wDAAwD,CAAC,EAAE,CAAC;AAE3F,MAAM,QAAQ,GAA2B,EAAE,CAAC;AAC5C;;GAEG;AACH,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC,IAAY,EAAE,EAAU,EAAE,EAAE;IACtD,IAAI,CAAC,SAAS,EAAE,CAAC;QACf,OAAO;IACT,CAAC;IACD,IAAI,CAAC,EAAE,EAAE,CAAC;QACR,MAAM,IAAI,KAAK,CAAC,iBAAiB,CAAC,CAAC;IACrC,CAAC;IACD,EAAE,GAAG,KAAK,GAAG,EAAE,CAAC;IAChB,IAAI,EAAE,GAAG,QAAQ,CAAC,cAAc,CAAC,EAAE,CAAC,CAAC;IACrC,IAAI,CAAC,EAAE,EAAE,CAAC;QACR,EAAE,GAAG,QAAQ,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC;QACrC,EAAE,CAAC,YAAY,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;QAC1B,MAAM,IAAI,GAAG,QAAQ,CAAC,oBAAoB,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;QACtD,IAAI,CAAC,IAAI,EAAE,CAAC;YACV,MAAM,IAAI,KAAK,CAAC,yBAAyB,CAAC,CAAC;QAC7C,CAAC;QACD,EAAE,CAAC,SAAS,GAAG,IAAI,CAAC;QACpB,IAAI,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC;IACvB,CAAC;SAAM,CAAC;QACN,EAAE,CAAC,SAAS,GAAG,IAAI,CAAC;IACtB,CAAC;IACD,QAAQ,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC;IACpB,YAAY,CAAC,OAAO,CAAC,iBAAiB,EAAE,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC,CAAC;IAClE,OAAO,EAAE,CAAC;AACZ,CAAC,CAAA;AAED;;;;GAIG;AACH,SAAS,eAAe;IACtB,MAAM,KAAK,GAAG,YAAY,CAAC,OAAO,CAAC,iBAAiB,CAAC,CAAC;IACtD,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,OAAO;IACT,CAAC;IACD,MAAM,IAAI,GAA2B,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;IACvD,MAAM,IAAI,GAAG,QAAQ,CAAC,oBAAoB,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;IACtD,IAAI,CAAC,IAAI,EAAE,CAAC;QACV,OAAO;IACT,CAAC;IAED,MAAM,QAAQ,GAAG,QAAQ,CAAC,sBAAsB,EAAE,CAAC;IAEnD,KAAK,IAAI,EAAE,IAAI,IAAI,EAAE,CAAC;QACpB,IAAI,IAAI,CAAC,cAAc,CAAC,EAAE,CAAC,EAAE,CAAC;YAC5B,0DAA0D;YAC1D,MAAM,MAAM,GAAG,QAAQ,CAAC,cAAc,CAAC,EAAE,CAAC,CAAC;YAC3C,IAAI,MAAM,EAAE,CAAC;gBACX,SAAS;YACX,CAAC;YACD,MAAM,EAAE,GAAG,QAAQ,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC;YAC3C,MAAM,IAAI,GAAG,IAAI,CAAC,EAAE,CAAC,CAAC;YACtB,EAAE,CAAC,YAAY,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;YAC1B,EAAE,CAAC,SAAS,GAAG,IAAI,IAAI,EAAE,CAAC;YAC1B,QAAQ,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC;QAC3B,CAAC;IACH,CAAC;IACD,IAAI,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAC;AAC7B,CAAC;AAED,IAAI,SAAS,EAAE,CAAC;IACd,eAAe,EAAE,CAAC;AACpB,CAAC"}
package/rollup.config.mjs DELETED
@@ -1,16 +0,0 @@
1
-
2
- import sucrase from '@rollup/plugin-sucrase'
3
-
4
- export default {
5
- input: './src/index.ts',
6
- plugins: [
7
- sucrase({
8
- transforms: ['typescript']
9
- })
10
- ],
11
- output: {
12
- file: './dist/index.js',
13
- format: 'umd',
14
- name: 'patchCss'
15
- }
16
- }
package/src/index.ts DELETED
@@ -1,71 +0,0 @@
1
- /** Detect that we're in a browser */
2
- const isBrowser = new Function('try { return this===window } catch(e) { return false }')();
3
-
4
- const sheetMap: Record<string, string> = {};
5
- /**
6
- * Insert a stylesheet by id
7
- */
8
- export const updateSheet = (text: string, id: string) => {
9
- if (!isBrowser) {
10
- return;
11
- }
12
- if (!id) {
13
- throw new Error('ID is required.');
14
- }
15
- id = 'id_' + id;
16
- let el = document.getElementById(id);
17
- if (!el) {
18
- el = document.createElement('style');
19
- el.setAttribute('id', id);
20
- const head = document.getElementsByTagName('head')[0];
21
- if (!head) {
22
- throw new Error('Missing <head> element.');
23
- }
24
- el.innerHTML = text;
25
- head.appendChild(el);
26
- } else {
27
- el.innerHTML = text;
28
- }
29
- sheetMap[id] = text;
30
- localStorage.setItem('patchcss:sheets', JSON.stringify(sheetMap));
31
- return el;
32
- }
33
-
34
- /**
35
- * We don't set sheetMap to the cached value, because ids can
36
- * change (maybe?), and we expect the host script to run
37
- * updateSheet for every current value.
38
- */
39
- function getCachedSheets() {
40
- const cache = localStorage.getItem('patchcss:sheets');
41
- if (!cache) {
42
- return;
43
- }
44
- const coll: Record<string, string> = JSON.parse(cache);
45
- const head = document.getElementsByTagName('head')[0];
46
- if (!head) {
47
- return;
48
- }
49
-
50
- const fragment = document.createDocumentFragment();
51
-
52
- for (let id in coll) {
53
- if (coll.hasOwnProperty(id)) {
54
- /** Sanity check, in case this script gets loaded twice */
55
- const exists = document.getElementById(id);
56
- if (exists) {
57
- continue;
58
- }
59
- const el = document.createElement('style');
60
- const text = coll[id];
61
- el.setAttribute('id', id);
62
- el.innerHTML = text ?? '';
63
- fragment.appendChild(el);
64
- }
65
- }
66
- head.appendChild(fragment);
67
- }
68
-
69
- if (isBrowser) {
70
- getCachedSheets();
71
- }
package/test/bootstrap.js DELETED
@@ -1,46 +0,0 @@
1
- const puppeteer = require('puppeteer')
2
-
3
- const globalVariables = {
4
- browser: global.browser,
5
- expect: global.expect
6
- }
7
-
8
- // puppeteer options
9
- const opts = {
10
- headless: true,
11
- timeout: 10000
12
- }
13
-
14
- const startServer = () => new Promise((resolve) => {
15
- let browserSync = require('browser-sync').create()
16
- browserSync.init({
17
- watch: true,
18
- open: false,
19
- server: {
20
- baseDir: './',
21
- directory: true
22
- },
23
- callbacks: {
24
- ready() {
25
- resolve(browserSync)
26
- }
27
- }
28
- })
29
- })
30
- let browserSync
31
- let browser
32
- // expose variables
33
- beforeAll(async () => {
34
- browserSync = await startServer()
35
- global.expect = expect
36
- browser = global.browser = await puppeteer.launch(opts)
37
- })
38
-
39
- // close browser and reset global variables
40
- afterAll(() => {
41
- browser.close()
42
- browserSync.exit()
43
-
44
- global.browser = globalVariables.browser
45
- global.expect = globalVariables.expect
46
- })
@@ -1,14 +0,0 @@
1
- <!DOCTYPE html>
2
- <html>
3
- <head>
4
- <style>
5
- .box { color: red; }
6
- </style>
7
- </head>
8
- <body>
9
- <script src="../../dist/index.js"></script>
10
- <script>
11
- console.log('foo')
12
- </script>
13
- </body>
14
- </html>
@@ -1,20 +0,0 @@
1
- describe('simple test for updated CSS', function() {
2
- let page
3
- let browser
4
-
5
- beforeAll(async () => {
6
- page = await browser.newPage()
7
- await page.goto('http://localhost:3000/test/files/01.html')
8
- })
9
-
10
- afterAll(async () => {
11
- await page.close()
12
- })
13
-
14
- it('should add a new style block', async () => {
15
- console.log(await browser.version())
16
- await page.evaluate('patchCss.updateSheet(\'body { background: blue }\', \'foo\')')
17
- let bg = await page.$eval('body', el => getComputedStyle(el).backgroundColor)
18
- expect(bg).to.eq('rgb(0, 0, 255)')
19
- })
20
- })
@@ -1,10 +0,0 @@
1
- {
2
- "extends": "./tsconfig.json",
3
- "compilerOptions": {
4
- "outDir": "./lib",
5
- "rootDir": "./src",
6
- "noEmit": false
7
- },
8
- "include": ["src/**/*"],
9
- "exclude": ["node_modules", "lib", "dist"]
10
- }
package/tsconfig.json DELETED
@@ -1,11 +0,0 @@
1
- {
2
- "extends": "../../tsconfig.json",
3
- "compilerOptions": {
4
- "noEmit": true,
5
- "outDir": "./lib",
6
- "rootDir": "./src",
7
- "lib": ["DOM"]
8
- },
9
- "include": ["src/**/*"],
10
- "exclude": ["node_modules", "lib", "dist"]
11
- }