diff --git a/.vscode/settings.json b/.vscode/settings.json index dc1a054c6c..75e3a44780 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -8,7 +8,7 @@ "vue" ], "editor.codeActionsOnSave": { - "source.fixAll.eslint": true + "source.fixAll.eslint": "explicit" }, "i18n-ally.localesPaths": [ "server/locales" diff --git a/client/components/editor/editor-asciidoc.vue b/client/components/editor/editor-asciidoc.vue index 296b2414b9..8a134c1068 100644 --- a/client/components/editor/editor-asciidoc.vue +++ b/client/components/editor/editor-asciidoc.vue @@ -51,12 +51,17 @@ v-list-item(@click='insertBeforeEachLine({ content: `NOTE: `})') v-list-item-action v-icon(color='blue') mdi-alpha-n-box-outline - v-list-item-title {{'Note blockquote'}} + v-list-item-title {{'Note Blockquote'}} + v-divider + v-list-item(@click='insertBeforeEachLine({ content: `[SUCCESS]\n`})') + v-list-item-action + v-icon(color='success') mdi-alpha-s-box-outline + v-list-item-title {{'Success Blockquote'}} v-divider v-list-item(@click='insertBeforeEachLine({ content: `TIP: `})') v-list-item-action v-icon(color='success') mdi-alpha-t-box-outline - v-list-item-title {{'Tip blockquote'}} + v-list-item-title {{'Tip Blockquote'}} v-divider v-list-item(@click='insertBeforeEachLine({ content: `WARNING: `})') v-list-item-action @@ -66,11 +71,12 @@ v-list-item(@click='insertBeforeEachLine({ content: `CAUTION: `})') v-list-item-action v-icon(color='purple') mdi-alpha-c-box-outline - v-list-item-title {{'Caution blockquote'}} + v-list-item-title {{'Caution Blockquote'}} + v-divider v-list-item(@click='insertBeforeEachLine({ content: `IMPORTANT: `})') v-list-item-action v-icon(color='error') mdi-alpha-i-box-outline - v-list-item-title {{'Important blockquote'}} + v-list-item-title {{'Important Blockquote'}} v-divider template(v-if='$vuetify.breakpoint.mdAndUp') v-spacer @@ -157,6 +163,8 @@ import cmFold from './common/cmFold' // INIT // ======================================== const asciidoctor = require('asciidoctor')() +const registry = asciidoctor.Extensions.create() +require('../../modules/asciidoc-extended')(registry) const cheerio = require('cheerio') // Platform detection @@ -216,7 +224,8 @@ export default { attributes: { showtitle: true, icons: 'font' - } + }, + 'extension_registry': registry }) const $ = cheerio.load(html, { decodeEntities: true diff --git a/client/components/editor/editor-markdown.vue b/client/components/editor/editor-markdown.vue index 4ca6e192c5..32071f87fc 100644 --- a/client/components/editor/editor-markdown.vue +++ b/client/components/editor/editor-markdown.vue @@ -63,11 +63,21 @@ v-icon(color='success') mdi-alpha-s-box-outline v-list-item-title {{$t('editor:markup.blockquoteSuccess')}} v-divider + v-list-item(@click='insertBeforeEachLine({ content: `> `, after: `{.is-tip}`})') + v-list-item-action + v-icon(color='success') mdi-alpha-t-box-outline + v-list-item-title {{'Tip Blockquote'}} + v-divider v-list-item(@click='insertBeforeEachLine({ content: `> `, after: `{.is-warning}`})') v-list-item-action v-icon(color='warning') mdi-alpha-w-box-outline v-list-item-title {{$t('editor:markup.blockquoteWarning')}} v-divider + v-list-item(@click='insertBeforeEachLine({ content: `> `, after: `{.is-caution}`})') + v-list-item-action + v-icon(color='purple') mdi-alpha-c-box-outline + v-list-item-title {{'Caution Blockquote'}} + v-divider v-list-item(@click='insertBeforeEachLine({ content: `> `, after: `{.is-danger}`})') v-list-item-action v-icon(color='error') mdi-alpha-e-box-outline diff --git a/client/modules/asciidoc-extended.js b/client/modules/asciidoc-extended.js new file mode 100644 index 0000000000..2a2aa84d57 --- /dev/null +++ b/client/modules/asciidoc-extended.js @@ -0,0 +1,17 @@ +// Asciidoctor API Documentation for HTML5Converter: +// https://www.rubydoc.info/gems/asciidoctor/2.0.23/Asciidoctor/Converter/Html5Converter#convert_admonition-instance_method + +module.exports = function (registry) { + // Success Admonition block rendering + // [SUCCESS] + // + registry.block(function () { + var self = this + self.named('SUCCESS') + self.onContext('paragraph') + self.process(function (parent, reader) { + var lines = reader.getLines() + return self.createBlock(parent, 'admonition', lines, {name: 'success', textlabel: 'Success'}) + }) + }) +} diff --git a/client/themes/default/scss/app.scss b/client/themes/default/scss/app.scss index c01faf1245..2f503ea9e1 100644 --- a/client/themes/default/scss/app.scss +++ b/client/themes/default/scss/app.scss @@ -242,9 +242,9 @@ } blockquote { - padding: 0 1rem 1rem 1rem; + padding: 0 1rem 0.8rem 1rem; background-color: mc('blue-grey', '50'); - border-left: 55px solid mc('blue-grey', '500'); + border-left: 52px solid mc('blue-grey', '500'); border-radius: .5rem; margin: 1rem 0; position: relative; @@ -255,12 +255,12 @@ &::before { display: inline-block; - font: normal normal normal 24px/1 "Material Design Icons", sans-serif; + font: normal normal normal 28px/1 "Material Design Icons", sans-serif; position: absolute; margin-top: -12px; top: 50%; - left: -38px; - color: rgba(255, 255, 255, .7); + left: -39px; + color: rgba(255, 255, 255, 0.85); content: "\F0757"; } @@ -354,6 +354,46 @@ border-color: mc('green', '500'); } } + &.is-tip { + background-color: mc('green', '50'); + border-color: mc('green', '300'); + color: mc('green', '900'); + + &::before { + content: "\F0335"; + } + + code:not([class^="language-"]) { + background-color: mc('green', '50'); + color: mc('green', '800'); + } + + @at-root .theme--dark & { + background-color: mc('green', '900'); + color: mc('green', '50'); + border-color: mc('green', '500'); + } + } + &.is-caution { + background-color: mc('purple', '50'); + border-color: mc('purple', '300'); + color: mc('purple', '900'); + + &::before { + content: "\f0238"; + } + + code:not([class^="language-"]) { + background-color: mc('purple', '50'); + color: mc('purple', '800'); + } + + @at-root .theme--dark & { + background-color: mc('purple', '900'); + color: mc('purple', '50'); + border-color: mc('purple', '500'); + } + } } // --------------------------------- @@ -378,7 +418,7 @@ &::before { display: inline-block; - font: normal normal normal 24px/1 "Material Design Icons", sans-serif !important; + font: normal normal normal 28px/1 "Material Design Icons", sans-serif !important; } } @@ -388,6 +428,8 @@ } &.note { + background-color: transparent !important; + td.icon { background-color: mc('blue', '300'); color: mc('blue', '50'); @@ -405,7 +447,30 @@ } } } + + &.success { + background-color: transparent !important; + + td.icon { + background-color: mc('green', '300'); + color: mc('green', '50'); + &::before { + content: "\F0E1E"; + } + } + td.content { + color: darken(mc('green', '900'), 10%); + background-color: mc('green', '50'); + + @at-root .theme--dark & { + background-color: mc('green', '900'); + color: mc('green', '50'); + } + } + } + &.tip { + background-color: transparent !important; td.icon { background-color: mc('green', '300'); color: mc('green', '50'); @@ -423,6 +488,7 @@ } } } + &.warning { background-color: transparent !important; @@ -443,7 +509,10 @@ } } } + &.caution { + background-color: transparent !important; + td.icon { background-color: mc('purple', '300'); color: mc('purple', '50'); @@ -461,7 +530,10 @@ } } } + &.important { + background-color: transparent !important; + td.icon { background-color: mc('red', '300'); color: mc('red', '50'); @@ -685,7 +757,7 @@ display:inline-block; vertical-align:top; padding-top:0; - + &:first-child { width: 100%; } diff --git a/server/modules/rendering/asciidoc-core/renderer.js b/server/modules/rendering/asciidoc-core/renderer.js index e37217d875..d5824c6f4c 100644 --- a/server/modules/rendering/asciidoc-core/renderer.js +++ b/server/modules/rendering/asciidoc-core/renderer.js @@ -1,4 +1,6 @@ const asciidoctor = require('asciidoctor')() +const registry = asciidoctor.Extensions.create() +require('../../../../client/modules/asciidoc-extended')(registry) const cheerio = require('cheerio') module.exports = { @@ -9,7 +11,8 @@ module.exports = { attributes: { showtitle: true, icons: 'font' - } + }, + 'extension_registry': registry }) const $ = cheerio.load(html, {