mirror of
				https://github.com/go-gitea/gitea.git
				synced 2025-11-03 20:36:07 +01:00 
			
		
		
		
	Use monaco for the git hook editor (#13552)
Migrate git hook editor to monaco, replacing CodeMirror. Had to do a few refactors to make the monaco instantiation generic enough to be of use. Co-authored-by: Lunny Xiao <xiaolunwen@gmail.com> Co-authored-by: techknowlogick <techknowlogick@gitea.io>
This commit is contained in:
		@@ -26,12 +26,11 @@ function getLanguage(filename) {
 | 
			
		||||
  return languagesByFilename[filename] || languagesByExt[extname(filename)] || 'plaintext';
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function updateEditor(monaco, editor, filenameInput) {
 | 
			
		||||
  const newFilename = filenameInput.value;
 | 
			
		||||
  editor.updateOptions(getOptions(filenameInput));
 | 
			
		||||
function updateEditor(monaco, editor, filename, lineWrapExts) {
 | 
			
		||||
  editor.updateOptions({...getFileBasedOptions(filename, lineWrapExts)});
 | 
			
		||||
  const model = editor.getModel();
 | 
			
		||||
  const language = model.getModeId();
 | 
			
		||||
  const newLanguage = getLanguage(newFilename);
 | 
			
		||||
  const newLanguage = getLanguage(filename);
 | 
			
		||||
  if (language !== newLanguage) monaco.editor.setModelLanguage(model, newLanguage);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -41,24 +40,12 @@ function exportEditor(editor) {
 | 
			
		||||
  if (!window.codeEditors.includes(editor)) window.codeEditors.push(editor);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export async function createCodeEditor(textarea, filenameInput, previewFileModes) {
 | 
			
		||||
  const filename = basename(filenameInput.value);
 | 
			
		||||
  const previewLink = document.querySelector('a[data-tab=preview]');
 | 
			
		||||
  const markdownExts = (textarea.dataset.markdownFileExts || '').split(',');
 | 
			
		||||
  const lineWrapExts = (textarea.dataset.lineWrapExtensions || '').split(',');
 | 
			
		||||
  const isMarkdown = markdownExts.includes(extname(filename));
 | 
			
		||||
 | 
			
		||||
  if (previewLink) {
 | 
			
		||||
    if (isMarkdown && (previewFileModes || []).includes('markdown')) {
 | 
			
		||||
      previewLink.dataset.url = previewLink.dataset.url.replace(/(.*)\/.*/i, `$1/markdown`);
 | 
			
		||||
      previewLink.style.display = '';
 | 
			
		||||
    } else {
 | 
			
		||||
      previewLink.style.display = 'none';
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
export async function createMonaco(textarea, filename, editorOpts) {
 | 
			
		||||
  const monaco = await import(/* webpackChunkName: "monaco" */'monaco-editor');
 | 
			
		||||
 | 
			
		||||
  initLanguages(monaco);
 | 
			
		||||
  let {language, ...other} = editorOpts;
 | 
			
		||||
  if (!language) language = getLanguage(filename);
 | 
			
		||||
 | 
			
		||||
  const container = document.createElement('div');
 | 
			
		||||
  container.className = 'monaco-editor-container';
 | 
			
		||||
@@ -66,8 +53,9 @@ export async function createCodeEditor(textarea, filenameInput, previewFileModes
 | 
			
		||||
 | 
			
		||||
  const editor = monaco.editor.create(container, {
 | 
			
		||||
    value: textarea.value,
 | 
			
		||||
    language: getLanguage(filename),
 | 
			
		||||
    ...getOptions(filenameInput, lineWrapExts),
 | 
			
		||||
    theme: isDarkTheme() ? 'vs-dark' : 'vs',
 | 
			
		||||
    language,
 | 
			
		||||
    ...other,
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  const model = editor.getModel();
 | 
			
		||||
@@ -80,33 +68,60 @@ export async function createCodeEditor(textarea, filenameInput, previewFileModes
 | 
			
		||||
    editor.layout();
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  filenameInput.addEventListener('keyup', () => {
 | 
			
		||||
    updateEditor(monaco, editor, filenameInput);
 | 
			
		||||
  });
 | 
			
		||||
  exportEditor(editor);
 | 
			
		||||
 | 
			
		||||
  const loading = document.querySelector('.editor-loading');
 | 
			
		||||
  if (loading) loading.remove();
 | 
			
		||||
 | 
			
		||||
  exportEditor(editor);
 | 
			
		||||
  return {monaco, editor};
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function getFileBasedOptions(filename, lineWrapExts) {
 | 
			
		||||
  return {
 | 
			
		||||
    wordWrap: (lineWrapExts || []).includes(extname(filename)) ? 'on' : 'off',
 | 
			
		||||
  };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export async function createCodeEditor(textarea, filenameInput, previewFileModes) {
 | 
			
		||||
  const filename = basename(filenameInput.value);
 | 
			
		||||
  const previewLink = document.querySelector('a[data-tab=preview]');
 | 
			
		||||
  const markdownExts = (textarea.dataset.markdownFileExts || '').split(',');
 | 
			
		||||
  const lineWrapExts = (textarea.dataset.lineWrapExtensions || '').split(',');
 | 
			
		||||
  const isMarkdown = markdownExts.includes(extname(filename));
 | 
			
		||||
  const editorConfig = getEditorconfig(filenameInput);
 | 
			
		||||
 | 
			
		||||
  if (previewLink) {
 | 
			
		||||
    if (isMarkdown && (previewFileModes || []).includes('markdown')) {
 | 
			
		||||
      previewLink.dataset.url = previewLink.dataset.url.replace(/(.*)\/.*/i, `$1/markdown`);
 | 
			
		||||
      previewLink.style.display = '';
 | 
			
		||||
    } else {
 | 
			
		||||
      previewLink.style.display = 'none';
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  const {monaco, editor} = await createMonaco(textarea, filename, {
 | 
			
		||||
    ...getFileBasedOptions(filenameInput.value, lineWrapExts),
 | 
			
		||||
    ...getEditorConfigOptions(editorConfig),
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  filenameInput.addEventListener('keyup', () => {
 | 
			
		||||
    const filename = filenameInput.value;
 | 
			
		||||
    updateEditor(monaco, editor, filename, lineWrapExts);
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  return editor;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function getOptions(filenameInput, lineWrapExts) {
 | 
			
		||||
  const ec = getEditorconfig(filenameInput);
 | 
			
		||||
  const theme = isDarkTheme() ? 'vs-dark' : 'vs';
 | 
			
		||||
  const wordWrap = (lineWrapExts || []).includes(extname(filenameInput.value)) ? 'on' : 'off';
 | 
			
		||||
 | 
			
		||||
  const opts = {theme, wordWrap};
 | 
			
		||||
  if (isObject(ec)) {
 | 
			
		||||
    opts.detectIndentation = !('indent_style' in ec) || !('indent_size' in ec);
 | 
			
		||||
    if ('indent_size' in ec) opts.indentSize = Number(ec.indent_size);
 | 
			
		||||
    if ('tab_width' in ec) opts.tabSize = Number(ec.tab_width) || opts.indentSize;
 | 
			
		||||
    if ('max_line_length' in ec) opts.rulers = [Number(ec.max_line_length)];
 | 
			
		||||
    opts.trimAutoWhitespace = ec.trim_trailing_whitespace === true;
 | 
			
		||||
    opts.insertSpaces = ec.indent_style === 'space';
 | 
			
		||||
    opts.useTabStops = ec.indent_style === 'tab';
 | 
			
		||||
  }
 | 
			
		||||
function getEditorConfigOptions(ec) {
 | 
			
		||||
  if (!isObject(ec)) return {};
 | 
			
		||||
 | 
			
		||||
  const opts = {};
 | 
			
		||||
  opts.detectIndentation = !('indent_style' in ec) || !('indent_size' in ec);
 | 
			
		||||
  if ('indent_size' in ec) opts.indentSize = Number(ec.indent_size);
 | 
			
		||||
  if ('tab_width' in ec) opts.tabSize = Number(ec.tab_width) || opts.indentSize;
 | 
			
		||||
  if ('max_line_length' in ec) opts.rulers = [Number(ec.max_line_length)];
 | 
			
		||||
  opts.trimAutoWhitespace = ec.trim_trailing_whitespace === true;
 | 
			
		||||
  opts.insertSpaces = ec.indent_style === 'space';
 | 
			
		||||
  opts.useTabStops = ec.indent_style === 'tab';
 | 
			
		||||
  return opts;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user