Skip to content

Commit

Permalink
WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
sahinvardar committed Dec 13, 2024
1 parent 2c55956 commit 0304145
Show file tree
Hide file tree
Showing 6 changed files with 189 additions and 144 deletions.
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,8 @@
"@types/node": "^20.2.5",
"@typescript-eslint/eslint-plugin": "^6.11.0",
"@typescript-eslint/parser": "^6.11.0",
"astring": "^1.8.5",
"@vardario/astring-ts-generator": "^1.1.0",
"astring": "^1.9.0",
"eslint": "^8.54.0",
"eslint-config-prettier": "^9.0.0",
"eslint-plugin-unused-imports": "^3.0.0",
Expand Down
22 changes: 17 additions & 5 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

133 changes: 3 additions & 130 deletions src/print-html.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,49 +3,9 @@ import _ from 'lodash';
import { walk } from 'estree-walker';
import { AST } from 'svelte/compiler';
import { DefaultPrinterIdentOptions, PrinterIdentOptions } from './index.js';
import { Node } from 'estree';
export type Write = (text: string) => void;
import { ElementLike, printAttributes, SvelteNode } from './utils.js';

type ElementLike =
| AST.Component
| AST.TitleElement
| AST.SlotElement
| AST.RegularElement
| AST.SvelteBody
| AST.SvelteComponent
| AST.SvelteDocument
| AST.SvelteElement
| AST.SvelteFragment
| AST.SvelteHead
| AST.SvelteOptionsRaw
| AST.SvelteSelf
| AST.SvelteWindow;

type Directive =
| AST.AnimateDirective
| AST.BindDirective
| AST.ClassDirective
| AST.LetDirective
| AST.OnDirective
| AST.StyleDirective
| AST.TransitionDirective
| AST.UseDirective;

type Tag = AST.ExpressionTag | AST.HtmlTag | AST.ConstTag | AST.DebugTag | AST.RenderTag;
type Block = AST.EachBlock | AST.IfBlock | AST.AwaitBlock | AST.KeyBlock | AST.SnippetBlock;

type TemplateNode =
| AST.Root
| AST.Text
| Tag
| ElementLike
| AST.Attribute
| AST.SpreadAttribute
| Directive
| AST.Comment
| Block;

type SvelteNode = Node | TemplateNode | AST.Fragment | any;
export type Write = (text: string) => void;

const HTML_VOID_ELEMENTS = new Set([
'area',
Expand Down Expand Up @@ -97,93 +57,6 @@ class ExpressionTagPrinter extends BaseHtmlNodePrinter {
}

class ElementPrinter extends BaseHtmlNodePrinter {
private printAttributes(attribute: AST.Attribute | AST.SpreadAttribute | Directive, context: PrinterContext) {
const { write } = context;

if (attribute.type === 'Attribute') {
if (attribute.value === true) {
return;
}

if (_.isArray(attribute.value)) {
const [value] = attribute.value;

if (value.type === 'Text') {
write(` ${attribute.name}="${value.data}"`);
}

if (value.type === 'ExpressionTag') {
write(` ${attribute.name}={${generate(value.expression, context.indent)}}`);
}
} else {
write(` ${attribute.name}={${generate(attribute.value.expression, context.indent)}}`);
}
} else if (attribute.type === 'SpreadAttribute') {
write(` {...${generate(attribute.expression, context.indent)}}`);
} else if (attribute.type === 'AnimateDirective') {
if (attribute.expression) {
write(` animate:${attribute.name}={${generate(attribute.expression, context.indent)}}`);
} else {
write(` animate:${attribute.name}`);
}
} else if (attribute.type === 'BindDirective') {
write(` bind:${attribute.name}={${generate(attribute.expression, context.indent)}}`);
} else if (attribute.type === 'ClassDirective') {
write(` class:${attribute.name}={${generate(attribute.expression, context.indent)}}`);
} else if (attribute.type === 'LetDirective') {
if (attribute.expression) {
write(` let:${attribute.name}={${generate(attribute.expression, context.indent)}}`);
} else {
write(` let:${attribute.name}`);
}
} else if (attribute.type === 'OnDirective') {
if (attribute.expression) {
write(` on:${attribute.name}={${generate(attribute.expression, context.indent)}}`);
} else {
write(` on:${attribute.name}`);
}
} else if (attribute.type === 'StyleDirective') {
if (attribute.value === true) {
write(` style:${attribute.name}`);
} else {
if (_.isArray(attribute.value)) {
const [value] = attribute.value;
if (value.type === 'Text') {
write(` style:${attribute.name}="${value.data}"`);
} else {
write(` style:${attribute.name}={${generate(value, context.indent)}}`);
}
} else {
write(` style:${attribute.name}={${generate(attribute.value.expression, context.indent)}}`);
}
}
} else if (attribute.type === 'TransitionDirective') {
const transition = () => {
if (attribute.intro && !attribute.outro) {
return 'in';
}

if (attribute.outro && !attribute.intro) {
return 'out';
}

return 'transition';
};

if (attribute.expression) {
write(` ${transition()}:${attribute.name}={${generate(attribute.expression, context.indent)}}`);
} else {
write(` ${transition()}:${attribute.name}`);
}
} else if (attribute.type === 'UseDirective') {
if (attribute.expression) {
write(` use:${attribute.name}={${generate(attribute.expression, context.indent)}}`);
} else {
write(` use:${attribute.name}`);
}
}
}

enter(node: ElementLike, _: SvelteNode, context: PrinterContext) {
const { write } = context;

Expand All @@ -207,7 +80,7 @@ class ElementPrinter extends BaseHtmlNodePrinter {
});
}

node.attributes.forEach(attribute => this.printAttributes(attribute, context));
node.attributes.forEach(attribute => printAttributes(attribute, context));

if (
(node.type === 'Component' ||
Expand Down
15 changes: 9 additions & 6 deletions src/print-script.ts
Original file line number Diff line number Diff line change
@@ -1,23 +1,26 @@
import { generate } from 'astring';
import type { AST } from 'svelte/compiler';
import { DefaultPrinterIdentOptions, PrinterIdentOptions } from './index.js';
import generator from '@vardario/astring-ts-generator';
import { attributeToString } from './utils.js';

export default function printScript(root: AST.Root, indent: PrinterIdentOptions = DefaultPrinterIdentOptions): string {
let result = '';

if (root.instance) {
result += '<script';
if (root.instance.context !== 'default') {
result += ` context="${root.instance.context}"`;
}
result += root.instance.attributes.map(attributeToString).join(' ');
result += '>';
result += generate(root.instance.content, indent);
result += generate(root.instance.content, { ...indent, generator });
result += '</script>';
}

if (root.module) {
result += '<script context="module">';
result += generate(root.module.content, indent);
result += '<script';
result += root.module.attributes.map(attributeToString).join(' ');
result += '>';

result += generate(root.module.content, { ...indent, generator });
result += '</script>';
}

Expand Down
8 changes: 6 additions & 2 deletions src/tests/print-script.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@ import { describe, expect, test } from 'vitest';
import printScript from '../print-script';

function testScriptPrinter(code: string, expectedResult?: string) {
const root = parse(code);
const root = parse(code, { modern: true });
const result = printScript(root, {
indent: '',
lineEnd: ''
});
expect(result, expectedResult ?? code);
expect(result).toBe(expectedResult ?? code);
}

describe('<script>', () => {
Expand All @@ -23,4 +23,8 @@ describe('<script>', () => {
test('instance && module', () => {
testScriptPrinter('<script>let a;</script><script context="module">let a;</script>');
});

test('typescript instance', () => {
testScriptPrinter('<script lang="ts">interface A {}const a: number = 0;</script>');
});
});
Loading

0 comments on commit 0304145

Please sign in to comment.