From 45bff6fccb3f5c71ff24c1ceb48cd532196c90f6 Mon Sep 17 00:00:00 2001 From: Nate Moore Date: Thu, 6 Apr 2023 11:36:28 -0500 Subject: [PATCH] feat(prerender): support quoted true / false values and 0 / 1 (#6772) --- .changeset/cuddly-eels-melt.md | 5 ++++ .../astro/src/vite-plugin-scanner/scan.ts | 23 ++++++++++++-- .../units/vite-plugin-scanner/scan.test.js | 30 +++++++++++++++++++ 3 files changed, 56 insertions(+), 2 deletions(-) create mode 100644 .changeset/cuddly-eels-melt.md diff --git a/.changeset/cuddly-eels-melt.md b/.changeset/cuddly-eels-melt.md new file mode 100644 index 000000000..90f80f28d --- /dev/null +++ b/.changeset/cuddly-eels-melt.md @@ -0,0 +1,5 @@ +--- +'astro': patch +--- + +Allow `import.meta.env` values of `0`, `1`, `true`, and `false` to be used for `export const prerender` statements diff --git a/packages/astro/src/vite-plugin-scanner/scan.ts b/packages/astro/src/vite-plugin-scanner/scan.ts index bb6efe9f5..4af20e303 100644 --- a/packages/astro/src/vite-plugin-scanner/scan.ts +++ b/packages/astro/src/vite-plugin-scanner/scan.ts @@ -13,6 +13,25 @@ function includesExport(code: string) { return false; } +// Support quoted values to allow statically known `import.meta.env` variables to be used +function isQuoted(value: string) { + return (value[0] === '"' || value[0] === "'") && value[value.length - 1] === value[0] +} + +function isTruthy(value: string) { + if (isQuoted(value)) { + value = value.slice(1, -1); + } + return value === 'true' || value === '1'; +} + +function isFalsy(value: string) { + if (isQuoted(value)) { + value = value.slice(1, -1); + } + return value === 'false' || value === '0'; +} + let didInit = false; export async function scan(code: string, id: string): Promise { @@ -39,14 +58,14 @@ export async function scan(code: string, id: string): Promise { // For a given export, check the value of the first non-whitespace token. // Basically extract the `true` from the statement `export const prerender = true` const suffix = code.slice(endOfLocalName).trim().replace(/\=/, '').trim().split(/[;\n]/)[0]; - if (prefix !== 'const' || !(suffix === 'true' || suffix === 'false')) { + if (prefix !== 'const' || !(isTruthy(suffix) || isFalsy(suffix))) { throw new AstroError({ ...AstroErrorData.InvalidPrerenderExport, message: AstroErrorData.InvalidPrerenderExport.message(prefix, suffix), location: { file: id }, }); } else { - pageOptions[name as keyof PageOptions] = suffix === 'true'; + pageOptions[name as keyof PageOptions] = isTruthy(suffix); } } } diff --git a/packages/astro/test/units/vite-plugin-scanner/scan.test.js b/packages/astro/test/units/vite-plugin-scanner/scan.test.js index 8bd1f0857..373a5822b 100644 --- a/packages/astro/test/units/vite-plugin-scanner/scan.test.js +++ b/packages/astro/test/units/vite-plugin-scanner/scan.test.js @@ -17,6 +17,36 @@ describe('astro scan', () => { expect(result.prerender).to.equal(false); }); + it('recognizes single quoted boolean (\'true\')', async () => { + const result = await scan(`export const prerender = 'true';`, '/src/components/index.astro'); + expect(result.prerender).to.equal(true); + }); + + it('recognizes double quoted boolean ("true")', async () => { + const result = await scan(`export const prerender = "true";`, '/src/components/index.astro'); + expect(result.prerender).to.equal(true); + }); + + it('recognizes double quoted boolean ("false")', async () => { + const result = await scan(`export const prerender = "false";`, '/src/components/index.astro'); + expect(result.prerender).to.equal(false); + }); + + it('recognizes single quoted boolean (\'false\')', async () => { + const result = await scan(`export const prerender = 'false';`, '/src/components/index.astro'); + expect(result.prerender).to.equal(false); + }); + + it('recognizes number (1)', async () => { + const result = await scan(`export const prerender = 1;`, '/src/components/index.astro'); + expect(result.prerender).to.equal(true); + }); + + it('recognizes number (0)', async () => { + const result = await scan(`export const prerender = 0;`, '/src/components/index.astro'); + expect(result.prerender).to.equal(false); + }); + it('throws on let boolean literal', async () => { try { const result = await scan(`export let prerender = true;`, '/src/components/index.astro');