diff --git a/editor/_json-editor.scss b/editor/_json-editor.scss
new file mode 100644
index 0000000..7a62f51
--- /dev/null
+++ b/editor/_json-editor.scss
@@ -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;
+ }
+}
diff --git a/editor/index.html b/editor/index.html
index 177fbf6..35c7cd8 100644
--- a/editor/index.html
+++ b/editor/index.html
@@ -11,9 +11,9 @@
JSONCV Editor
diff --git a/editor/main.js b/editor/main.js
index 9e113dc..6b43d1b 100644
--- a/editor/main.js
+++ b/editor/main.js
@@ -1,14 +1,17 @@
+import objectPath from 'object-path';
+
import { JSONEditor } from '@json-editor/json-editor/dist/jsoneditor';
import * as exampleData from '../sample.resume.json';
import * as jsoncvSchema from '../schema/jsoncv.schema.json';
+import { registerTheme } from './theme';
import { createElement } from './utils';
const propertiesInOrder = ['basics', 'education', 'work', 'skills', 'projects', 'languages', 'interests', 'references', 'awards', 'publications', 'volunteer']
const basicsPropertiesInOrder = ['name', 'label', 'email', 'phone', 'url', 'summary', 'image', 'location', 'profiles']
// toc elements
-const elToc = document.querySelector('#editor-toc')
+const elToc = document.querySelector('.editor-toc')
const tocUl = createElement('ul', {
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
-const elEditorContainer = document.querySelector('#editor-container')
+registerTheme(JSONEditor)
+const elEditorContainer = document.querySelector('.editor-container')
const editor = new JSONEditor(elEditorContainer, {
schema: jsoncvSchema,
+ theme: 'mytheme',
});
editor.on('ready',() => {
editor.setValue(exampleData)
diff --git a/editor/styles.scss b/editor/styles.scss
index ab45113..da39492 100644
--- a/editor/styles.scss
+++ b/editor/styles.scss
@@ -1,21 +1,24 @@
+@use 'json-editor';
+
#main {
display: flex;
.left {
flex-grow: 1;
+ padding-right: 16px;
}
.right {
width: 300px;
}
}
-#editor-container {
+.editor-container {
[data-schemapath]:target {
animation: bgFade 2s forwards;
}
}
-#editor-toc {
+.editor-toc {
position: fixed;
}
diff --git a/editor/theme.js b/editor/theme.js
new file mode 100644
index 0000000..8aa0385
--- /dev/null
+++ b/editor/theme.js
@@ -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
+}