forked from zauberzeug/nicegui
-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge remote-tracking branch 'nicegui/main' into feature/client_data
- Loading branch information
Showing
154 changed files
with
1,569 additions
and
321 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -31,7 +31,6 @@ | |
} | ||
} | ||
} | ||
} | ||
} | ||
}, | ||
// More info: https://aka.ms/dev-containers-non-root. | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,4 @@ | ||
.mypy_cache | ||
__pycache__/ | ||
.DS_Store | ||
*.tmp |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,178 @@ | ||
export default { | ||
template: ` | ||
<div></div> | ||
`, | ||
props: { | ||
value: String, | ||
language: String, | ||
theme: String, | ||
resource_path: String, | ||
lineWrapping: Boolean, | ||
disable: Boolean, | ||
indent: String, | ||
highlightWhitespace: Boolean, | ||
}, | ||
watch: { | ||
value(newValue) { | ||
this.setEditorValue(newValue); | ||
}, | ||
language(newLanguage) { | ||
this.setLanguage(newLanguage); | ||
}, | ||
theme(newTheme) { | ||
this.setTheme(newTheme); | ||
}, | ||
disable(newDisable) { | ||
this.setDisabled(newDisable); | ||
}, | ||
}, | ||
data() { | ||
return { | ||
// To let other methods wait for the editor to be created because | ||
// they might be called by the server before the editor is created. | ||
editorPromise: new Promise((resolve) => { | ||
this.resolveEditor = resolve; | ||
}), | ||
}; | ||
}, | ||
methods: { | ||
// Find the language's extension by its name. Case insensitive. | ||
findLanguage(name) { | ||
for (const language of this.languages) | ||
for (const alias of [language.name, ...language.alias]) | ||
if (name.toLowerCase() === alias.toLowerCase()) return language; | ||
|
||
console.error(`Language not found: ${this.language}`); | ||
console.info("Supported language names:", languages.map((lang) => lang.name).join(", ")); | ||
return null; | ||
}, | ||
// Get the names of all supported languages | ||
async getLanguages() { | ||
if (!this.editor) await this.editorPromise; | ||
// Over 100 supported languages: https://github.com/codemirror/language-data/blob/main/src/language-data.ts | ||
return this.languages.map((lang) => lang.name).sort(Intl.Collator("en").compare); | ||
}, | ||
setLanguage(language) { | ||
if (!language) { | ||
this.editor.dispatch({ | ||
effects: this.languageConfig.reconfigure([]), | ||
}); | ||
return; | ||
} | ||
|
||
const lang_description = this.findLanguage(language, this.languages); | ||
if (!lang_description) { | ||
console.error("Language not found:", language); | ||
return; | ||
} | ||
|
||
lang_description.load().then((extension) => { | ||
this.editor.dispatch({ | ||
effects: this.languageConfig.reconfigure([extension]), | ||
}); | ||
}); | ||
}, | ||
async getThemes() { | ||
if (!this.editor) await this.editorPromise; | ||
// `this.themes` also contains some non-theme objects | ||
// The real themes are Arrays | ||
return Object.keys(this.themes) | ||
.filter((key) => Array.isArray(this.themes[key])) | ||
.sort(Intl.Collator("en").compare); | ||
}, | ||
setTheme(theme) { | ||
const new_theme = this.themes[theme]; | ||
if (new_theme === undefined) { | ||
console.error("Theme not found:", theme); | ||
return; | ||
} | ||
this.editor.dispatch({ | ||
effects: this.themeConfig.reconfigure([new_theme]), | ||
}); | ||
}, | ||
setEditorValue(value) { | ||
if (!this.editor) return; | ||
if (this.editor.state.doc.toString() === value) return; | ||
|
||
this.emitting = false; | ||
this.editor.dispatch({ changes: { from: 0, to: this.editor.state.doc.length, insert: value } }); | ||
this.emitting = true; | ||
}, | ||
setDisabled(disabled) { | ||
this.editor.dispatch({ | ||
effects: this.editableConfig.reconfigure(this.editableStates[!disabled]), | ||
}); | ||
}, | ||
setupExtensions() { | ||
const CM = this.CM; | ||
|
||
const self = this; | ||
|
||
// Sends a ChangeSet https://codemirror.net/docs/ref/#state.ChangeSet | ||
// containing only the changes made to the document. | ||
// This could potentially be optimized further by sending updates | ||
// periodically instead of on every change and accumulating changesets | ||
// with ChangeSet.compose. | ||
const changeSender = this.CM.ViewPlugin.fromClass( | ||
class { | ||
update(update) { | ||
if (!update.docChanged) return; | ||
if (!self.emitting) return; | ||
self.$emit("update:value", update.changes); | ||
} | ||
} | ||
); | ||
|
||
const extensions = [ | ||
CM.basicSetup, | ||
changeSender, | ||
// Enables the Tab key to indent the current lines https://codemirror.net/examples/tab/ | ||
CM.keymap.of([CM.indentWithTab]), | ||
// Sets indentation https://codemirror.net/docs/ref/#language.indentUnit | ||
CM.indentUnit.of(this.indent), | ||
// We will set these Compartments later and dynamically through props | ||
this.themeConfig.of([]), | ||
this.languageConfig.of([]), | ||
this.editableConfig.of([]), | ||
CM.EditorView.theme({ | ||
"&": { height: "100%" }, | ||
".cm-scroller": { overflow: "auto" }, | ||
}), | ||
]; | ||
|
||
if (this.lineWrapping) extensions.push(CM.EditorView.lineWrapping); | ||
if (this.highlightWhitespace) extensions.push([CM.highlightWhitespace()]); | ||
|
||
return extensions; | ||
}, | ||
}, | ||
async mounted() { | ||
this.CM = await import(`${this.resource_path}/editor.js`); | ||
const CM = this.CM; | ||
|
||
// This is used to prevent emitting the value we just received from the server. | ||
this.emitting = true; | ||
|
||
// The Compartments are used to change the properties of the editor ("extensions") dynamically | ||
this.themes = { ...CM.themes, oneDark: CM.oneDark }; | ||
this.themeConfig = new CM.Compartment(); | ||
this.languages = CM.languages; | ||
this.languageConfig = new CM.Compartment(); | ||
this.editableConfig = new CM.Compartment(); | ||
this.editableStates = { true: CM.EditorView.editable.of(true), false: CM.EditorView.editable.of(false) }; | ||
|
||
const extensions = this.setupExtensions(); | ||
|
||
this.editor = new CM.EditorView({ | ||
doc: this.value, | ||
extensions: extensions, | ||
parent: this.$el, | ||
}); | ||
|
||
this.resolveEditor(this.editor); | ||
|
||
this.setLanguage(this.language); | ||
this.setTheme(this.theme); | ||
this.setDisabled(this.disable); | ||
}, | ||
}; |
Oops, something went wrong.