taco
taco3w ago

Vite + Codemirror in SvelteKit 4 broken due to @codemirror/state being loaded twice

I am trying to migrate the SvelteKit project from Node to Deno, and this issue is preventing me from switching over. The npm modules installed alongside SvelteKit 4 needed to reproduce are codemirror @codemirror/lang-json I would imagine that being able to change the .deno directory to somewhere outside of node_modules would fix this. This is the error received in the browser on load: Error: Unrecognized extension value in extension set ([object Object]). This sometimes happens because multiple instances of @codemirror/state are loaded, breaking instanceof checks. The 2 instances being loaded in the browser are at: node_modules/@codemirror/state/dist/index.js node_modules/.deno/@codemirror+state@6.5.2/node_modules/@codemirror/state/dist This is running in the denoland/deno:alpine docker container.
FROM denoland/deno:alpine as dev

COPY ./lib /app/lib

COPY ./web /app/web

WORKDIR /app/web

RUN deno install

EXPOSE 5173

CMD ["deno", "run", "-A", "npm:vite", "dev", "--host"]
FROM denoland/deno:alpine as dev

COPY ./lib /app/lib

COPY ./web /app/web

WORKDIR /app/web

RUN deno install

EXPOSE 5173

CMD ["deno", "run", "-A", "npm:vite", "dev", "--host"]
Deno version (in the container):
deno 2.2.2 (stable, release, x86_64-unknown-linux-gnu)
v8 13.4.114.9-rusty
typescript 5.7.3
deno 2.2.2 (stable, release, x86_64-unknown-linux-gnu)
v8 13.4.114.9-rusty
typescript 5.7.3
I have tried to deny .deno in vite.config.js in server/fs/deny. Neither denying node_modules/.deno or denying .deno work.
import { sveltekit } from '@sveltejs/kit/vite';
import { defineConfig } from 'vitest/config';

export default defineConfig({
plugins: [sveltekit()],
test: {
include: ['src/**/*.{test,spec}.{js,ts}'],
},
server: {
allowedHosts: ['mydomain.com'],
fs: {
deny: '.deno'
}
},

});
import { sveltekit } from '@sveltejs/kit/vite';
import { defineConfig } from 'vitest/config';

export default defineConfig({
plugins: [sveltekit()],
test: {
include: ['src/**/*.{test,spec}.{js,ts}'],
},
server: {
allowedHosts: ['mydomain.com'],
fs: {
deny: '.deno'
}
},

});
3 Replies
taco
tacoOP3w ago
You can reproduce this by setting up the basic codemirror editor within a +page.svelte. This page is a stripped-down version of what I have.
<script>
import { onMount } from 'svelte';

import { json } from '@codemirror/lang-json';
import { editorFromTextarea } from '$lib/codemirror';
import { EditorView, basicSetup } from 'codemirror';

/**
* @function editorFromTextarea
* @param {HTMLTextAreaElement} field
* @param {Array<import('@codemirror/state').Extension>} extensions
* @returns {import('@codemirror/view').EditorView}
*/
export const editorFromTextarea = (field, ...extensions) => {
if (!field.parentNode) {
throw new Error('Parent node missing');
}
const view = new EditorView({
extensions: [basicSetup, ...extensions],
doc: field.value,
});

field.parentNode.insertBefore(view.dom, field);
field.style.display = 'none';
if (field.form) {
field.form.addEventListener('submit', () => {
field.value = view.state.doc.toString();
});
}
return view;
};
/** @type {HTMLTextAreaElement} */
let textareaElement;

onMount(() => {
const textareaView = editorFromTextarea(
textareaElement,
json(),
EditorView.updateListener.of((view) => {
if (view.docChanged) {
try {
console.log(view.state.doc.toString());
} catch {}
}
}),
);
}
</script>
<textarea bind:this={textareaElement} id="textareaElement" name="textareaElement" value="Text Content"></textarea>
<script>
import { onMount } from 'svelte';

import { json } from '@codemirror/lang-json';
import { editorFromTextarea } from '$lib/codemirror';
import { EditorView, basicSetup } from 'codemirror';

/**
* @function editorFromTextarea
* @param {HTMLTextAreaElement} field
* @param {Array<import('@codemirror/state').Extension>} extensions
* @returns {import('@codemirror/view').EditorView}
*/
export const editorFromTextarea = (field, ...extensions) => {
if (!field.parentNode) {
throw new Error('Parent node missing');
}
const view = new EditorView({
extensions: [basicSetup, ...extensions],
doc: field.value,
});

field.parentNode.insertBefore(view.dom, field);
field.style.display = 'none';
if (field.form) {
field.form.addEventListener('submit', () => {
field.value = view.state.doc.toString();
});
}
return view;
};
/** @type {HTMLTextAreaElement} */
let textareaElement;

onMount(() => {
const textareaView = editorFromTextarea(
textareaElement,
json(),
EditorView.updateListener.of((view) => {
if (view.docChanged) {
try {
console.log(view.state.doc.toString());
} catch {}
}
}),
);
}
</script>
<textarea bind:this={textareaElement} id="textareaElement" name="textareaElement" value="Text Content"></textarea>
marvinh.
marvinh.3w ago
Can you file an issue for that here https://github.com/denoland/deno-vite-plugin/issues ? It's much easier to track issues for us on GitHub than in discord
GitHub
Issues · denoland/deno-vite-plugin
Vite plugin to enable Deno resolution inside vite. - Issues · denoland/deno-vite-plugin
taco
tacoOP3w ago
GitHub
Vite + Codemirror in SvelteKit 4 broken due to @codemirror/state be...
Version: docker denoland/deno:alpine deno 2.2.2 (stable, release, x86_64-unknown-linux-gnu) v8 13.4.114.9-rusty typescript 5.7.3 I am trying to migrate the SvelteKit project from Node to Deno, and ...

Did you find this page helpful?