Skip to content

Commit

Permalink
Fix alpinejs friendly attrs (#30)
Browse files Browse the repository at this point in the history
* switch to node-html-parser fork

* fixes #27

* add note on local packaging

* 0.8.0
  • Loading branch information
callmephilip authored Nov 8, 2024
1 parent 1360f09 commit 3c0539d
Show file tree
Hide file tree
Showing 6 changed files with 222 additions and 123 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,3 +29,8 @@ All notable changes to the "html2ft" extension will be documented in this file.
## 0.7.0

- Improve code formatting

## 0.8.0

- Correctly parse alpinejs attrs like `x-transition.opacity.duration.600ms`
- Group kw args into 1 dictionary `Div(**{'x-transition.opacity.duration.600ms': True}, **{'x-transition.scale.origin.top': True})` becomes `Div(**{'x-transition.opacity.duration.600ms': True, 'x-transition.scale.origin.top': True})`
7 changes: 7 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,14 @@ Improve SVG handling

Improve code formatting

## 0.8.0

- Correctly parse alpinejs attrs like `x-transition.opacity.duration.600ms`
- Group kw args into 1 dictionary `Div(**{'x-transition.opacity.duration.600ms': True}, **{'x-transition.scale.origin.top': True})` becomes `Div(**{'x-transition.opacity.duration.600ms': True, 'x-transition.scale.origin.top': True})`


## Release flow

- local build (for testing): `npm upgrade && pnpm vsce package`
- create a tag (e.g. `git tag 0.6.2`)
- `git push origin --tags`
4 changes: 2 additions & 2 deletions packages/vscode-html2ft/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"name": "html2ft",
"displayName": "html2ft",
"description": "Convert HTML to FastHTML FT",
"version": "0.7.9",
"version": "0.8.0",
"publisher": "PhilipNuzhnyi",
"repository": "https://github.com/callmephilip/html2ft",
"license": "MIT",
Expand Down Expand Up @@ -68,6 +68,6 @@
"webpack-cli": "^5.1.4"
},
"dependencies": {
"node-html-parser": "^6.1.13"
"node-html-parser": "github:callmephilip/node-html-parser#handle-attrs-with-dots"
}
}
39 changes: 29 additions & 10 deletions packages/vscode-html2ft/src/converter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,8 +65,10 @@ export function html2ft(html: string, attr1st: boolean = false): string {
a === "class" ? 1 : b === "class" ? -1 : 0
);

const kws: { [key: string]: string } = {};

for (const key of elmAttrs) {
const value = el.getAttribute(key);
let value = el.getAttribute(key);

if (typeof value === "undefined") {
continue;
Expand All @@ -78,20 +80,37 @@ export function html2ft(html: string, attr1st: boolean = false): string {
// clean up value by removing extra spaces and newlines
const cleanedValue = value.trim().replace(/\s+/g, " ");

const serializeValue = (v: string) => {
if (v === "True" || v === "False") {
return v;
}
return JSON.stringify(cleanedValue).replaceAll('"', "'");
};

if (/^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(formattedKey)) {
attrs.push(
`${formattedKey}=${JSON.stringify(cleanedValue).replaceAll('"', "'")}`
);
// "standard" looking attributes just get pushed in as key=value
attrs.push(`${formattedKey}=${serializeValue(cleanedValue)}`);
} else {
attrs.push(
`**{${JSON.stringify(key)}: ${JSON.stringify(cleanedValue).replaceAll(
'"',
"'"
)}}`
);
// for anything wild looking (i.e. "x-transition.opacity.duration.600ms"), let's get them all together in a dictionary
// and then include them via **{...} python dictionary spread
kws[key] = serializeValue(cleanedValue !== "" ? cleanedValue : "True");
}
}

if (Object.keys(kws).length) {
// got kws? throw them in to attrs all in one go
attrs.push(
`**{${Object.keys(kws)
.reduce(
(acc, key) =>
acc +
`, ${JSON.stringify(key).replaceAll('"', "'")}: ${kws[key]}`,
""
)
.replace(/^,\s/, "")}}`
);
}

const spc = " ".repeat(lvl * indent);
const onlychild =
!cts.length || (cts.length === 1 && cts[0].nodeType === 3); // text node (nodeType === 3)
Expand Down
64 changes: 64 additions & 0 deletions packages/vscode-html2ft/tests/converter.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,70 @@ Script(src='https://cdn.jsdelivr.net/npm/[email protected]/dist/js/uikit-icons.min.js
Script(type='module', src='https://unpkg.com/[email protected]/dist/js/wc.iife.js')
Link(rel='stylesheet', href='https://unpkg.com/[email protected]/dist/css/blue.min.css')`,
},
{
description: "funky alpinejs attributes",
input:
"<div x-transition.opacity.duration.600ms x-transition.scale.origin.top><p>hello</p></div>",
expected: `Div(
P("hello"),
**{'x-transition.opacity.duration.600ms': True, 'x-transition.scale.origin.top': True}
)`,
},
{
description: "funky alpinejs attributes, attrs first",
input:
"<div x-transition.opacity.duration.600ms x-transition.scale.origin.top><p>hello</p></div>",
attr1st: true,
expected: `Div(**{'x-transition.opacity.duration.600ms': True, 'x-transition.scale.origin.top': True})(
P("hello")
)`,
},
{
description: "moar aplinejs",
input: `<div x-data="{ open: false }">
<button @click="open = ! open">Toggle</button>
<div
x-show="open"
x-transition:enter="transition ease-out duration-300"
x-transition:enter-start="opacity-0 scale-90"
x-transition:enter-end="opacity-100 scale-100"
x-transition:leave="transition ease-in duration-300"
x-transition:leave-start="opacity-100 scale-100"
x-transition:leave-end="opacity-0 scale-90"
>Hello 👋</div>
</div>`,
expected: `Div(
Button("Toggle", **{'@click': 'open = ! open'}),
Div("Hello 👋", x_show='open', **{'x-transition:enter': 'transition ease-out duration-300', 'x-transition:enter-start': 'opacity-0 scale-90', 'x-transition:enter-end': 'opacity-100 scale-100', 'x-transition:leave': 'transition ease-in duration-300', 'x-transition:leave-start': 'opacity-100 scale-100', 'x-transition:leave-end': 'opacity-0 scale-90'}),
x_data='{ open: false }'
)`,
},
{
description: "moar aplinejs attr1st",
input: `<div x-data="{ open: false }">
<button @click="open = ! open"><span>Toggle</span></button>
<div
x-show="open"
x-transition:enter="transition ease-out duration-300"
x-transition:enter-start="opacity-0 scale-90"
x-transition:enter-end="opacity-100 scale-100"
x-transition:leave="transition ease-in duration-300"
x-transition:leave-start="opacity-100 scale-100"
x-transition:leave-end="opacity-0 scale-90"
><span>Hello 👋</span></div>
</div>`,
attr1st: true,
expected: `Div(x_data='{ open: false }')(
Button(**{'@click': 'open = ! open'})(
Span("Toggle")
),
Div(x_show='open', **{'x-transition:enter': 'transition ease-out duration-300', 'x-transition:enter-start': 'opacity-0 scale-90', 'x-transition:enter-end': 'opacity-100 scale-100', 'x-transition:leave': 'transition ease-in duration-300', 'x-transition:leave-start': 'opacity-100 scale-100', 'x-transition:leave-end': 'opacity-0 scale-90'})(
Span("Hello 👋")
)
)`,
},
];

describe("html2ft", () => {
Expand Down
Loading

0 comments on commit 3c0539d

Please sign in to comment.