add custom theme to json editor

This commit is contained in:
Reorx 2023-02-02 17:54:06 +08:00
parent 5551ac6ced
commit 3c8ac17617
5 changed files with 165 additions and 6 deletions

72
editor/_json-editor.scss Normal file
View File

@ -0,0 +1,72 @@
.editor-container {
font-size: 14px;
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
--gap: 8px;
h1 {}
h2 {}
h3 {}
p {
margin: 0 0 var(--gap) 0;
}
input[type=text],
input[type=email] {
padding: 2px 4px;
}
textarea {
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
line-height: 1.3;
padding: var(--gap);
}
// override theme-default
.je-indented-panel {
padding-left: var(--gap);
margin-left: var(--gap);
border-left: 1px solid #ccc
}
.je-indented-panel--top {
padding-left: var(--gap);
margin-left: var(--gap);
}
.je-object__container {
}
.form-control {
margin-bottom: var(--gap);
}
.je-form-input-label {
display: block;
margin-bottom: calc(var(--gap) / 2);
font-weight: bold;
}
.je-form-input-description {
margin: 0;
font-size: 12px;
color: #999;
}
.je-child-editor-holder {
margin-bottom: var(--gap);
}
.je-header-button-holder {
display: inline-block;
margin-left: 10px;
font-size: 0.8em;
vertical-align: middle;
}
.je-table {
margin-bottom: 5px;
border-bottom: 1px solid #ccc;
}
.je-textarea {
height: 150px;
min-height: 150px;
max-height: 500px;
resize: vertical;
}
}

View File

@ -11,9 +11,9 @@
<h1>JSONCV Editor</h1> <h1>JSONCV Editor</h1>
<div id="main"> <div id="main">
<div class="left" id="editor-container"></div> <div class="left editor-container"></div>
<div class="right"> <div class="right">
<div id="editor-toc"></div> <div class="editor-toc"></div>
</div> </div>
</div> </div>

View File

@ -1,14 +1,17 @@
import objectPath from 'object-path';
import { JSONEditor } from '@json-editor/json-editor/dist/jsoneditor'; import { JSONEditor } from '@json-editor/json-editor/dist/jsoneditor';
import * as exampleData from '../sample.resume.json'; import * as exampleData from '../sample.resume.json';
import * as jsoncvSchema from '../schema/jsoncv.schema.json'; import * as jsoncvSchema from '../schema/jsoncv.schema.json';
import { registerTheme } from './theme';
import { createElement } from './utils'; import { createElement } from './utils';
const propertiesInOrder = ['basics', 'education', 'work', 'skills', 'projects', 'languages', 'interests', 'references', 'awards', 'publications', 'volunteer'] const propertiesInOrder = ['basics', 'education', 'work', 'skills', 'projects', 'languages', 'interests', 'references', 'awards', 'publications', 'volunteer']
const basicsPropertiesInOrder = ['name', 'label', 'email', 'phone', 'url', 'summary', 'image', 'location', 'profiles'] const basicsPropertiesInOrder = ['name', 'label', 'email', 'phone', 'url', 'summary', 'image', 'location', 'profiles']
// toc elements // toc elements
const elToc = document.querySelector('#editor-toc') const elToc = document.querySelector('.editor-toc')
const tocUl = createElement('ul', { const tocUl = createElement('ul', {
parent: elToc parent: elToc
}) })
@ -47,10 +50,20 @@ basicsPropertiesInOrder.forEach((name, index) => {
}) })
}) })
// add format to schema
const keyFormatMap = {
'basics.properties.summary': 'textarea',
}
for (const [key, format] of Object.entries(keyFormatMap)) {
objectPath.get(jsoncvSchema.properties, key).format = format
}
// initialize editor // initialize editor
const elEditorContainer = document.querySelector('#editor-container') registerTheme(JSONEditor)
const elEditorContainer = document.querySelector('.editor-container')
const editor = new JSONEditor(elEditorContainer, { const editor = new JSONEditor(elEditorContainer, {
schema: jsoncvSchema, schema: jsoncvSchema,
theme: 'mytheme',
}); });
editor.on('ready',() => { editor.on('ready',() => {
editor.setValue(exampleData) editor.setValue(exampleData)

View File

@ -1,21 +1,24 @@
@use 'json-editor';
#main { #main {
display: flex; display: flex;
.left { .left {
flex-grow: 1; flex-grow: 1;
padding-right: 16px;
} }
.right { .right {
width: 300px; width: 300px;
} }
} }
#editor-container { .editor-container {
[data-schemapath]:target { [data-schemapath]:target {
animation: bgFade 2s forwards; animation: bgFade 2s forwards;
} }
} }
#editor-toc { .editor-toc {
position: fixed; position: fixed;
} }

71
editor/theme.js Normal file
View File

@ -0,0 +1,71 @@
import { AbstractTheme } from '@json-editor/json-editor/src/theme.js';
export class MyTheme extends AbstractTheme {
getFormInputLabel (text, req) {
const el = super.getFormInputLabel(text, req)
el.classList.add('je-form-input-label')
return el
}
getFormInputDescription (text) {
const el = super.getFormInputDescription(text)
el.classList.add('je-form-input-description')
return el
}
getIndentedPanel () {
const el = super.getIndentedPanel()
el.classList.add('je-indented-panel')
return el
}
getTopIndentedPanel () {
return this.getIndentedPanel()
}
getChildEditorHolder () {
const el = super.getChildEditorHolder()
el.classList.add('je-child-editor-holder')
return el
}
getHeaderButtonHolder () {
const el = this.getButtonHolder()
el.classList.add('je-header-button-holder')
return el
}
getTable () {
const el = super.getTable()
el.classList.add('je-table')
return el
}
addInputError (input, text) {
const group = this.closest(input, '.form-control') || input.controlgroup
if (!input.errmsg) {
input.errmsg = document.createElement('div')
input.errmsg.setAttribute('class', 'errmsg')
input.errmsg.style = input.errmsg.style || {}
input.errmsg.style.color = 'red'
group.appendChild(input.errmsg)
} else {
input.errmsg.style.display = 'block'
}
input.errmsg.innerHTML = ''
input.errmsg.appendChild(document.createTextNode(text))
}
removeInputError (input) {
if (input.style) {
input.style.borderColor = ''
}
if (input.errmsg) input.errmsg.style.display = 'none'
}
}
export function registerTheme(JSONEditor) {
JSONEditor.defaults.themes['mytheme'] = MyTheme
}