Skip to content

Commit

Permalink
feat: add json-editor shortcode
Browse files Browse the repository at this point in the history
  • Loading branch information
jgazeau committed Aug 9, 2024
1 parent 727fa3a commit 0f15ea8
Show file tree
Hide file tree
Showing 28 changed files with 571 additions and 50 deletions.
12 changes: 12 additions & 0 deletions .bmycconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,18 @@
},
"currentVersion": "7.2.0"
},
{
"package": "json-editor",
"hold": false,
"name": "js/json-editor",
"localPath": "assets/js/external/json-editor/jsoneditor.min.js",
"assetManager": {
"name": "cdnjs",
"library": "json-editor",
"fileName": "jsoneditor.min.js"
},
"currentVersion": "2.15.1"
},
{
"package": "fontawesome",
"hold": false,
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/hugo.yml
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ jobs:
--gc \
--minify \
--source exampleSite \
--baseURL "${{ steps.pages.outputs.base_url }}/"
--baseURL "${{ steps.pages.outputs.base_url }}/shadocs/"
- name: Upload artifact
uses: actions/upload-pages-artifact@v3
with:
Expand Down
1 change: 1 addition & 0 deletions assets/js/external/json-editor/jsoneditor.min.js

Large diffs are not rendered by default.

102 changes: 102 additions & 0 deletions assets/js/shortcodes/jsoneditor.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
import {
getFirstAncestorByClass
} from '../theme/modules/helpers.min.js';

// VARS //
// MAIN //
document.addEventListener('DOMContentLoaded', function () {
renderAllJsoneditor();
});
function renderAllJsoneditor() {
let divj = document.getElementsByClassName('sc-jsoneditor-container');
for (let i = 0; i < divj.length; i++) {
renderJsoneditor(divj[i]);
}
}
function renderJsoneditor(jc) {
const jsoneditorActionWrapper = document.getElementById(jc.id + '-action-wrapper');
const jsoneditorCopy = document.getElementById(jc.id + '-copy');
const jsoneditorDownload = document.getElementById(jc.id + '-download');
const jsoneditorErrorId = jc.id + '-error';
const jsoneditorError = document.getElementById(jsoneditorErrorId);
if (jsoneditorError) {
jsoneditorError.remove();
}
const jsoneditorWrapper = getFirstAncestorByClass(jc, 'sc-jsoneditor-wrapper');
const jsoneditorPromise = new Promise((resolve) => resolve());
jsoneditorPromise
.then(() => {
return getJsonSchema(jc.getAttribute('jsoneditor-url'));
})
.then((schemaContent) => {
const schema = JSON.parse(schemaContent);
let jsoneditor = new JSONEditor(jc, {
array_controls_top: false,
disable_array_delete_all_rows: true,
disable_array_delete_last_row: true,
disable_collapse: false,
disable_edit_json: true,
disable_properties: true,
iconlib: 'fontawesome5',
prompt_before_delete: false,
remove_button_labels: true,
schema: schema,
theme: "barebones"
});
jsoneditorCopy.addEventListener('click', () => {
if (validateSchema(jsoneditor)) {
jsoneditorCopy.classList.toggle('sc-jsoneditor-success', true);
jsoneditorCopy.classList.toggle('sc-jsoneditor-error', false);
jsoneditorCopy.setAttribute('title-after', codeCopyAfter)
navigator.clipboard.writeText(JSON.stringify(jsoneditor.getValue(), null, 2));
} else {
jsoneditorCopy.classList.toggle('sc-jsoneditor-success', false);
jsoneditorCopy.classList.toggle('sc-jsoneditor-error', true);
jsoneditorCopy.setAttribute('title-after', jsoneditorValidateError)
}
});
jsoneditorDownload.addEventListener('click', () => {
if (validateSchema(jsoneditor)) {
URL.revokeObjectURL(jsoneditorDownload.href);
jsoneditorDownload.href = URL.createObjectURL(new Blob([JSON.stringify(jsoneditor.getValue(), null, 2)], { type: 'application/json' }));
jsoneditorDownload.download = schema.title + '.json';
} else {
jsoneditorDownload.classList.toggle('sc-jsoneditor-success', false);
jsoneditorDownload.classList.toggle('sc-jsoneditor-error', true);
jsoneditorDownload.setAttribute('title-after', jsoneditorValidateError)
}
});
jsoneditorWrapper.classList.toggle('is-loading', false);
})
.catch((error) => {
const ed = document.createElement('div');
ed.classList.add('sc-alert', 'sc-alert-error');
ed.innerHTML = error;
ed.id = jsoneditorErrorId;
while (jc.lastChild) {
jc.removeChild(jc.lastChild);
}
jsoneditorWrapper.classList.toggle('is-loading', false);
jsoneditorWrapper.insertAdjacentElement('afterbegin', ed);
jsoneditorActionWrapper.classList.toggle('is-hidden', true);
jc.classList.toggle('is-hidden', true);
});
}
function getJsonSchema(url) {
const xhr = new XMLHttpRequest();
xhr.open('GET', url, false);
xhr.send(null);
if (xhr.status === 200) {
return xhr.responseText;
} else {
throw new Error(`Error getting content at ${url} ${xhr.status} ${xhr.statusText}`);
}
}
function validateSchema(jsoneditor) {
const errors = jsoneditor.validate();
if (errors.length) {
return false;
} else {
return true;
}
}
5 changes: 2 additions & 3 deletions assets/sass/theme/global.sass
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,10 @@
//
body
+responsive-size(font-size, $content-font-size, 3px)
+static-size-height(100%)
+static-size-width(100%)
+static-size-height(100vh)
+static-size-width(100vw)
+font-family(lato)
flex-flow: column
position: fixed
display: flex
section
+static-size-height(100%)
Expand Down
1 change: 1 addition & 0 deletions assets/sass/theme/main.sass
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
@import "shortcodes_collapsible";
@import "shortcodes_highcharts";
@import "shortcodes_intro";
@import "shortcodes_jsoneditor";
@import "shortcodes_openapi";
@import "shortcodes_pagebreak";
@import "shortcodes_snippet";
Expand Down
154 changes: 154 additions & 0 deletions assets/sass/theme/shortcodes_jsoneditor.sass
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
//
// Treeview
//
.sc-jsoneditor-container
border: 1px solid smooth-color($content-background, 30)
background: smooth-color($content-background, 10)
padding: $theme-gap-medium-size
color: $content-writing-color
+font-family(roboto-mono)
.je-indented-panel
border: 1px solid smooth-color($content-background, 20)
padding: $theme-gap-medium-size
margin: 0
.row
padding: $theme-gap-medium-size
&:not(:has(.je-indented-panel))
&:focus-within,
&:hover
background: smooth-color($content-background, 15)
div[data-schematype="object"].je-object__container
>.je-indented-panel
padding: 0
div[data-schematype="array"]
>.je-indented-panel
div[data-schematype].je-indented-panel
&:focus-within,
&:hover
background: smooth-color($content-background, 15)
>div
>div[data-schematype]+div[data-schematype]
margin: $theme-gap-medium-size 0
>div[data-schematype]:first-child
margin-bottom: $theme-gap-medium-size
div:has(span>button.json-editor-btntype-delete),
div:has(span>button.json-editor-btntype-move)
position: relative
>span
&:has(button.json-editor-btntype-delete)
&:has(button.json-editor-btntype-move)
justify-content: space-between
flex-direction: row
position: absolute
flex-wrap: nowrap
display: flex
right: 0
top: 0
div[data-schematype="object"]>span
&:has(button.json-editor-btntype-delete),
&:has(button.json-editor-btntype-move)
button
margin-left: $theme-gap-small-size
.je-indented-panel>span
&:has(button.json-editor-btntype-delete),
&:has(button.json-editor-btntype-move)
margin: $theme-gap-medium-size $theme-gap-small-size
button
margin-right: $theme-gap-small-size
.je-header
font-weight: bold
button
border: 1px solid smooth-color($json-editor-color, 25)
padding: $theme-gap-small-size $theme-gap-medium-size
color: findColorInvert($json-editor-color)
background: $json-editor-color
&:before
padding-right: $theme-gap-medium-size
font: var(--fa-font-solid)
content: "\f550"
&:hover
background: smooth-color($json-editor-color, 20)
cursor: pointer
&.je-object__title
button:before
content: "\f1b2"
.json-editor-btn-add
border: 1px solid smooth-color($json-editor-add-color, 25)
color: findColorInvert($json-editor-add-color)
background: $json-editor-add-color
&:hover
background: smooth-color($json-editor-add-color, 15)
cursor: pointer
.json-editor-btntype-delete
border: 1px solid smooth-color($json-editor-delete-color, 25)
color: findColorInvert($json-editor-delete-color)
background: $json-editor-delete-color
&:hover
background: smooth-color($json-editor-delete-color, 15)
cursor: pointer
.json-editor-btntype-move
border: 1px solid smooth-color($json-editor-move-color, 25)
color: findColorInvert($json-editor-move-color)
background: $json-editor-move-color
&:hover
background: smooth-color($json-editor-move-color, 15)
cursor: pointer
.form-control
label
&:after
content: ":"
input
width: 100%
.errmsg
font-style: italic
color: red
input,
select
border: 1px solid smooth-color($content-background, 25)
background: $content-background
color: $content-writing-color
+static-size-width(100%)
box-shadow: unset
outline: unset
margin: 0
&:hover,
&:focus,
&:focus-visible,
border: 1px solid smooth-color($content-background, 50)
.sc-jsoneditor-action-wrapper
padding: $theme-gap-medium-size
justify-content: center
flex-direction: row
flex-wrap: nowrap
display: flex
.is-action-button
position: relative
&.sc-jsoneditor-copy-button:after
right: 100%
&.sc-jsoneditor-download-button:after
left: 100%
&.sc-jsoneditor-success:after
color: $json-editor-success-color
&.sc-jsoneditor-error:after
color: $json-editor-error-color
&:after
+responsive-size(font-size, $theme-font-medium-size, 3px)
height: $theme-gap-extra-large-size
padding: $theme-gap-medium-size
content: attr(title-after)
+font-family(roboto-mono)
text-overflow: ellipsis
white-space: nowrap
align-items: center
transform: scale(0)
max-width: inherit
position: absolute
overflow: hidden
display: inline
opacity: 0
&:not(:active):after
transition: transform 1.5s step-end
animation: copied 1.5s ease-in-out
&:active:after
transition: transform 1.5s step-start
transform: scale(1)
6 changes: 6 additions & 0 deletions assets/sass/theme/variables.sass
Original file line number Diff line number Diff line change
Expand Up @@ -77,5 +77,11 @@ $intro-progressbar-color: mediumseagreen
$intro-skipbutton-color: firebrick
$intro-tooltip-min-width: 250px
$intro-tooltip-max-width: 350px
$json-editor-color: steelblue
$json-editor-add-color: darkgreen
$json-editor-delete-color: darkred
$json-editor-move-color: steelblue
$json-editor-success-color: darkgreen
$json-editor-error-color: darkred
$mermaid-label-font-size: 0.875rem
$treeview-icon-color: darkgreen
2 changes: 2 additions & 0 deletions cypress.config.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
const { defineConfig } = require('cypress');

module.exports = defineConfig({
chromeWebSecurity: false,
e2e: {
baseUrl: 'http://localhost:1313/',
},
Expand Down Expand Up @@ -29,6 +30,7 @@ module.exports = defineConfig({
SC_COLLAPSIBLE_PATH: 'collapsible/',
SC_HIGHCHARTS_PATH: 'highcharts/',
SC_INTRO_PATH: 'intro/',
SC_JSONEDITOR_PATH: 'jsoneditor/',
SC_OPENAPI_PATH: 'openapi/',
SC_PAGEBREAK_PATH: 'pagebreak/',
SC_PARAMETER_PATH: 'parameter/',
Expand Down
3 changes: 0 additions & 3 deletions cypress/e2e/global/mermaidTests.cy.js
Original file line number Diff line number Diff line change
Expand Up @@ -48,9 +48,6 @@ describe('for: mermaid', () => {
}
);
});
// For now local download is not fully supported in firefox browser.
// Cypress doesn't seems to accept browser preferences in headless mode.
// https://github.com/cypress-io/cypress/issues/8814
it('export button should export mermaid', { browser: '!firefox' }, () => {
const path = require('path');
cy.get('#content .sc-mermaid-wrapper.helper-loading-container').each(
Expand Down
3 changes: 2 additions & 1 deletion cypress/e2e/shortcodes/alertTests.cy.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@ describe('for: alert shortcode', () => {
});
it('alerts should be visible', () => {
cy.get('#content .sc-alert').each(($elem) => {
cy.get($elem).scrollIntoView().should('be.visible');
cy.get('#contentContainer').scrollTo(0, $elem[0].getBoundingClientRect().top,{ensureScrollable: false});
cy.get($elem).should('be.visible');
});
});
});
Loading

0 comments on commit 0f15ea8

Please sign in to comment.