mirror of
https://github.com/knadh/listmonk.git
synced 2025-01-24 07:10:00 +08:00
replacing codeflask with code-input
This commit is contained in:
parent
2abc0a8651
commit
80e6dd191a
4 changed files with 147 additions and 101 deletions
3
frontend/index.html
vendored
3
frontend/index.html
vendored
|
@ -17,5 +17,8 @@
|
|||
<div id="app"></div>
|
||||
|
||||
<script type="module" src="/src/main.js"></script>
|
||||
<script src="./node_modules/@webcoder49/code-input/code-input.js"></script>
|
||||
<link rel="stylesheet" href="./node_modules/@webcoder49/code-input/code-input.min.css">
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
|
1
frontend/package.json
vendored
1
frontend/package.json
vendored
|
@ -11,6 +11,7 @@
|
|||
},
|
||||
"dependencies": {
|
||||
"@tinymce/tinymce-vue": "^3",
|
||||
"@webcoder49/code-input": "github:WebCoder49/code-input",
|
||||
"axios": "^1.7.4",
|
||||
"buefy": "^0.9.25",
|
||||
"bulma": "^0.9.4",
|
||||
|
|
|
@ -1,10 +1,18 @@
|
|||
<template>
|
||||
<div ref="htmlEditor" id="html-editor" class="html-editor" />
|
||||
<div ref="htmlEditor" class="html-editor">
|
||||
<code-input
|
||||
ref="editor"
|
||||
:value="value"
|
||||
@input="handleInput"
|
||||
language="html"
|
||||
:data-readonly="disabled"
|
||||
spellcheck="false"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import CodeFlask from 'codeflask';
|
||||
import { colors } from '../constants';
|
||||
import Prism from 'prismjs';
|
||||
|
||||
export default {
|
||||
props: {
|
||||
|
@ -13,66 +21,60 @@ export default {
|
|||
disabled: Boolean,
|
||||
},
|
||||
|
||||
data() {
|
||||
return {
|
||||
data: '',
|
||||
flask: null,
|
||||
};
|
||||
},
|
||||
|
||||
methods: {
|
||||
initHTMLEditor(body) {
|
||||
// CodeFlask editor is rendered in a shadow DOM tree to keep its styles
|
||||
// sandboxed away from the global styles.
|
||||
const el = document.createElement('code-flask');
|
||||
el.attachShadow({ mode: 'open' });
|
||||
el.shadowRoot.innerHTML = `
|
||||
<style>
|
||||
.codeflask .codeflask__flatten {
|
||||
font-size: 15px;
|
||||
white-space: pre-wrap ;
|
||||
word-break: break-word ;
|
||||
}
|
||||
.codeflask .codeflask__lines { background: #fafafa; z-index: 10; }
|
||||
.codeflask .token.tag { font-weight: bold; }
|
||||
.codeflask .token.attr-name { color: #111; }
|
||||
.codeflask .token.attr-value { color: ${colors.primary} !important; }
|
||||
</style>
|
||||
<div id="area"></area>
|
||||
`;
|
||||
this.$refs.htmlEditor.appendChild(el);
|
||||
handleInput(event) {
|
||||
this.$emit('input', event.target.value);
|
||||
},
|
||||
|
||||
this.flask = new CodeFlask(el.shadowRoot.getElementById('area'), {
|
||||
language: this.$props.language,
|
||||
lineNumbers: false,
|
||||
styleParent: el.shadowRoot,
|
||||
readonly: this.disabled,
|
||||
});
|
||||
initializeEditor() {
|
||||
// const textarea = this.$refs.editor;
|
||||
// textarea.setAttribute('is', 'code-input');
|
||||
// textarea.setAttribute('data-language', this.language);
|
||||
|
||||
this.flask.onUpdate((v) => {
|
||||
this.data = v;
|
||||
this.$emit('input', v);
|
||||
});
|
||||
|
||||
// Set the initial value.
|
||||
this.flask.updateCode(body);
|
||||
|
||||
this.$nextTick(() => {
|
||||
document.querySelector('code-flask').shadowRoot.querySelector('textarea').focus();
|
||||
});
|
||||
// Register Prism for syntax highlighting if needed
|
||||
if (window.codeInput) {
|
||||
window.codeInput.registerTemplate(
|
||||
'syntax-highlighted',
|
||||
window.codeInput.templates.prism(Prism, []),
|
||||
);
|
||||
// window.codeInput.setDefaultTemplate('syntax-highlighted');
|
||||
}
|
||||
},
|
||||
},
|
||||
|
||||
mounted() {
|
||||
this.initHTMLEditor(this.$props.value || '');
|
||||
},
|
||||
|
||||
watch: {
|
||||
value(newVal) {
|
||||
if (newVal !== this.data) {
|
||||
this.flask.updateCode(newVal);
|
||||
}
|
||||
},
|
||||
this.initializeEditor();
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style>
|
||||
/* Hide the non-editable preview content */
|
||||
.code-input pre[aria-hidden="true"] {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
/* Additional styling */
|
||||
.html-editor {
|
||||
width: 100%;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.html-editor textarea {
|
||||
font-size: 15px;
|
||||
min-height: 200px;
|
||||
width: 100%;
|
||||
padding: 8px;
|
||||
border: none;
|
||||
resize: none;
|
||||
}
|
||||
|
||||
.token.tag { font-weight: bold; }
|
||||
.token.attr-name { color: #111; }
|
||||
.token.attr-value { color: #0066cc; }
|
||||
|
||||
.html-editor textarea:focus {
|
||||
outline: none;
|
||||
border-color: #0066cc;
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -1,11 +1,20 @@
|
|||
<template>
|
||||
<div ref="markdownEditor" id="markdown-editor" class="markdown-editor" />
|
||||
<div ref="markdownEditor" class="markdown-editor">
|
||||
<code-input
|
||||
ref="editor"
|
||||
:value="value"
|
||||
@input="handleInput"
|
||||
language="markdown"
|
||||
:data-readonly="disabled"
|
||||
spellcheck="false"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import 'prismjs/components/prism-markdown';
|
||||
import CodeFlask from 'codeflask';
|
||||
import { colors } from '../constants';
|
||||
// import 'code-input'; // Import the web component
|
||||
// import 'prismjs/components/prism-markdown';
|
||||
import Prism from 'prismjs';
|
||||
|
||||
export default {
|
||||
props: {
|
||||
|
@ -17,63 +26,94 @@ export default {
|
|||
data() {
|
||||
return {
|
||||
data: '',
|
||||
flask: null,
|
||||
};
|
||||
},
|
||||
|
||||
methods: {
|
||||
initMarkdownEditor(body) {
|
||||
// CodeFlask editor is rendered in a shadow DOM tree to keep its styles
|
||||
// sandboxed away from the global styles.
|
||||
const el = document.createElement('code-flask');
|
||||
el.attachShadow({ mode: 'open' });
|
||||
handleInput(event) {
|
||||
this.$emit('input', event.target.value);
|
||||
},
|
||||
|
||||
el.shadowRoot.innerHTML = `
|
||||
<style>
|
||||
.codeflask .codeflask__flatten { font-size: 15px; }
|
||||
.codeflask .token.tag { font-weight: bold; color: ${colors.primary} !important; }
|
||||
.codeflask .token { color: ${colors.primary} !important; }
|
||||
.codeflask .token.heading { font-weight: bold; }
|
||||
.codeflask .token.important,.token.bold,.token.strong { font-weight: bold; }
|
||||
.codeflask .token.em,.token.italic { font-style: italic; }
|
||||
.codeflask .token.comment { color: slategray; }
|
||||
.codeflask .token.url { color: ${colors.primary}; text-decoration: underline; }
|
||||
</style>
|
||||
<div id="area"></area>
|
||||
`;
|
||||
this.$refs.markdownEditor.appendChild(el);
|
||||
initializeEditor() {
|
||||
// const textarea = this.$refs.editor;
|
||||
// textarea.setAttribute('is', 'code-input');
|
||||
// textarea.setAttribute('data-language', this.language);
|
||||
|
||||
this.flask = new CodeFlask(el.shadowRoot.getElementById('area'), {
|
||||
language: this.$props.language || 'markdown',
|
||||
lineNumbers: false,
|
||||
styleParent: el.shadowRoot,
|
||||
readonly: this.disabled,
|
||||
});
|
||||
|
||||
this.flask.onUpdate((v) => {
|
||||
this.data = v;
|
||||
this.$emit('input', v);
|
||||
});
|
||||
|
||||
// Set the initial value.
|
||||
this.flask.updateCode(body);
|
||||
|
||||
this.$nextTick(() => {
|
||||
document.querySelector('code-flask').shadowRoot.querySelector('textarea').focus();
|
||||
});
|
||||
// Register Prism for syntax highlighting if needed
|
||||
if (window.codeInput) {
|
||||
window.codeInput.registerTemplate(
|
||||
'syntax-highlighted',
|
||||
window.codeInput.templates.prism(Prism, []),
|
||||
);
|
||||
// window.codeInput.setDefaultTemplate('syntax-highlighted');
|
||||
}
|
||||
},
|
||||
},
|
||||
|
||||
mounted() {
|
||||
this.initMarkdownEditor(this.$props.value || '');
|
||||
this.initializeEditor();
|
||||
},
|
||||
|
||||
watch: {
|
||||
value(newVal) {
|
||||
if (newVal !== this.data) {
|
||||
this.flask.updateCode(newVal);
|
||||
this.data = newVal;
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.markdown-editor {
|
||||
width: 100%;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
/* Base editor styles */
|
||||
.markdown-editor textarea {
|
||||
font-size: 15px;
|
||||
min-height: 200px;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border: none;
|
||||
border-radius: 2px;
|
||||
padding: 8px;
|
||||
box-sizing: border-box; /* Keep padding within the width/height */
|
||||
resize: none; /* Optional: Prevent resizing */
|
||||
}
|
||||
|
||||
/* Markdown syntax highlighting */
|
||||
.markdown-editor .token {
|
||||
color: var(--primary-color, #0066cc);
|
||||
}
|
||||
|
||||
.markdown-editor .token.heading {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.markdown-editor .token.important,
|
||||
.markdown-editor .token.bold,
|
||||
.markdown-editor .token.strong {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.markdown-editor .token.em,
|
||||
.markdown-editor .token.italic {
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.markdown-editor .token.comment {
|
||||
color: slategray;
|
||||
}
|
||||
|
||||
.markdown-editor .token.url {
|
||||
color: var(--primary-color, #0066cc);
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
/* Focus state */
|
||||
.markdown-editor textarea:focus {
|
||||
outline: none;
|
||||
border-color: var(--primary-color, #0066cc);
|
||||
}
|
||||
</style>
|
||||
|
|
Loading…
Reference in a new issue