Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/json editor #250

Merged
merged 2 commits into from
Aug 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
52 changes: 0 additions & 52 deletions assets/js/external/asyncapi-web-component.js

This file was deleted.

1 change: 1 addition & 0 deletions assets/js/external/json-editor/jsoneditor.min.js

Large diffs are not rendered by default.

110 changes: 110 additions & 0 deletions assets/js/shortcodes/jsoneditor.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
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);
const jsonPostProcessFunction = jc.getAttribute('post-process-function');
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(maybePostProcessJson(jsonPostProcessFunction, 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(maybePostProcessJson(jsonPostProcessFunction, 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;
}
}
function maybePostProcessJson(jsonPostProcessFunction, json) {
if (typeof window[jsonPostProcessFunction] === 'function') {
return window[jsonPostProcessFunction](json);
} else {
return json;
}
}
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import {
addFunctionToResizeEvent,
getFirstAncestorByClass,
} from '../../theme/modules/helpers.min.js';
} from '../theme/modules/helpers.min.js';

// VARS //
window.noZensmooth = true;
// MAIN //
document.addEventListener('DOMContentLoaded', function () {
renderAllOpenAPI();
Expand Down
1 change: 0 additions & 1 deletion assets/js/shortcodes/openapi/openapi.js

This file was deleted.

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');
});
});
});
16 changes: 6 additions & 10 deletions cypress/e2e/shortcodes/asyncapiTests.cy.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,10 @@ describe('for: asyncapi shortcode', () => {
'helper-loading-container'
);
});
it(
'asyncapi should not have a loading helper once loaded',
{ defaultCommandTimeout: 10000 },
() => {
cy.get('#content .sc-asyncapi-wrapper.helper-loading-container').should(
'not.have.class',
'is-loading'
);
}
);
it('asyncapi should not have a loading helper once loaded', { defaultCommandTimeout: 10000 }, () => {
cy.get('#content .sc-asyncapi-wrapper.helper-loading-container').should(
'not.have.class',
'is-loading'
);
});
});
Loading