Skip to content

Commit

Permalink
feat: get declaration and imports mapping to work
Browse files Browse the repository at this point in the history
  • Loading branch information
saurabhdaware committed Mar 3, 2024
1 parent 4a89828 commit a16e806
Show file tree
Hide file tree
Showing 10 changed files with 212 additions and 59 deletions.
2 changes: 2 additions & 0 deletions packages/abell/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
"dependencies": {
"@jridgewell/sourcemap-codec": "^1.4.15",
"commander": "^7.2.0",
"dedent": "^0.7.0",
"express": "^4.17.2",
"node-match-path": "^0.6.3",
"postcss-selector-parser": "^6.0.10",
Expand All @@ -52,6 +53,7 @@
"vite": "4.4.9"
},
"devDependencies": {
"@types/dedent": "^0.7.0",
"@types/express": "^4.17.13",
"@types/stylis": "^4.0.2"
}
Expand Down
8 changes: 8 additions & 0 deletions packages/abell/src/type-utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,13 @@ export type Route = {
};
};

export type SourceMapObject = { pos?: number; col?: number; line?: number };
export type MapsObject = {
importTextMap: SourceMapObject[];
declarationTextMap: SourceMapObject[];
abellTextMap: SourceMapObject[];
};

export type StyleTagAttributes = Record<string, string | boolean>;
export type CSSBlockType = {
text: string;
Expand All @@ -27,6 +34,7 @@ export type AbstractSyntaxArrayType = {
text: string;
blocks: { text: string }[];
};
maps: MapsObject;
};

export type AbellOptions = {
Expand Down
24 changes: 24 additions & 0 deletions packages/abell/src/utils/__tests__/test-files/generated.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { default as _path } from 'path';
import { evaluateAbellBlock as e } from 'abell';

import x from './x';

const __filename = "/test.abell";
const __dirname = _path.dirname(__filename);
const root = _path.relative(__dirname, "/")
export const html = (props = {}) => {
const Abell = { props, __filename, __dirname };

/** @declarations */
const x = 999;

return `
<b>${e( 3 + 4 )}</b>
<nav>${e( x * 2 )}</nav>
`
};
export default html;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIm9yaWdpbmFsLmFiZWxsIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7O0tBQ0s7O0tBRUE7Ozs7OztPQUdBOzs7T0FHQSIsImZpbGUiOiJnZW5lcmF0ZWQudHMiLCJzb3VyY2VSb290IjoiL1VzZXJzL3NhdXJhYmhkYXdhcmUvRGVza3RvcC9wcm9qZWN0cy9hYmVsbC1vcmcvYWJlbGwtbW9ub3JlcG8vcGFja2FnZXMvYWJlbGwvc3JjL3V0aWxzL19fdGVzdHNfXy90ZXN0LWZpbGVzIiwic291cmNlc0NvbnRlbnQiOlsiXG4gICAge3tcbiAgICAgIGltcG9ydCB4IGZyb20gJy4veCc7XG4gICAgfX1cblxuICAgIDxiPnt7IDMgKyA0IH19PC9iPlxuICAgIHt7XG4gICAgICAvKiogQGRlY2xhcmF0aW9ucyAqL1xuICAgICAgY29uc3QgeCA9IDk5OTtcbiAgICB9fVxuICAgIDxuYXY+e3sgeCAqIDIgfX08L25hdj5cbiAgICAiXX0=
12 changes: 12 additions & 0 deletions packages/abell/src/utils/__tests__/test-files/original.abell
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@

{{
import x from './x';
}}

<b>{{ 3 + 4 }}</b>
{{
/** @declarations */
const x = 999;
}}
<nav>{{ x * 2 }}</nav>

27 changes: 22 additions & 5 deletions packages/abell/src/vite-plugin-abell/compiler/compiler.spec.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
/* eslint-disable max-len */
import fs from 'fs';
import path from 'path';
import { describe, test, expect, vi, beforeAll, afterAll } from 'vitest';
import { compile } from './index';
Expand Down Expand Up @@ -74,7 +75,7 @@ describe('compile()', () => {
`);
});

test('should place declarations and imports at correct places', () => {
test.only('should place declarations and imports at correct places', () => {
const abellCode = `
{{
import x from './x';
Expand All @@ -92,11 +93,27 @@ describe('compile()', () => {
filepath: consistentPathJoin(process.cwd(), 'test.abell'),
cwd: process.cwd()
});
expect(js.trim().replace(`\\\\test.abell`, '/test.abell'))

fs.writeFileSync(
path.resolve(
__dirname,
'../../utils/__tests__/test-files/original.abell'
),
abellCode
);

fs.writeFileSync(
path.resolve(__dirname, '../../utils/__tests__/test-files/generated.ts'),
js.code +
`\n//# sourceMappingURL=data:application/json;base64,` +
Buffer.from(js.map.toString()).toString('base64')
);

expect(js.code.replace(`\\\\test.abell`, '/test.abell'))
.toMatchInlineSnapshot(`
"import { default as _path } from 'path';
"import { default as _path } from 'path';
import { evaluateAbellBlock as e } from 'abell';
import x from './x';
const __filename = \\"/test.abell\\";
Expand All @@ -117,7 +134,7 @@ describe('compile()', () => {
\`
};
export default html;"
`);
`);
});

test('should successfully compile with imports', () => {
Expand Down
137 changes: 101 additions & 36 deletions packages/abell/src/vite-plugin-abell/compiler/compiler.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
/* eslint-disable max-len */
import { AbstractSyntaxArrayType } from '../../type-utils.js';
import path from 'path';
import dedent from 'dedent';
import { SourceMapGenerator } from 'source-map';
import tokenize from './generic-tokenizer.js';
import { getScopedHTML } from './scope-css/index.js';
import { getSyntaxBlocks } from './syntax-blocks.js';
Expand All @@ -20,28 +22,22 @@ interface CompileOptions {
outputType?: 'js-string' | 'syntax-blocks';
}

interface HTMLOutputCompileOptions extends CompileOptions {
outputType: 'syntax-blocks';
}

interface JSOutputCompileOptions extends CompileOptions {
outputType?: 'js-string';
}

type CompileOutputType = string | AbstractSyntaxArrayType;
type CompileOutputType = {
code: string;
map: SourceMapGenerator;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
meta: any;
};

export function compile(
abellTemplate: string,
options: HTMLOutputCompileOptions
): AbstractSyntaxArrayType;
export function compile(
abellTemplate: string,
options: JSOutputCompileOptions
): string;
export function compile(
abellTemplate: string,
options: CompileOptions
): CompileOutputType {
const sourceMap = new SourceMapGenerator({
file: 'generated.ts',
sourceRoot: path.join(__dirname, '../../utils/__tests__/test-files')
});

const tokens = tokenize<TokenSchemaType>(
abellTemplate,
tokenSchema,
Expand All @@ -52,31 +48,96 @@ export function compile(
abellTemplate.includes('<html') && abellTemplate.includes('</html>');
const isAbellComponent = !isHTMLPage;

const { declarationBlocks, importBlock, cssBlocks, out } = getSyntaxBlocks(
tokens,
{
const { declarationBlocks, importBlock, cssBlocks, out, maps } =
getSyntaxBlocks(tokens, {
isPage: isHTMLPage
}
);
});

let htmlOut = out.text;
if (isAbellComponent) {
htmlOut = getScopedHTML(htmlOut, cssBlocks, options.filepath);
}

if (options.outputType === 'syntax-blocks') {
return {
declarationBlocks,
importBlock,
out: {
blocks: out.blocks,
text: htmlOut
},
cssBlocks
};
const IMPORTS_OFFSET = 3;
// const DECLARATIONS_OFFSET = {
// line: 9 +
// }

// const mapss = [];
const importLinesDiff =
maps.importTextMap[maps.importTextMap.length - 1].line! -
maps.importTextMap[0].line!;

const DECLARATIONS_OFFSET = {
line: 9 + importLinesDiff,
col: 2
};

for (const importTextMapIndex in maps.importTextMap) {
const importTextMapObj = maps.importTextMap[importTextMapIndex];
const idx = Number(importTextMapIndex);

if (importTextMapObj.col && importTextMapObj.line) {
sourceMap.addMapping({
generated: {
line:
idx <= 0
? IMPORTS_OFFSET
: IMPORTS_OFFSET +
(maps.importTextMap[idx]?.line ?? 0) -
(maps.importTextMap[idx - 1]?.line ?? 0),
column: importTextMapObj.col
},
source: 'original.abell',
original: {
line: importTextMapObj.line,
column: importTextMapObj.col
}
});
}
}

for (const declarationTextMapIndex in maps.declarationTextMap) {
const declarationTextMapObj =
maps.declarationTextMap[declarationTextMapIndex];
const idx = Number(declarationTextMapIndex);

if (declarationTextMapObj.col && declarationTextMapObj.line) {
sourceMap.addMapping({
generated: {
line:
idx <= 0
? DECLARATIONS_OFFSET.line
: DECLARATIONS_OFFSET.line +
(maps.declarationTextMap[idx]?.line ?? 0) -
(maps.declarationTextMap[idx - 1]?.line ?? 0),
column: DECLARATIONS_OFFSET.col + declarationTextMapObj.col
},
source: 'original.abell',
original: {
line: declarationTextMapObj.line,
column: declarationTextMapObj.col
}
});
}
}

const jsOut = `
// console.log(mapss);

const meta = {
declarationBlocks,
importBlock,
out: {
blocks: out.blocks,
text: htmlOut
},
cssBlocks,
maps
};

sourceMap.setSourceContent('original.abell', abellTemplate);

const jsOut = dedent`
import { default as _path } from 'path';
import { evaluateAbellBlock as e } from 'abell';
${importBlock.text}
Expand All @@ -89,9 +150,13 @@ export function compile(
return \`${htmlOut}\`
};
export default html;
`.trim();
`;

return jsOut;
return {
code: jsOut,
map: sourceMap,
meta
};
}

export default compile;
28 changes: 21 additions & 7 deletions packages/abell/src/vite-plugin-abell/compiler/syntax-blocks.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { isDeclarationBlock, isImportBlock, parseAttributes } from './utils.js';
import { Token } from './generic-tokenizer.js';
import { AbstractSyntaxArrayType } from '../../type-utils.js';
import { AbstractSyntaxArrayType, MapsObject } from '../../type-utils.js';
import { TokenSchemaType } from './token-schema.js';

export const getSyntaxBlocks = (
Expand All @@ -23,11 +23,11 @@ export const getSyntaxBlocks = (
outText: ''
};

// const maps = {
// importTextMap: [],
// declarationTextMap: [],
// abellTextMap: []
// };
const maps: MapsObject = {
importTextMap: [],
declarationTextMap: [],
abellTextMap: []
};

const cssBlocks = [];
const outBlocks: { text: string }[] = [];
Expand Down Expand Up @@ -55,6 +55,9 @@ export const getSyntaxBlocks = (
}
blockState.isInsideAbellBlock = true;
blockState.blockCount++;
maps.abellTextMap = [
{ pos: token.pos, col: token.col, line: token.line }
];
} else if (token.type === 'BLOCK_END') {
/**
* Abell Block End
Expand All @@ -75,8 +78,18 @@ export const getSyntaxBlocks = (

if (isImportBlock(blockState.blockCount, texts.abellText)) {
texts.importText = texts.abellText;
maps.importTextMap = [
...maps.abellTextMap,
{ pos: token.pos, col: token.col, line: token.line }
];
maps.abellTextMap = [];
} else if (isDeclarationBlock(texts.abellText)) {
texts.declarationText = texts.abellText;
maps.declarationTextMap = [
...maps.abellTextMap,
{ pos: token.pos, col: token.col, line: token.line }
];
maps.abellTextMap = [];
} else {
if (blockState.isInsideCSSBlock) {
texts.cssText += `\${e(${texts.abellText})}`;
Expand Down Expand Up @@ -149,6 +162,7 @@ export const getSyntaxBlocks = (
out: {
text: texts.outText,
blocks: outBlocks
}
},
maps
};
};
Loading

0 comments on commit a16e806

Please sign in to comment.