Skip to content

Commit fb52ff5

Browse files
committed
feat: support esm and cjs
1 parent 723bb31 commit fb52ff5

File tree

8 files changed

+3682
-940
lines changed

8 files changed

+3682
-940
lines changed

.eslintrc

-19
This file was deleted.

.github/workflows/nodejs.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ jobs:
2323
uses: actions/setup-node@v4
2424
with:
2525
node-version: ${{ matrix.node-version }}
26-
- run: npm install
26+
- run: npm ci
2727
- run: npm test
2828
env:
2929
CI: true

build.config.ts

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import { defineBuildConfig } from 'unbuild'
2+
3+
export default defineBuildConfig({
4+
rollup: {
5+
emitCJS: true,
6+
},
7+
rootDir: './lib',
8+
outDir: '../dist',
9+
entries: ['index.js'],
10+
})

dist/index.cjs

+91
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
'use strict';
2+
3+
const defaultParseRules = {
4+
class: {
5+
delimiter: /\s+/,
6+
glue: " "
7+
},
8+
style: {
9+
delimiter: /\s*;\s*(?![^()]*\))/,
10+
keyDelimiter: /\s*:\s*/,
11+
glue: "; ",
12+
keyGlue: ": "
13+
}
14+
};
15+
16+
function parseAttr(attrStr, rule) {
17+
rule = rule || {};
18+
const delimiter = rule.delimiter;
19+
const keyDelimiter = rule.keyDelimiter;
20+
if (!delimiter && !keyDelimiter) {
21+
return attrStr;
22+
}
23+
const attrValues = delimiter ? String(attrStr).split(delimiter) : [attrStr];
24+
if (!keyDelimiter) {
25+
return attrValues;
26+
}
27+
const attrDict = {};
28+
attrValues.forEach((attrKeyValue) => {
29+
const match = attrKeyValue.match(keyDelimiter);
30+
if (!match) {
31+
return;
32+
}
33+
const attrKey = attrKeyValue.slice(0, match.index);
34+
if (!attrKey) {
35+
return;
36+
}
37+
const attrValue = attrKeyValue.slice(match.index + match[0].length) || "";
38+
let attrCombinedValue = attrDict[attrKey];
39+
if (attrCombinedValue) {
40+
if (!Array.isArray(attrCombinedValue)) {
41+
attrCombinedValue = [attrCombinedValue];
42+
}
43+
attrCombinedValue.push(attrValue);
44+
} else {
45+
attrCombinedValue = attrValue;
46+
}
47+
attrDict[attrKey] = attrCombinedValue;
48+
});
49+
return attrDict;
50+
}
51+
function stringifyAttr(attr, rule) {
52+
rule = rule || {};
53+
const delimiter = (rule.glue || rule.delimiter || "").toString();
54+
const keyDelimiter = (rule.keyGlue || rule.keyDelimiter || "").toString();
55+
if (typeof attr === "string") {
56+
return attr;
57+
}
58+
if (Array.isArray(attr)) {
59+
return attr.join(delimiter);
60+
}
61+
const attrKeyValues = [];
62+
for (let attrName of Object.keys(attr)) {
63+
let attrCombinedValue = Array.isArray(attr[attrName]) ? attr[attrName] : [attr[attrName]];
64+
attrCombinedValue.forEach((attrValue) => {
65+
attrKeyValues.push(attrName + keyDelimiter + attrValue);
66+
});
67+
}
68+
return attrKeyValues.join(delimiter);
69+
}
70+
71+
function parseAttrs(posthtmlAttrs = {}, options = {}) {
72+
const parseRules = Object.assign({}, defaultParseRules, options.rules || {});
73+
const attrs = {};
74+
for (let attrName of Object.keys(posthtmlAttrs)) {
75+
attrs[attrName] = parseAttr(posthtmlAttrs[attrName], parseRules[attrName]);
76+
}
77+
attrs.compose = function() {
78+
return composeAttrs(this, parseRules);
79+
};
80+
return attrs;
81+
}
82+
function composeAttrs(attrs, parseRules) {
83+
delete attrs.compose;
84+
const posthtmlAttrs = {};
85+
for (let attrName of Object.keys(attrs)) {
86+
posthtmlAttrs[attrName] = stringifyAttr(attrs[attrName], parseRules[attrName]) || true;
87+
}
88+
return posthtmlAttrs;
89+
}
90+
91+
module.exports = parseAttrs;

dist/index.mjs

+89
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
const defaultParseRules = {
2+
class: {
3+
delimiter: /\s+/,
4+
glue: " "
5+
},
6+
style: {
7+
delimiter: /\s*;\s*(?![^()]*\))/,
8+
keyDelimiter: /\s*:\s*/,
9+
glue: "; ",
10+
keyGlue: ": "
11+
}
12+
};
13+
14+
function parseAttr(attrStr, rule) {
15+
rule = rule || {};
16+
const delimiter = rule.delimiter;
17+
const keyDelimiter = rule.keyDelimiter;
18+
if (!delimiter && !keyDelimiter) {
19+
return attrStr;
20+
}
21+
const attrValues = delimiter ? String(attrStr).split(delimiter) : [attrStr];
22+
if (!keyDelimiter) {
23+
return attrValues;
24+
}
25+
const attrDict = {};
26+
attrValues.forEach((attrKeyValue) => {
27+
const match = attrKeyValue.match(keyDelimiter);
28+
if (!match) {
29+
return;
30+
}
31+
const attrKey = attrKeyValue.slice(0, match.index);
32+
if (!attrKey) {
33+
return;
34+
}
35+
const attrValue = attrKeyValue.slice(match.index + match[0].length) || "";
36+
let attrCombinedValue = attrDict[attrKey];
37+
if (attrCombinedValue) {
38+
if (!Array.isArray(attrCombinedValue)) {
39+
attrCombinedValue = [attrCombinedValue];
40+
}
41+
attrCombinedValue.push(attrValue);
42+
} else {
43+
attrCombinedValue = attrValue;
44+
}
45+
attrDict[attrKey] = attrCombinedValue;
46+
});
47+
return attrDict;
48+
}
49+
function stringifyAttr(attr, rule) {
50+
rule = rule || {};
51+
const delimiter = (rule.glue || rule.delimiter || "").toString();
52+
const keyDelimiter = (rule.keyGlue || rule.keyDelimiter || "").toString();
53+
if (typeof attr === "string") {
54+
return attr;
55+
}
56+
if (Array.isArray(attr)) {
57+
return attr.join(delimiter);
58+
}
59+
const attrKeyValues = [];
60+
for (let attrName of Object.keys(attr)) {
61+
let attrCombinedValue = Array.isArray(attr[attrName]) ? attr[attrName] : [attr[attrName]];
62+
attrCombinedValue.forEach((attrValue) => {
63+
attrKeyValues.push(attrName + keyDelimiter + attrValue);
64+
});
65+
}
66+
return attrKeyValues.join(delimiter);
67+
}
68+
69+
function parseAttrs(posthtmlAttrs = {}, options = {}) {
70+
const parseRules = Object.assign({}, defaultParseRules, options.rules || {});
71+
const attrs = {};
72+
for (let attrName of Object.keys(posthtmlAttrs)) {
73+
attrs[attrName] = parseAttr(posthtmlAttrs[attrName], parseRules[attrName]);
74+
}
75+
attrs.compose = function() {
76+
return composeAttrs(this, parseRules);
77+
};
78+
return attrs;
79+
}
80+
function composeAttrs(attrs, parseRules) {
81+
delete attrs.compose;
82+
const posthtmlAttrs = {};
83+
for (let attrName of Object.keys(attrs)) {
84+
posthtmlAttrs[attrName] = stringifyAttr(attrs[attrName], parseRules[attrName]) || true;
85+
}
86+
return posthtmlAttrs;
87+
}
88+
89+
export { parseAttrs as default };

eslint.config.js

+28
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import js from '@eslint/js';
2+
import stylistic from '@stylistic/eslint-plugin';
3+
4+
export default [
5+
js.configs.recommended,
6+
{
7+
plugins: {
8+
'@stylistic': stylistic
9+
},
10+
languageOptions: {
11+
sourceType: 'module',
12+
ecmaVersion: 2020,
13+
globals: {
14+
es6: true,
15+
node: true,
16+
browser: false
17+
}
18+
},
19+
rules: {
20+
semi: [2, 'always'],
21+
quotes: [2, 'single'],
22+
indent: [2, 2, {SwitchCase: 1}],
23+
camelcase: [2, {properties: 'always'}],
24+
'@stylistic/linebreak-style': [2, 'unix'],
25+
'@stylistic/brace-style': [2, '1tbs', {allowSingleLine: true}],
26+
}
27+
}
28+
]

0 commit comments

Comments
 (0)