Vue component for editing Vue components with interactive REPL functionality.
—
The file system provides the File class and compilation utilities for managing code files with compilation results, editor state persistence, and language detection.
Core file model representing a single file in the REPL with compilation state and editor persistence.
/**
* Represents a file in the REPL with code content and compilation results
*/
class File {
/** File path/name relative to project root */
filename: string;
/** Raw source code content */
code: string;
/** Whether file is hidden from file explorer UI */
hidden: boolean;
/** Compilation results for different output formats */
compiled: {
/** Compiled JavaScript code */
js: string;
/** Extracted/compiled CSS */
css: string;
/** Server-side rendering compiled code */
ssr: string;
/** Client-side source map */
clientMap: string;
/** SSR source map */
ssrMap: string;
};
/** Monaco editor view state for cursor/scroll position persistence */
editorViewState: editor.ICodeEditorViewState | null;
/**
* Create a new file instance
* @param filename - File path/name
* @param code - Initial file content
* @param hidden - Whether file should be hidden from UI
*/
constructor(filename: string, code?: string, hidden?: boolean);
/**
* Detected language based on file extension
* @returns Language identifier for syntax highlighting
*/
readonly language: 'vue' | 'html' | 'css' | 'typescript' | 'javascript';
}Usage Examples:
import { File } from "@vue/repl/core";
// Create new Vue component file
const vueFile = new File(
'src/components/Button.vue',
`<template>
<button @click="handleClick">
<slot />
</button>
</template>
<script setup lang="ts">
const emit = defineEmits<{
click: [event: MouseEvent]
}>();
const handleClick = (event: MouseEvent) => {
emit('click', event);
};
</script>
<style scoped>
button {
padding: 8px 16px;
border-radius: 4px;
}
</style>`
);
// Create TypeScript utility file
const tsFile = new File(
'src/utils/helpers.ts',
`export const formatDate = (date: Date): string => {
return date.toLocaleDateString();
};
export const debounce = <T extends (...args: any[]) => any>(
fn: T,
delay: number
): T => {
let timeoutId: ReturnType<typeof setTimeout>;
return ((...args: any[]) => {
clearTimeout(timeoutId);
timeoutId = setTimeout(() => fn(...args), delay);
}) as T;
};`
);
// Create hidden configuration file
const configFile = new File(
'package.json',
JSON.stringify({ name: 'my-app', version: '1.0.0' }),
true // hidden from file explorer
);
// Access file properties
console.log(vueFile.language); // 'vue'
console.log(tsFile.language); // 'typescript'
console.log(vueFile.compiled.js); // Compiled JavaScript after compilationCore compilation function that processes different file types into executable code.
/**
* Compile a file based on its type and content
* Handles Vue SFC, TypeScript/JavaScript, CSS, and JSON files
* @param store - Store instance for compiler access and options
* @param file - File instance to compile
* @returns Promise resolving to array of compilation errors or empty array
*/
function compileFile(
store: Store,
file: File
): Promise<(string | Error)[]>;Supported File Types:
.vue: Vue Single File Components with full SFC compilation.ts, .tsx: TypeScript files with JSX support.js, .jsx: JavaScript files with JSX support.css: CSS stylesheets (passed through unchanged).json: JSON files (converted to ES module exports)Usage Examples:
import { compileFile, File, useStore } from "@vue/repl/core";
const store = useStore();
const file = new File('src/App.vue', '<template><div>Hello</div></template>');
// Compile the file
const errors = await compileFile(store, file);
if (errors.length === 0) {
console.log('Compiled successfully');
console.log(file.compiled.js); // Compiled JavaScript
console.log(file.compiled.css); // Extracted CSS
} else {
console.error('Compilation errors:', errors);
}
// TypeScript file compilation
const tsFile = new File('utils.ts', `
export const add = (a: number, b: number): number => a + b;
`);
const tsErrors = await compileFile(store, tsFile);
console.log(tsFile.compiled.js); // Compiled JavaScript without typesFiles automatically detect their language based on file extensions for proper syntax highlighting and compilation.
/**
* Language detection based on file extension
*/
type FileLanguage = 'vue' | 'html' | 'css' | 'typescript' | 'javascript';
/**
* Language detection mapping
*/
const languageMap = {
'.vue': 'vue',
'.html': 'html',
'.css': 'css',
'.ts': 'typescript',
'.tsx': 'typescript',
'.js': 'javascript',
'.jsx': 'javascript'
};Usage Example:
const files = [
new File('App.vue'),
new File('utils.ts'),
new File('styles.css'),
new File('config.json')
];
files.forEach(file => {
console.log(`${file.filename}: ${file.language}`);
});
// Output:
// App.vue: vue
// utils.ts: typescript
// styles.css: css
// config.json: javascript (default)Files maintain editor view state for cursor position, scroll position, and selections across editor switches.
/**
* Monaco editor view state interface
*/
interface ICodeEditorViewState {
cursorState: ICursorState[];
viewState: IViewState;
contributionsState: { [id: string]: any };
}Usage Example:
// View state is automatically managed by the editor components
// No manual intervention needed - handled by Monaco/CodeMirror editors
// Access view state if needed
const file = store.activeFile;
if (file.editorViewState) {
console.log('File has saved editor state');
}The file system uses specific naming conventions for special files:
/** Standard filename for import map configuration */
const importMapFile = 'import-map.json';
/** Standard filename for TypeScript configuration */
const tsconfigFile = 'tsconfig.json';
/**
* Add src/ prefix to relative file paths
* @param file - File path
* @returns Path with src/ prefix if needed
*/
function addSrcPrefix(file: string): string;
/**
* Remove src/ prefix from file paths for export
* @param file - File path with potential src/ prefix
* @returns Path without src/ prefix
*/
function stripSrcPrefix(file: string): string;Usage Examples:
import { stripSrcPrefix } from "@vue/repl/core";
// File path normalization
console.log(addSrcPrefix('App.vue')); // 'src/App.vue'
console.log(addSrcPrefix('src/App.vue')); // 'src/App.vue' (unchanged)
console.log(stripSrcPrefix('src/App.vue')); // 'App.vue'
// Special files bypass src/ prefix
console.log(addSrcPrefix('import-map.json')); // 'import-map.json'
console.log(addSrcPrefix('tsconfig.json')); // 'tsconfig.json'Vue Single File Components undergo comprehensive compilation:
Compilation Options:
The compilation process respects store SFC options:
// SFC compilation can be customized via store
store.sfcOptions = {
script: {
babelParserPlugins: ['jsx', 'decorators-legacy']
},
template: {
compilerOptions: {
isCustomElement: (tag) => tag.startsWith('custom-')
}
},
style: {
trim: true
}
};Compilation errors are comprehensive and helpful:
// Errors are returned as array of strings or Error objects
const errors = await compileFile(store, file);
errors.forEach(error => {
if (typeof error === 'string') {
console.error('Compilation error:', error);
} else {
console.error('Exception:', error.message, error.stack);
}
});Install with Tessl CLI
npx tessl i tessl/npm-vue--repl