Skip to content

Commit f65cb10

Browse files
committed
Compatibility replacement logic
- added logic to replace certain, opt-in tags in component names and strings for compatiblity reasons (mjx-container) - switched to tsup
1 parent 28dc1f8 commit f65cb10

6 files changed

Lines changed: 180 additions & 49 deletions

File tree

CHANGELOG.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,14 @@
11
# Changelog
22

3+
### 0.5.0
4+
5+
- added compatibility replacement logic for elements that use Web component syntax, opt-in
6+
- updated build process, removed rollup, and switched to tsup
7+
8+
### 0.4.0
9+
10+
- added replacement logic for camel cased properties
11+
312
### 0.3.2
413

514
- switched to ts from tsx for jsx-runtime

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "solid-jsx",
3-
"version": "0.4.0",
3+
"version": "0.5.0",
44
"description": "",
55
"source": "src/jsx-runtime.ts",
66
"main": "./dist/jsx-runtime.js",
@@ -57,7 +57,7 @@
5757
"eslint-plugin-prettier": "^4.0.0",
5858
"eslint-plugin-unicorn": "^40.1.0",
5959
"husky": "^7.0.4",
60-
"lint-staged": "^12.2.0",
60+
"lint-staged": "^12.2.1",
6161
"prettier": "^2.5.1",
6262
"rimraf": "^3.0.2",
6363
"tsup": "^5.11.11",

pnpm-lock.yaml

Lines changed: 7 additions & 7 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/elements.ts

Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
// Attributes that need to be renamed
2+
export const MAPPED_ATTRIBUTES = new Map<string, string>([
3+
['className', 'class'],
4+
['htmlFor', 'for'],
5+
['glyphName', 'glyph-name'],
6+
['glyphOrientationHorizontal', 'glyph-orientation-horizontal'],
7+
['glyphOrientationVertical', 'glyph-orientation-vertical'],
8+
['markerEnd', 'marker-end'],
9+
['markerMid', 'marker-mid'],
10+
['markerStart', 'marker-start'],
11+
['textAnchor', 'text-anchor'],
12+
['textDecoration', 'text-decoration'],
13+
['textRendering', 'text-rendering'],
14+
]);
15+
16+
const REPLACED_COMPAT_SET = new Set(['mjx-container']);
17+
export const REPLACED_COMPAT = new Map<string, string>(
18+
[...REPLACED_COMPAT_SET].map((key) => [key, key.replace(/-/g, '_')])
19+
);
20+
21+
// Attributes that need to be converted to lowercase
22+
export const LOWERCASE_ATTRIBUTES = new Map<string, string>(
23+
[
24+
'autoComplete',
25+
'autoFocus',
26+
'allowFullScreen',
27+
'contentEditable',
28+
'formNoValidate',
29+
'isMap',
30+
'noModule',
31+
'noValidate',
32+
'playsInline',
33+
'readOnly',
34+
'tabIndex',
35+
].map((attribute) => [attribute, attribute.toLowerCase()])
36+
);
37+
38+
export const CSS_PROPERTIES = new Set([
39+
'accent',
40+
'align',
41+
'animation',
42+
'aspect',
43+
'backdrop',
44+
'backface',
45+
'background',
46+
'block',
47+
'border',
48+
'box',
49+
'break',
50+
'caption',
51+
'caret',
52+
'clip',
53+
'column',
54+
'content',
55+
'counter',
56+
'empty',
57+
'flex',
58+
'font',
59+
'forced',
60+
'grid',
61+
'hanging',
62+
'image',
63+
'initial',
64+
'inline',
65+
'inset',
66+
'justify',
67+
'letter',
68+
'line',
69+
'list',
70+
'margin',
71+
'mask',
72+
'max',
73+
'mix',
74+
'object',
75+
'offset',
76+
'outline',
77+
'overflow',
78+
'overscroll',
79+
'padding',
80+
'page',
81+
'place',
82+
'pointer',
83+
'row',
84+
'ruby',
85+
'scroll',
86+
'scrollbar',
87+
'shape',
88+
'tab',
89+
'table',
90+
'text',
91+
'touch',
92+
'transform',
93+
'unicode',
94+
'user',
95+
'vertical',
96+
'white',
97+
'will',
98+
'word',
99+
'writing',
100+
'z',
101+
]);
102+
103+
export const SVG_ATTRIBUTES = new Set([
104+
'accent',
105+
'arabic',
106+
'baseline',
107+
'cap',
108+
'clip',
109+
'color',
110+
'dominant',
111+
'enable',
112+
'fill',
113+
'flood',
114+
'font',
115+
'horiz',
116+
'image',
117+
'letter',
118+
'lightning',
119+
'mask',
120+
'overline',
121+
'paint',
122+
'pointer',
123+
'rendering',
124+
'shape',
125+
'stop',
126+
'strikethrough',
127+
'stroke',
128+
'transform',
129+
'underline',
130+
'v',
131+
'vector',
132+
'vert',
133+
'x',
134+
]);

src/jsx-runtime.ts

Lines changed: 27 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,12 @@
11
import { createComponent, JSX, mergeProps, PropsWithChildren } from 'solid-js';
22
import { Dynamic } from 'solid-js/web';
3+
import {
4+
CSS_PROPERTIES,
5+
LOWERCASE_ATTRIBUTES,
6+
MAPPED_ATTRIBUTES,
7+
REPLACED_COMPAT,
8+
SVG_ATTRIBUTES,
9+
} from 'elements';
310

411
export const Fragment = (properties: PropsWithChildren): JSX.Element => properties.children;
512

@@ -11,6 +18,11 @@ const getProperties = (
1118
properties_[jsxKeyToSolid(key)] =
1219
typeof properties[key] === 'object' && !Array.isArray(properties[key])
1320
? getProperties(properties[key] as Record<string, unknown>)
21+
: typeof properties[key] === 'string'
22+
? (properties[key] as string).replace(
23+
new RegExp([...REPLACED_COMPAT.keys()].join('|'), 'g'),
24+
(match: string) => REPLACED_COMPAT.get(match) ?? match
25+
)
1426
: properties[key];
1527
return properties_;
1628
};
@@ -23,7 +35,10 @@ export const jsx = (
2335
? type.name === 'Fragment'
2436
? Fragment(properties)
2537
: type(getProperties(properties))
26-
: createComponent(Dynamic, mergeProps(getProperties(properties), { component: type }));
38+
: createComponent(
39+
Dynamic,
40+
mergeProps(getProperties(properties), { component: REPLACED_COMPAT.get(type) ?? type })
41+
);
2742

2843
// For the moment we do not distinguish static children from dynamic ones
2944
export const jsxs = jsx;
@@ -32,50 +47,23 @@ export const jsxs = jsx;
3247
// function jsxDEV(type, props , maybeKey, isStaticChildren, source, self)
3348
export const jsxDEV = jsx;
3449

35-
// Attributes that need to be renamed
36-
const MAPPED_ATTRIBUTES = new Map<string, string>([
37-
['className', 'class'],
38-
['htmlFor', 'for'],
39-
['glyphName', 'glyph-name'],
40-
['glyphOrientationHorizontal', 'glyph-orientation-horizontal'],
41-
['glyphOrientationVertical', 'glyph-orientation-vertical'],
42-
// ['horizAdvX', 'horiz-adv-x'],
43-
// ['horizOriginX', 'horiz-origin-x'],
44-
['markerEnd', 'marker-end'],
45-
['markerMid', 'marker-mid'],
46-
['markerStart', 'marker-start'],
47-
['textAnchor', 'text-anchor'],
48-
['textDecoration', 'text-decoration'],
49-
['textRendering', 'text-rendering'],
50-
]);
51-
52-
// Attributes that need to be converted to lowercase
53-
const LOWERCASE_ATTRIBUTES = new Map<string, string>(
54-
[
55-
'autoComplete',
56-
'autoFocus',
57-
'allowFullScreen',
58-
'contentEditable',
59-
'formNoValidate',
60-
'isMap',
61-
'noModule',
62-
'noValidate',
63-
'playsInline',
64-
'readOnly',
65-
'tabIndex',
66-
].map((attribute) => [attribute, attribute.toLowerCase()])
67-
);
68-
6950
const jsxKeyToSolid = (key: string): string =>
7051
MAPPED_ATTRIBUTES.get(key) ??
7152
LOWERCASE_ATTRIBUTES.get(key) ??
7253
key
7354
.replace(
74-
/^(xmlns|xlink|xml)([A-Z][a-z]+)/,
55+
/^(xml(?:ns)?|xlink)([A-Z][a-z]+)/,
7556
(_, p1: string, p2: string) => `${p1}:${p2.toLowerCase()}`
7657
)
7758
.replace(
78-
/^(accent|arabic|baseline|cap|clip|color|dominant|enable|fill|flood|font|image|letter|lightning|overline|paint|pointer|rendering|shape|stop|strikethrough|stroke|transform|underline|unicode|v|vector|vert|vertical|word|writing|x|)([A-Z][a-z]+?)([A-Z][a-z]+?)?/,
79-
(_, p1: string, p2: string, p3: string | undefined) =>
80-
`${p1}-${p2.toLowerCase()}${p3 ? `-${p3}` : ''}`
59+
new RegExp(
60+
`^(${[...CSS_PROPERTIES, ...SVG_ATTRIBUTES].join(
61+
'|'
62+
)})([A-Z][a-z]+)([A-Z][a-z]+)?([A-Z][a-z]+)?`
63+
),
64+
(_, p1: string, p2: string, p3?: string, p4?: string) =>
65+
[p1, p2, p3, p4]
66+
.filter(Boolean)
67+
.map((value) => value?.toLowerCase())
68+
.join('-')
8169
);

tsconfig.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@
2727
"module": "commonjs" /* Specify what module code is generated. */,
2828
"rootDir": "./src" /* Specify the root folder within your source files. */,
2929
// "moduleResolution": "node", /* Specify how TypeScript looks up a file from a given module specifier. */
30-
// "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */
30+
"baseUrl": "./src" /* Specify the base directory to resolve non-relative module names. */,
3131
// "paths": {}, /* Specify a set of entries that re-map imports to additional lookup locations. */
3232
// "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */
3333
// "typeRoots": [], /* Specify multiple folders that act like `./node_modules/@types`. */

0 commit comments

Comments
 (0)