110 lines
3.1 KiB
JavaScript
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 */ }
|
|
}
|
|
}
|