@ -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 ( newF ilename) ;
const newLanguage = getLanguage ( f ilename) ;
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 } ;
}
return editor ;
function getFileBasedOptions ( filename , lineWrapExts ) {
return {
wordWrap : ( lineWrapExts || [ ] ) . includes ( extname ( filename ) ) ? 'on' : 'off' ,
} ;
}
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' ;
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 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 ;
}