Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

svelte parser uses lang only from first script tag #933

Open
milahu opened this issue Nov 30, 2022 · 0 comments · May be fixed by #934
Open

svelte parser uses lang only from first script tag #933

milahu opened this issue Nov 30, 2022 · 0 comments · May be fixed by #934

Comments

@milahu
Copy link

milahu commented Nov 30, 2022

currently the svelte parser fails to parse typescript
when the first script tag is javascript

<script>
  console.log("hello from javascript")
</script>

<script lang="ts">
  console.log("hello from typescript")
  export let name: string | null;
</script>
CompileError [ParseError]: Unexpected token
    at error (node_modules/svelte/compiler.js:16675:20)
    at Parser$1.error (node_modules/svelte/compiler.js:16753:10)
    at Parser$1.acorn_error (node_modules/svelte/compiler.js:16747:15)
    at Object.read_script [as read] (node_modules/svelte/compiler.js:8799:17)
    at tag (node_modules/svelte/compiler.js:15701:34)
    at new Parser$1 (node_modules/svelte/compiler.js:16712:22)
    at parse$I (node_modules/svelte/compiler.js:16844:21)
    at node_modules/@builder.io/mitosis/dist/src/parsers/svelte/index.js:98:48
    at step (node_modules/@builder.io/mitosis/dist/src/parsers/svelte/index.js:33:23)
    at Object.next (node_modules/@builder.io/mitosis/dist/src/parsers/svelte/index.js:14:53)
    at fulfilled (node_modules/@builder.io/mitosis/dist/src/parsers/svelte/index.js:5:58) {

parsers/svelte/index.js:98: const ast = parse(processedString.code);

processedString.code has unprocessed typescript in <script lang="ts">

export const parseSvelte = async function (
string_: string,
path = 'MyComponent.svelte',
): Promise<MitosisComponent> {
const usesTypescript = isTypeScriptComponent(string_);
const processedString = await preprocess(
string_,
[
preprocessor({
typescript: usesTypescript ? { tsconfigFile: false } : false,
}),
],
{
filename: path.split('/').pop(),
},
);
const ast = parse(processedString.code);
const componentName = path.split('/').pop()?.split('.')[0] ?? 'MyComponent';
return mapAstToMitosisJson(ast, componentName, string_, usesTypescript);
};

blame isTypeScriptComponent

export function isTypeScriptComponent(string_: string) {
const regex = createTagRegex('script', 'gi');
const match = regex.exec(string_);
const { lang } = parseAttributes((match?.length && match[1]) || '');
return lang === 'ts';
}

const match = regex.exec(string_); gets only the first match

fix

mitosis/packages/core/src/parsers/svelte/typescript/index.ts
function isTypeScriptComponent(string_) {
  const regex = createTagRegex('script', 'gi');
// bad: use only first match
/*
  const match = regex.exec(string_);
console.log("match", match)
  const { lang } = parseAttributes((match?.length && match[1]) || '');
  return lang === 'ts';
*/
// good: use all matches
// https://stackoverflow.com/a/6323598/10440128
var isTypeScript = false;
string_.replace(regex, (...match) => {
//console.log("match:\n", match)
  const { lang } = parseAttributes((match?.length && match[1]) || '');
  if (lang === 'ts') isTypeScript = true;
});
return isTypeScript;
}

/** Create a tag matching regexp. */
function createTagRegex(tagName, flags) {
  console.log(`/<!--[^]*?-->|<${tagName}(\\s[^]*?)?(?:>([^]*?)<\\/${tagName}>|\\/>)`);
  return new RegExp(`/<!--[^]*?-->|<${tagName}(\\s[^]*?)?(?:>([^]*?)<\\/${tagName}>|\\/>)`, flags);
}

/** Transform an attribute string into a key-value object */
function parseAttributes(attributesString) {
  return attributesString
    .split(/\s+/)
    .filter(Boolean)
    .reduce((accumulator, attribute) => {
      const [name, value] = attribute.split('=');

      // istanbul ignore next
      accumulator[name] = value ? value.replace(/["']/g, '') : true;

      return accumulator;
    }, {});
}

var c = `
<script>
  console.log("hello from javascript")
</script>

<script lang="ts">
  console.log("hello from typescript")
  export let name: string | null;
</script>
`

console.log(
isTypeScriptComponent(c)
)
ideally, the svelte parser should use my svelte.config.js
import sveltePreprocess from 'svelte-preprocess';

export default {
  preprocess: sveltePreprocess(),
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

1 participant