diff --git a/packages/abell/src/type-utils.ts b/packages/abell/src/type-utils.ts index c72df57..55a6221 100644 --- a/packages/abell/src/type-utils.ts +++ b/packages/abell/src/type-utils.ts @@ -65,6 +65,13 @@ export type AbellOptions = { * E.g. if you want to use top-level await in entry.build.ts, you can set target here without having to change target of your final client bundle */ serverBuild?: ViteUserConfig['build']; + + /** + * Allows `.abell` files to be imported in client-side code. + * + * Abell variables like `Abell.root`, `__dirname`, `__filename` etc return empty string when this flag is set + */ + experimentalAllowClientSide?: boolean; }; export interface AbellViteConfig extends ViteUserConfig { diff --git a/packages/abell/src/vite-plugin-abell/compiler/compiler.spec.ts b/packages/abell/src/vite-plugin-abell/compiler/compiler.spec.ts index 800376b..5a117d4 100644 --- a/packages/abell/src/vite-plugin-abell/compiler/compiler.spec.ts +++ b/packages/abell/src/vite-plugin-abell/compiler/compiler.spec.ts @@ -36,11 +36,12 @@ describe('compile()', () => { }); expect(js.trim().replace(`\\\\test.abell`, '/test.abell')) .toMatchInlineSnapshot(` - "import { evaluateAbellBlock as e } from 'abell/dist/utils/evaluateAbellBlock'; + "import { default as _path } from 'path'; + import { evaluateAbellBlock as e } from 'abell/dist/utils/evaluateAbellBlock'; const __filename = \\"/test.abell\\"; - const __dirname = \\"/\\"; - const root = \\"\\" + const __dirname = _path.dirname(__filename); + const root = _path.relative(__dirname, \\"/\\"); export const html = (props = {}) => { const Abell = { props, __filename, __dirname }; @@ -93,13 +94,14 @@ describe('compile()', () => { }); expect(js.trim().replace(`\\\\test.abell`, '/test.abell')) .toMatchInlineSnapshot(` - "import { evaluateAbellBlock as e } from 'abell/dist/utils/evaluateAbellBlock'; + "import { default as _path } from 'path'; + import { evaluateAbellBlock as e } from 'abell/dist/utils/evaluateAbellBlock'; import x from './x'; const __filename = \\"/test.abell\\"; - const __dirname = \\"/\\"; - const root = \\"\\" + const __dirname = _path.dirname(__filename); + const root = _path.relative(__dirname, \\"/\\"); export const html = (props = {}) => { const Abell = { props, __filename, __dirname }; diff --git a/packages/abell/src/vite-plugin-abell/compiler/compiler.ts b/packages/abell/src/vite-plugin-abell/compiler/compiler.ts index 9188ed3..caed5d6 100644 --- a/packages/abell/src/vite-plugin-abell/compiler/compiler.ts +++ b/packages/abell/src/vite-plugin-abell/compiler/compiler.ts @@ -19,6 +19,7 @@ interface CompileOptions { filepath: string; cwd?: string; outputType?: 'js-string' | 'syntax-blocks'; + isClientSide?: boolean; } interface HTMLOutputCompileOptions extends CompileOptions { @@ -77,15 +78,21 @@ export function compile( }; } - const __filename = options.filepath; - const __dirname = path.dirname(options.filepath); - const jsOut = ` + ${options.isClientSide ? '' : `import { default as _path } from 'path';`} import { evaluateAbellBlock as e } from 'abell/dist/utils/evaluateAbellBlock'; ${importBlock.text} - const __filename = ${JSON.stringify(__filename)}; - const __dirname = ${JSON.stringify(__dirname)}; - const root = ${JSON.stringify(path.relative(__dirname, options.cwd ?? ''))} + const __filename = ${ + options.isClientSide ? '"";' : JSON.stringify(options.filepath) + }; + const __dirname = ${ + options.isClientSide ? '"";' : '_path.dirname(__filename);' + } + const root = ${ + options.isClientSide + ? '"";' + : `_path.relative(__dirname, ${JSON.stringify(options.cwd)});` + } export const html = (props = {}) => { const Abell = { props, __filename, __dirname }; ${declarationBlocks.text} diff --git a/packages/abell/src/vite-plugin-abell/vite-plugin-abell.ts b/packages/abell/src/vite-plugin-abell/vite-plugin-abell.ts index ca0aa71..e004c97 100644 --- a/packages/abell/src/vite-plugin-abell/vite-plugin-abell.ts +++ b/packages/abell/src/vite-plugin-abell/vite-plugin-abell.ts @@ -29,7 +29,8 @@ export function vitePluginAbell(abellOptions?: AbellOptions): PluginOption { if (id.endsWith('.abell')) { const jsCode = compile(src, { filepath: id, - cwd: process.cwd() + cwd: process.cwd(), + isClientSide: abellOptions?.experimentalAllowClientSide ?? false }); let outCode = jsCode; // If loader is not defined, skip the esbuild transform