@master/css-server 2.0.0-rc.69 → 2.0.0-rc.70

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
@@ -41,16 +41,58 @@
41
41
  <img alt="Follow @mastercorg" src="https://img.shields.io/static/v1?label=%20&message=twitter&color=f6f7f8&logo=twitter&style=for-the-badge">
42
42
  </picture>
43
43
  </a>
44
- <a aria-label="Github Actions" href="https://github.com/master-co/css/actions/workflows/release.yml">
44
+ <a aria-label="Github Actions" href="https://github.com/master-co/css/actions/workflows/ci-release.yml">
45
45
  <picture>
46
- <source media="(prefers-color-scheme: dark)" srcset="https://img.shields.io/github/actions/workflow/status/master-co/css/release.yml?branch=rc&label=%20&message=twitter&color=212022&logo=githubactions&style=for-the-badge">
47
- <source media="(prefers-color-scheme: light)" srcset="https://img.shields.io/github/actions/workflow/status/master-co/css/release.yml?branch=rc&label=%20&message=twitter&color=f6f7f8&logo=githubactions&style=for-the-badge&logoColor=%23000">
48
- <img alt="Github release actions" src="https://img.shields.io/github/actions/workflow/status/master-co/css/release.yml?branch=rc&label=%20&message=twitter&color=f6f7f8&logo=githubactions&style=for-the-badge&logoColor=%23000">
46
+ <source media="(prefers-color-scheme: dark)" srcset="https://img.shields.io/github/actions/workflow/status/master-co/css/ci-release.yml?branch=rc&label=%20&message=twitter&color=212022&logo=githubactions&style=for-the-badge">
47
+ <source media="(prefers-color-scheme: light)" srcset="https://img.shields.io/github/actions/workflow/status/master-co/css/ci-release.yml?branch=rc&label=%20&message=twitter&color=f6f7f8&logo=githubactions&style=for-the-badge&logoColor=%23000">
48
+ <img alt="Github release actions" src="https://img.shields.io/github/actions/workflow/status/master-co/css/ci-release.yml?branch=rc&label=%20&message=twitter&color=f6f7f8&logo=githubactions&style=for-the-badge&logoColor=%23000">
49
49
  </picture>
50
50
  </a>
51
51
  </p>
52
52
 
53
53
  </div>
54
54
 
55
- ## Documentation
56
- Check out the official [documentation](https://rc.css.master.co/reference/server).
55
+ ## Installation
56
+
57
+ ```bash
58
+ npm install @master/css-server
59
+ ```
60
+
61
+ `@master/css-server` renders required Master CSS from HTML. It parses HTML, extracts class names, creates a `MasterCSS` instance, and injects or updates `<style id="master-css">`.
62
+
63
+ ## API
64
+
65
+ ### `render()`
66
+
67
+ Render HTML and inject generated CSS.
68
+
69
+ ```ts
70
+ import { render } from '@master/css-server'
71
+
72
+ const result = render('<div class="text:center"></div>', manifest)
73
+
74
+ console.log(result.html)
75
+ console.log(result.css.text)
76
+ ```
77
+
78
+ ### `renderCSS()`
79
+
80
+ Render only the CSS needed by an HTML string.
81
+
82
+ ```ts
83
+ import { renderCSS } from '@master/css-server'
84
+
85
+ const css = renderCSS('<div class="text:center"></div>', manifest)
86
+ ```
87
+
88
+ ### `parseHTML()`
89
+
90
+ Parse HTML into the lightweight DOM representation used by the server renderer.
91
+
92
+ ```ts
93
+ import { parseHTML } from '@master/css-server'
94
+
95
+ const document = parseHTML('<html><head></head><body></body></html>')
96
+ ```
97
+
98
+ Use official framework integrations when possible; they compose this package with manifest loading, source scanning, and runtime hydration.
@@ -0,0 +1,2 @@
1
+ import { createCSSWithNativeDeclarations } from '@master/css-validator';
2
+ export default createCSSWithNativeDeclarations;
@@ -0,0 +1,2 @@
1
+ import { createCSSWithNativeDeclarations } from '@master/css-validator';
2
+ export { createCSSWithNativeDeclarations as default } from '@master/css-validator';
@@ -0,0 +1,2 @@
1
+ import type { MasterCSSManifest } from '@master/css-schema/manifest';
2
+ export default function getDefaultManifest(): MasterCSSManifest;
@@ -0,0 +1,8 @@
1
+ import defaultManifestJSON from '@master/css-preset/default-manifest.json' with { type: 'json' };
2
+
3
+ const defaultManifest = defaultManifestJSON;
4
+ function getDefaultManifest() {
5
+ return defaultManifest;
6
+ }
7
+
8
+ export { getDefaultManifest as default };
package/dist/index.d.ts CHANGED
@@ -1,3 +1,5 @@
1
1
  export { default as render } from './render';
2
+ export type { RenderOptions, RenderResult, RenderHydrationManifestOption } from './render';
2
3
  export { default as renderCSS } from './render-css';
3
4
  export { default as parseHTML } from './parse-html';
5
+ export { default as createServerCSS } from './create-server-css';
package/dist/index.mjs CHANGED
@@ -1,3 +1,4 @@
1
1
  export { default as render } from './render.mjs';
2
2
  export { default as renderCSS } from './render-css.mjs';
3
3
  export { default as parseHTML } from './parse-html.mjs';
4
+ export { createCSSWithNativeDeclarations as createServerCSS } from '@master/css-validator';
@@ -1,4 +1,5 @@
1
1
  import { DomHandler, Parser } from 'htmlparser2';
2
+ import { MASTER_CSS_RUNTIME_STYLE_ID } from '@master/css-schema/runtime-style';
2
3
  import decodeHTML from './decode-html.mjs';
3
4
 
4
5
  /**
@@ -20,10 +21,11 @@ import decodeHTML from './decode-html.mjs';
20
21
  break;
21
22
  }
22
23
  } else if (element.type === 'style') {
23
- if (element.attribs.id === 'master') styleElement = element;
24
+ if (element.attribs.id === MASTER_CSS_RUNTIME_STYLE_ID) styleElement = element;
24
25
  }
25
26
  if (element.attribs.class) {
26
- element.attribs.class.split(' ').forEach((className)=>{
27
+ element.attribs.class.trim().split(/\s+/).forEach((className)=>{
28
+ if (!className) return;
27
29
  className = decodeHTML(className);
28
30
  if (!classes.includes(className)) classes.push(className);
29
31
  });
@@ -1,8 +1,9 @@
1
- import { MasterCSS, Config } from '@master/css';
1
+ import { MasterCSS } from '@master/css';
2
+ import type { MasterCSSManifest } from '@master/css-schema/manifest';
2
3
  /**
3
4
  * Renders the Master CSS string from HTML
4
5
  * @param html
5
- * @param config
6
+ * @param manifest
6
7
  * @returns MasterCSS
7
8
  */
8
- export default function renderCSS(html: string, config?: Config): MasterCSS | undefined;
9
+ export default function renderCSS(html: string, manifest?: MasterCSSManifest): MasterCSS | undefined;
@@ -1,16 +1,17 @@
1
1
  import parseHTML from './parse-html.mjs';
2
- import { createCSS } from '@master/css';
2
+ import getDefaultManifest from './default-manifest.mjs';
3
+ import { createCSSWithNativeDeclarations } from '@master/css-validator';
3
4
 
4
5
  /**
5
6
  * Renders the Master CSS string from HTML
6
7
  * @param html
7
- * @param config
8
+ * @param manifest
8
9
  * @returns MasterCSS
9
- */ function renderCSS(html, config) {
10
+ */ function renderCSS(html, manifest) {
10
11
  if (!html) return;
11
12
  const { classes } = parseHTML(html);
12
13
  if (!classes.length) return;
13
- const css = createCSS(config);
14
+ const css = createCSSWithNativeDeclarations(manifest || getDefaultManifest());
14
15
  classes.forEach((eachClass)=>css.add(eachClass));
15
16
  return css;
16
17
  }
package/dist/render.d.ts CHANGED
@@ -1,11 +1,17 @@
1
- import { MasterCSS, Config } from '@master/css';
1
+ import { MasterCSS } from '@master/css';
2
+ import type { MasterCSSManifest } from '@master/css-schema/manifest';
3
+ import { type MasterCSSHydrationManifest } from '@master/css-schema/hydration-manifest';
2
4
  import { Element, ChildNode } from 'domhandler';
3
- /**
4
- * Renders the page-required and sorted CSS text from HTML and injected it back into HTML
5
- * @param html
6
- * @param config
7
- */
8
- export default function render(html: string, config?: Config): {
5
+ export type RenderExternalHydrationManifestSource = string | ((json: string, hydrationManifest: MasterCSSHydrationManifest) => string);
6
+ export interface RenderExternalHydrationManifestOption {
7
+ type: 'external';
8
+ src: RenderExternalHydrationManifestSource;
9
+ }
10
+ export type RenderHydrationManifestOption = 'return' | 'inject' | false | RenderExternalHydrationManifestOption;
11
+ export interface RenderOptions {
12
+ hydrationManifest?: RenderHydrationManifestOption;
13
+ }
14
+ export interface RenderResult {
9
15
  html: string;
10
16
  css?: MasterCSS;
11
17
  classes: string[];
@@ -13,4 +19,11 @@ export default function render(html: string, config?: Config): {
13
19
  htmlElement: Element | null;
14
20
  headElement: Element | null;
15
21
  styleElement: Element | null;
16
- };
22
+ hydrationManifest?: MasterCSSHydrationManifest;
23
+ }
24
+ /**
25
+ * Renders the page-required and sorted CSS text from HTML and injected it back into HTML
26
+ * @param html
27
+ * @param manifest
28
+ */
29
+ export default function render(html: string, manifest?: MasterCSSManifest, options?: RenderOptions): RenderResult;
package/dist/render.mjs CHANGED
@@ -1,33 +1,170 @@
1
- import { createCSS } from '@master/css';
1
+ import { createHydrationManifest } from '@master/css';
2
+ import { MASTER_CSS_HYDRATION_MANIFEST_ATTR, serializeMasterCSSHydrationManifest, MASTER_CSS_HYDRATION_MANIFEST_SCRIPT_ID } from '@master/css-schema/hydration-manifest';
3
+ import { MASTER_CSS_RUNTIME_STYLE_ID } from '@master/css-schema/runtime-style';
2
4
  import parseHTML from './parse-html.mjs';
5
+ import getDefaultManifest from './default-manifest.mjs';
6
+ import { createCSSWithNativeDeclarations } from '@master/css-validator';
3
7
  import { Text, Element } from 'domhandler';
4
8
  import serialize from 'dom-serializer';
5
9
 
10
+ function createHydrationManifestScript(hydrationManifest) {
11
+ return new Element('script', {
12
+ type: 'application/json',
13
+ id: MASTER_CSS_HYDRATION_MANIFEST_SCRIPT_ID
14
+ }, [
15
+ new Text(serializeMasterCSSHydrationManifest(hydrationManifest))
16
+ ]);
17
+ }
18
+ function isHydrationManifestScript(node) {
19
+ return node.type === 'script' && node.name === 'script' && node.attribs.id === MASTER_CSS_HYDRATION_MANIFEST_SCRIPT_ID;
20
+ }
21
+ function setHydrationManifestScript(element, hydrationManifest) {
22
+ element.attribs.type = 'application/json';
23
+ element.attribs.id = MASTER_CSS_HYDRATION_MANIFEST_SCRIPT_ID;
24
+ element.childNodes = [
25
+ new Text(serializeMasterCSSHydrationManifest(hydrationManifest))
26
+ ];
27
+ }
28
+ function isExternalHydrationManifestOption(hydrationManifest) {
29
+ return typeof hydrationManifest === 'object' && hydrationManifest?.type === 'external';
30
+ }
31
+ function getExternalHydrationManifestSource(option, hydrationManifest) {
32
+ const json = serializeMasterCSSHydrationManifest(hydrationManifest);
33
+ return typeof option.src === 'function' ? option.src(json, hydrationManifest) : option.src;
34
+ }
35
+ function findHydrationManifestScripts(childNodes, matches = []) {
36
+ for(let index = 0; index < childNodes.length; index++){
37
+ const node = childNodes[index];
38
+ if (isHydrationManifestScript(node)) {
39
+ matches.push({
40
+ element: node,
41
+ childNodes,
42
+ index
43
+ });
44
+ }
45
+ if ('childNodes' in node) {
46
+ findHydrationManifestScripts(node.childNodes, matches);
47
+ }
48
+ }
49
+ return matches;
50
+ }
51
+ function removeNode(nodes, target) {
52
+ const index = nodes.indexOf(target);
53
+ if (index !== -1) {
54
+ nodes.splice(index, 1);
55
+ return true;
56
+ }
57
+ for (const node of nodes){
58
+ if ('childNodes' in node && removeNode(node.childNodes, target)) {
59
+ return true;
60
+ }
61
+ }
62
+ return false;
63
+ }
64
+ function removeHydrationManifestScripts(nodes) {
65
+ const existingScripts = findHydrationManifestScripts(nodes);
66
+ for(let index = existingScripts.length - 1; index >= 0; index--){
67
+ const script = existingScripts[index];
68
+ script.childNodes.splice(script.index, 1);
69
+ }
70
+ return existingScripts.length > 0;
71
+ }
72
+ function removeExternalHydrationManifest(styleElement) {
73
+ if (styleElement) {
74
+ delete styleElement.attribs[MASTER_CSS_HYDRATION_MANIFEST_ATTR];
75
+ }
76
+ }
77
+ function injectExternalHydrationManifest(nodes, styleElement, src) {
78
+ removeHydrationManifestScripts(nodes);
79
+ if (styleElement) {
80
+ styleElement.attribs[MASTER_CSS_HYDRATION_MANIFEST_ATTR] = src;
81
+ }
82
+ }
83
+ function injectHydrationManifest(nodes, htmlElement, headElement, styleElement, hydrationManifest) {
84
+ removeExternalHydrationManifest(styleElement);
85
+ const existingScripts = findHydrationManifestScripts(nodes);
86
+ if (existingScripts.length) {
87
+ const [firstScript, ...duplicateScripts] = existingScripts;
88
+ setHydrationManifestScript(firstScript.element, hydrationManifest);
89
+ for(let index = duplicateScripts.length - 1; index >= 0; index--){
90
+ const script = duplicateScripts[index];
91
+ script.childNodes.splice(script.index, 1);
92
+ }
93
+ return;
94
+ }
95
+ const scriptElement = createHydrationManifestScript(hydrationManifest);
96
+ if (headElement) {
97
+ headElement.childNodes.push(scriptElement);
98
+ } else if (htmlElement) {
99
+ headElement = new Element('head', {}, [
100
+ scriptElement
101
+ ]);
102
+ htmlElement.childNodes.unshift(headElement);
103
+ } else {
104
+ const styleElementIndex = styleElement ? nodes.indexOf(styleElement) : -1;
105
+ if (styleElementIndex === -1) {
106
+ nodes.unshift(scriptElement);
107
+ } else {
108
+ nodes.splice(styleElementIndex + 1, 0, scriptElement);
109
+ }
110
+ }
111
+ }
6
112
  /**
7
113
  * Renders the page-required and sorted CSS text from HTML and injected it back into HTML
8
114
  * @param html
9
- * @param config
10
- */ function render(html, config) {
115
+ * @param manifest
116
+ */ function render(html, manifest, options = {}) {
11
117
  const context = parseHTML(html);
12
118
  const { classes, nodes, htmlElement } = context;
13
119
  let { headElement, styleElement } = context;
120
+ const externalHydrationManifestOption = isExternalHydrationManifestOption(options.hydrationManifest) ? options.hydrationManifest : undefined;
121
+ if (!classes.length && externalHydrationManifestOption) {
122
+ removeHydrationManifestScripts(nodes);
123
+ removeExternalHydrationManifest(styleElement);
124
+ }
14
125
  if (!classes.length) return {
15
- html,
126
+ html: externalHydrationManifestOption ? serialize(nodes, {
127
+ decodeEntities: false,
128
+ encodeEntities: false
129
+ }) : html,
16
130
  classes,
17
131
  nodes,
18
132
  htmlElement,
19
133
  headElement,
20
134
  styleElement
21
135
  };
22
- const css = createCSS(config);
136
+ const css = createCSSWithNativeDeclarations(manifest || getDefaultManifest());
23
137
  classes.forEach((eachClass)=>css.add(eachClass));
138
+ const hydrationManifest = options.hydrationManifest === false ? undefined : createHydrationManifest(css);
139
+ if (!css.text) {
140
+ if ((options.hydrationManifest === 'inject' || externalHydrationManifestOption) && styleElement) {
141
+ removeNode(nodes, styleElement);
142
+ styleElement = null;
143
+ }
144
+ if (externalHydrationManifestOption) {
145
+ removeHydrationManifestScripts(nodes);
146
+ }
147
+ return {
148
+ html: serialize(nodes, {
149
+ decodeEntities: false,
150
+ encodeEntities: false
151
+ }),
152
+ css,
153
+ classes,
154
+ hydrationManifest,
155
+ nodes,
156
+ htmlElement,
157
+ headElement,
158
+ styleElement
159
+ };
160
+ }
24
161
  if (styleElement) {
25
162
  styleElement.childNodes = [
26
163
  new Text(css.text)
27
164
  ];
28
165
  } else {
29
166
  styleElement = new Element('style', {
30
- id: 'master'
167
+ id: MASTER_CSS_RUNTIME_STYLE_ID
31
168
  }, [
32
169
  new Text(css.text)
33
170
  ]);
@@ -44,6 +181,13 @@ import serialize from 'dom-serializer';
44
181
  }
45
182
  }
46
183
  }
184
+ if (options.hydrationManifest === 'inject' && hydrationManifest?.rules.length) {
185
+ injectHydrationManifest(nodes, htmlElement, headElement, styleElement, hydrationManifest);
186
+ } else if (externalHydrationManifestOption && hydrationManifest?.rules.length) {
187
+ injectExternalHydrationManifest(nodes, styleElement, getExternalHydrationManifestSource(externalHydrationManifestOption, hydrationManifest));
188
+ } else {
189
+ removeExternalHydrationManifest(styleElement);
190
+ }
47
191
  return {
48
192
  html: serialize(nodes, {
49
193
  decodeEntities: false,
@@ -51,6 +195,7 @@ import serialize from 'dom-serializer';
51
195
  }),
52
196
  css,
53
197
  classes,
198
+ hydrationManifest,
54
199
  nodes,
55
200
  htmlElement,
56
201
  headElement,
package/package.json CHANGED
@@ -1 +1 @@
1
- {"name":"@master/css-server","type":"module","scripts":{"build":"techor build \"src/**/*.ts\"","dev":"pnpm build --watch","lint":"eslint","type-check":"tsc --noEmit","test":"vitest"},"license":"MIT","description":"Render Master CSS on the server side","author":"Aoyue Design LLC.","funding":"https://rc.css.master.co/sponsor","homepage":"https://css.master.co","bugs":{"url":"https://github.com/master-co/css/issues"},"repository":{"type":"git","url":"https://github.com/master-co/css.git","directory":"packages/server"},"keywords":["server","static","html","markup","dom","css","mastercss"],"sideEffects":false,"main":"./dist/index.cjs","module":"./dist/index.mjs","jsnext:main":"./dist/index.mjs","esnext":"./dist/index.mjs","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.mjs","require":"./dist/index.cjs"}},"files":["dist"],"publishConfig":{"access":"public","provenance":true},"dependencies":{"@master/css":"^2.0.0-rc.69","dom-serializer":"^2.0.0","domhandler":"^5.0.3","htmlparser2":"^10.0.0"},"devDependencies":{"shared":"^2.0.0-rc.69"},"version":"2.0.0-rc.69"}
1
+ {"name":"@master/css-server","type":"module","scripts":{"build":"techor build \"src/**/*.ts\" --formats esm && node scripts/restore-json-import-attributes.mjs","dev":"pnpm build --watch","lint":"eslint","type-check":"tsc --noEmit","test":"vitest"},"license":"MIT","description":"Render Master CSS on the server side","author":"Aoyue Design LLC.","funding":"https://rc.css.master.co/sponsor","homepage":"https://css.master.co","bugs":{"url":"https://github.com/master-co/css/issues"},"repository":{"type":"git","url":"https://github.com/master-co/css.git","directory":"packages/server"},"keywords":["server","static","html","markup","dom","css","mastercss"],"sideEffects":false,"main":"./dist/index.mjs","module":"./dist/index.mjs","jsnext:main":"./dist/index.mjs","esnext":"./dist/index.mjs","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.mjs","default":"./dist/index.mjs"}},"files":["dist"],"publishConfig":{"access":"public","provenance":true},"dependencies":{"@master/css":"^2.0.0-rc.70","@master/css-preset":"^2.0.0-rc.70","@master/css-validator":"^2.0.0-rc.70","dom-serializer":"^3.1.1","domhandler":"^6.0.1","htmlparser2":"^12.0.0","@master/css-schema":"^2.0.0-rc.70"},"devDependencies":{"@master/css-compiler":"^2.0.0-rc.70"},"version":"2.0.0-rc.70"}
@@ -1,29 +0,0 @@
1
- 'use strict';
2
-
3
- /*
4
- * The framework will encode attribute values ​​when rendering HTML to prevent XSS,
5
- * so we must decode it for correct CSS selectors.
6
- * https://github.com/facebook/react/issues/27836
7
- */ function decodeHTML(html) {
8
- return html.replace(/&(amp|apos|#39|#x27|quot|lt|gt);/g, (match, entity)=>{
9
- switch(entity){
10
- case 'amp':
11
- return '&';
12
- case 'apos':
13
- case '#39':
14
- case '#x27':
15
- return '\'';
16
- case 'quot':
17
- return '"';
18
- case 'lt':
19
- return '<';
20
- case 'gt':
21
- return '>';
22
- default:
23
- return match // 如果不是已知的實體,保留原樣
24
- ;
25
- }
26
- });
27
- }
28
-
29
- module.exports = decodeHTML;
package/dist/index.cjs DELETED
@@ -1,11 +0,0 @@
1
- 'use strict';
2
-
3
- var render = require('./render.cjs');
4
- var renderCss = require('./render-css.cjs');
5
- var parseHtml = require('./parse-html.cjs');
6
-
7
-
8
-
9
- exports.render = render;
10
- exports.renderCSS = renderCss;
11
- exports.parseHTML = parseHtml;
@@ -1,46 +0,0 @@
1
- 'use strict';
2
-
3
- var htmlparser2 = require('htmlparser2');
4
- var decodeHtml = require('./decode-html.cjs');
5
-
6
- /**
7
- * @param html
8
- * @returns {classes from html, root element}
9
- */ function parseHTML(html) {
10
- const classes = [];
11
- let htmlElement = null;
12
- let headElement = null;
13
- let styleElement = null;
14
- const handler = new htmlparser2.DomHandler(undefined, {}, (element)=>{
15
- if (element.type === 'tag') {
16
- switch(element.name){
17
- case 'html':
18
- htmlElement = element;
19
- break;
20
- case 'head':
21
- headElement = element;
22
- break;
23
- }
24
- } else if (element.type === 'style') {
25
- if (element.attribs.id === 'master') styleElement = element;
26
- }
27
- if (element.attribs.class) {
28
- element.attribs.class.split(' ').forEach((className)=>{
29
- className = decodeHtml(className);
30
- if (!classes.includes(className)) classes.push(className);
31
- });
32
- }
33
- });
34
- new htmlparser2.Parser(handler, {
35
- decodeEntities: false
36
- }).end(html);
37
- return {
38
- classes,
39
- nodes: handler.root.childNodes,
40
- htmlElement,
41
- headElement,
42
- styleElement
43
- };
44
- }
45
-
46
- module.exports = parseHTML;
@@ -1,20 +0,0 @@
1
- 'use strict';
2
-
3
- var parseHtml = require('./parse-html.cjs');
4
- var css = require('@master/css');
5
-
6
- /**
7
- * Renders the Master CSS string from HTML
8
- * @param html
9
- * @param config
10
- * @returns MasterCSS
11
- */ function renderCSS(html, config) {
12
- if (!html) return;
13
- const { classes } = parseHtml(html);
14
- if (!classes.length) return;
15
- const css$1 = css.createCSS(config);
16
- classes.forEach((eachClass)=>css$1.add(eachClass));
17
- return css$1;
18
- }
19
-
20
- module.exports = renderCSS;
package/dist/render.cjs DELETED
@@ -1,63 +0,0 @@
1
- 'use strict';
2
-
3
- var css = require('@master/css');
4
- var parseHtml = require('./parse-html.cjs');
5
- var domhandler = require('domhandler');
6
- var serialize = require('dom-serializer');
7
-
8
- /**
9
- * Renders the page-required and sorted CSS text from HTML and injected it back into HTML
10
- * @param html
11
- * @param config
12
- */ function render(html, config) {
13
- const context = parseHtml(html);
14
- const { classes, nodes, htmlElement } = context;
15
- let { headElement, styleElement } = context;
16
- if (!classes.length) return {
17
- html,
18
- classes,
19
- nodes,
20
- htmlElement,
21
- headElement,
22
- styleElement
23
- };
24
- const css$1 = css.createCSS(config);
25
- classes.forEach((eachClass)=>css$1.add(eachClass));
26
- if (styleElement) {
27
- styleElement.childNodes = [
28
- new domhandler.Text(css$1.text)
29
- ];
30
- } else {
31
- styleElement = new domhandler.Element('style', {
32
- id: 'master'
33
- }, [
34
- new domhandler.Text(css$1.text)
35
- ]);
36
- if (headElement) {
37
- headElement.childNodes.push(styleElement);
38
- } else {
39
- if (htmlElement) {
40
- headElement = new domhandler.Element('head', {}, [
41
- styleElement
42
- ]);
43
- htmlElement.childNodes.unshift(headElement);
44
- } else {
45
- nodes.unshift(styleElement);
46
- }
47
- }
48
- }
49
- return {
50
- html: serialize(nodes, {
51
- decodeEntities: false,
52
- encodeEntities: false
53
- }),
54
- css: css$1,
55
- classes,
56
- nodes,
57
- htmlElement,
58
- headElement,
59
- styleElement
60
- };
61
- }
62
-
63
- module.exports = render;