mod: в CodeMirror добавлено data-language для url
This commit is contained in:
@@ -46,17 +46,16 @@ cp "$ROOT_DIR/package.json" "$ROOT_DIR/package-lock.json" "$WORK_DIR/"
|
|||||||
|
|
||||||
cat > "$WORK_DIR/src/editor.js" <<'EOF'
|
cat > "$WORK_DIR/src/editor.js" <<'EOF'
|
||||||
import { Compartment, EditorState } from '@codemirror/state';
|
import { Compartment, EditorState } from '@codemirror/state';
|
||||||
import { EditorView } from '@codemirror/view';
|
import { EditorView, lineNumbers, placeholder } from '@codemirror/view';
|
||||||
import { defaultHighlightStyle, syntaxHighlighting } from '@codemirror/language';
|
import { defaultHighlightStyle, syntaxHighlighting } from '@codemirror/language';
|
||||||
import { html } from '@codemirror/lang-html';
|
import { html } from '@codemirror/lang-html';
|
||||||
import { javascript } from '@codemirror/lang-javascript';
|
import { javascript } from '@codemirror/lang-javascript';
|
||||||
import { json } from '@codemirror/lang-json';
|
import { json } from '@codemirror/lang-json';
|
||||||
import { css } from '@codemirror/lang-css';
|
import { css } from '@codemirror/lang-css';
|
||||||
import { solarizedDark, solarizedLight } from '@uiw/codemirror-theme-solarized';
|
import { solarizedDark, solarizedLight } from '@uiw/codemirror-theme-solarized';
|
||||||
import { lineNumbers } from '@codemirror/view';
|
|
||||||
|
|
||||||
const themeCompartment = new Compartment();
|
const themeCompartment = new Compartment();
|
||||||
const processedForms = new Set(); // Храним формы, на которые уже повесили обработчик
|
const processedForms = new Set();
|
||||||
|
|
||||||
function isDarkTheme() {
|
function isDarkTheme() {
|
||||||
const rootTheme = document.documentElement.dataset.theme;
|
const rootTheme = document.documentElement.dataset.theme;
|
||||||
@@ -74,51 +73,50 @@ function reconfigureTheme(view) {
|
|||||||
function initCodeMirrorEditors() {
|
function initCodeMirrorEditors() {
|
||||||
document.querySelectorAll('textarea[data-codemirror-editor]').forEach((textarea) => {
|
document.querySelectorAll('textarea[data-codemirror-editor]').forEach((textarea) => {
|
||||||
const language = textarea.dataset.language || 'text';
|
const language = textarea.dataset.language || 'text';
|
||||||
|
const inputMode = textarea.dataset.inputMode || 'default';
|
||||||
let initialDoc = textarea.value ?? '';
|
let initialDoc = textarea.value ?? '';
|
||||||
const wrapper = document.createElement('div');
|
const wrapper = document.createElement('div');
|
||||||
wrapper.className = 'cm6-editor-wrapper';
|
wrapper.className = 'cm6-editor-wrapper';
|
||||||
textarea.insertAdjacentElement('beforebegin', wrapper);
|
textarea.insertAdjacentElement('beforebegin', wrapper);
|
||||||
|
|
||||||
// --- Beautify JSON on load ---
|
|
||||||
if (language === 'json') {
|
if (language === 'json') {
|
||||||
try {
|
try {
|
||||||
const parsed = JSON.parse(initialDoc);
|
const parsed = JSON.parse(initialDoc);
|
||||||
initialDoc = JSON.stringify(parsed, null, 2); // Форматируем с отступом в 2 пробела
|
initialDoc = JSON.stringify(parsed, null, 2);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
// Если в поле невалидный JSON, оставляем как есть
|
|
||||||
console.warn("CodeMirror: Initial content is not valid JSON, displaying as is.", e);
|
console.warn("CodeMirror: Initial content is not valid JSON, displaying as is.", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const syncTextarea = EditorView.updateListener.of((update) => {
|
const syncTextarea = EditorView.updateListener.of((update) => {
|
||||||
if (update.docChanged) {
|
if (update.docChanged) {
|
||||||
// Синхронизируем "красивый" JSON в textarea для немедленного отображения
|
|
||||||
textarea.value = update.state.doc.toString();
|
textarea.value = update.state.doc.toString();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// --- Собираем расширения в правильном порядке ---
|
||||||
const extensions = [
|
const extensions = [
|
||||||
EditorView.lineWrapping,
|
|
||||||
syntaxHighlighting(defaultHighlightStyle),
|
syntaxHighlighting(defaultHighlightStyle),
|
||||||
syncTextarea,
|
syncTextarea,
|
||||||
themeCompartment.of(isDarkTheme() ? solarizedDark : solarizedLight),
|
themeCompartment.of(isDarkTheme() ? solarizedDark : solarizedLight),
|
||||||
];
|
];
|
||||||
|
|
||||||
// Добавляем нумерацию строк, если не указано обратное
|
// Язык
|
||||||
if (!textarea.classList.contains('codemirror-no-lines')) {
|
if (language === 'javascript') extensions.push(javascript());
|
||||||
extensions.unshift(lineNumbers());
|
else if (language === 'css') extensions.push(css());
|
||||||
}
|
else if (language === 'json') extensions.push(json());
|
||||||
|
else if (language === 'html') extensions.push(html());
|
||||||
|
|
||||||
if (language === 'javascript') {
|
// Режим ввода
|
||||||
extensions.unshift(javascript());
|
if (inputMode === 'url') {
|
||||||
} else if (language === 'css') {
|
extensions.push(placeholder('https://example.com/path'));
|
||||||
extensions.unshift(css());
|
// Для URL не добавляем lineWrapping и lineNumbers
|
||||||
} else if (language === 'json') {
|
} else {
|
||||||
extensions.unshift(json());
|
extensions.push(EditorView.lineWrapping);
|
||||||
} else if (language === 'html') {
|
if (!textarea.classList.contains('codemirror-no-lines')) {
|
||||||
extensions.unshift(html());
|
extensions.push(lineNumbers());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// Для 'text' язык не добавляется, будет обычное поле
|
|
||||||
|
|
||||||
const state = EditorState.create({
|
const state = EditorState.create({
|
||||||
doc: initialDoc,
|
doc: initialDoc,
|
||||||
@@ -130,7 +128,6 @@ function initCodeMirrorEditors() {
|
|||||||
parent: wrapper,
|
parent: wrapper,
|
||||||
});
|
});
|
||||||
|
|
||||||
// Сохраняем ссылку на инстанс редактора для последующего доступа
|
|
||||||
textarea.cmView = view;
|
textarea.cmView = view;
|
||||||
|
|
||||||
reconfigureTheme(view);
|
reconfigureTheme(view);
|
||||||
@@ -144,7 +141,6 @@ function initCodeMirrorEditors() {
|
|||||||
const colorScheme = window.matchMedia('(prefers-color-scheme: dark)');
|
const colorScheme = window.matchMedia('(prefers-color-scheme: dark)');
|
||||||
colorScheme.addEventListener('change', () => reconfigureTheme(view));
|
colorScheme.addEventListener('change', () => reconfigureTheme(view));
|
||||||
|
|
||||||
// --- Minify JSON on save ---
|
|
||||||
const form = textarea.closest('form');
|
const form = textarea.closest('form');
|
||||||
if (form && !processedForms.has(form)) {
|
if (form && !processedForms.has(form)) {
|
||||||
form.addEventListener('submit', () => {
|
form.addEventListener('submit', () => {
|
||||||
@@ -154,10 +150,9 @@ function initCodeMirrorEditors() {
|
|||||||
try {
|
try {
|
||||||
const parsed = JSON.parse(prettyJson);
|
const parsed = JSON.parse(prettyJson);
|
||||||
const minifiedJson = JSON.stringify(parsed);
|
const minifiedJson = JSON.stringify(parsed);
|
||||||
jsonTextarea.value = minifiedJson; // Подменяем значение на сжатое
|
jsonTextarea.value = minifiedJson;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
// Если пользователь ввел невалидный JSON, позволяем Django его отвергнуть
|
console.warn("CodeMirror: Could not minify invalid JSON before submit.", e);
|
||||||
console.warn("CodeMirror: Could not minify invalid JSON before submit. Django will likely reject this.", e);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user