Files
fiddle/public/js/formatter.js

110 lines
3.1 KiB
JavaScript

import { loadScript } from './utils.js';
import { getActiveEditor, getActiveTab, getCurrentMode, getCssType, switchTab, getEditorValues } from './editors.js';
const PRETTIER_CDN = 'https://cdn.jsdelivr.net/npm/prettier@3';
const PLUGINS = [
'/standalone.min.js',
'/plugins/babel.min.js',
'/plugins/html.min.js',
'/plugins/postcss.min.js',
'/plugins/typescript.min.js',
'/plugins/estree.min.js',
];
let loaded = false;
async function ensurePrettier() {
if (loaded) return;
for (const plugin of PLUGINS) {
await loadScript(PRETTIER_CDN + plugin);
}
loaded = true;
}
function getParser(tabId, mode, cssType) {
if (tabId === 'html') return { parser: 'html', plugins: [prettierPlugins.html] };
if (tabId === 'css') {
return { parser: 'css', plugins: [prettierPlugins.postcss] };
}
// JS tab — depends on mode
if (mode === 'typescript' || mode === 'react-ts') {
return { parser: 'typescript', plugins: [prettierPlugins.typescript, prettierPlugins.estree] };
}
if (mode === 'markdown') {
return null; // Prettier markdown plugin not loaded
}
if (mode === 'vue' || mode === 'svelte') {
return { parser: 'html', plugins: [prettierPlugins.html] };
}
return { parser: 'babel', plugins: [prettierPlugins.babel, prettierPlugins.estree] };
}
export async function formatActiveEditor() {
const editor = getActiveEditor();
if (!editor) return;
await ensurePrettier();
const tabId = getActiveTab();
const mode = getCurrentMode();
const cssType = getCssType();
const config = getParser(tabId, mode, cssType);
if (!config) return;
const code = editor.getValue();
if (!code.trim()) return;
try {
// Save cursor position ratio
const pos = editor.getPosition();
const offset = editor.getModel().getOffsetAt(pos);
const ratio = offset / Math.max(code.length, 1);
const formatted = await prettier.format(code, {
parser: config.parser,
plugins: config.plugins,
singleQuote: true,
trailingComma: 'all',
printWidth: 100,
});
editor.setValue(formatted);
// Restore cursor approximately
const newOffset = Math.round(ratio * formatted.length);
const newPos = editor.getModel().getPositionAt(newOffset);
editor.setPosition(newPos);
editor.revealPositionInCenter(newPos);
} catch (e) {
console.warn('Prettier format error:', e.message);
}
}
export async function formatAll() {
await ensurePrettier();
const mode = getCurrentMode();
const cssType = getCssType();
const tabIds = ['html', 'css', 'js'];
for (const tabId of tabIds) {
const config = getParser(tabId, mode, cssType);
if (!config) continue;
// Temporarily switch to this tab to get its editor
switchTab(tabId);
const editor = getActiveEditor();
if (!editor) continue;
const code = editor.getValue();
if (!code.trim()) continue;
try {
const formatted = await prettier.format(code, {
parser: config.parser,
plugins: config.plugins,
singleQuote: true,
trailingComma: 'all',
printWidth: 100,
});
editor.setValue(formatted);
} catch (_) { /* skip tabs that fail */ }
}
}