diff --git a/client/components/admin/admin-comments.vue b/client/components/admin/admin-comments.vue index 75698d03..364cfeb7 100644 --- a/client/components/admin/admin-comments.vue +++ b/client/components/admin/admin-comments.vue @@ -17,7 +17,7 @@ v-flex(lg3, xs12) v-card.animated.fadeInUp v-toolbar(flat, color='primary', dark, dense) - .subtitle-1 {{$t('admin:comments.providers')}} + .subtitle-1 {{$t('admin:comments.provider')}} v-list.py-0(two-line, dense) template(v-for='(provider, idx) in providers') v-list-item(:key='provider.key', @click='selectedProvider = provider.key', :disabled='!provider.isAvailable') @@ -127,7 +127,20 @@ export default { this.$store.commit(`loadingStart`, 'admin-comments-saveproviders') try { const resp = await this.$apollo.mutate({ - mutation: gql``, + mutation: gql` + mutation($providers: [CommentProviderInput]!) { + comments { + updateProviders(providers: $providers) { + responseResult { + succeeded + errorCode + slug + message + } + } + } + } + `, variables: { providers: this.providers.map(tgt => ({ isEnabled: tgt.key === this.selectedProvider, @@ -136,19 +149,19 @@ export default { })) } }) - if (_.get(resp, 'data.comments.updateEngines.responseResult.succeeded', false)) { + if (_.get(resp, 'data.comments.updateProviders.responseResult.succeeded', false)) { this.$store.commit('showNotification', { message: this.$t('admin:comments.configSaveSuccess'), style: 'success', icon: 'check' }) } else { - throw new Error(_.get(resp, 'data.comments.updateEngines.responseResult.message', this.$t('common:error.unexpected'))) + throw new Error(_.get(resp, 'data.comments.updateProviders.responseResult.message', this.$t('common:error.unexpected'))) } } catch (err) { this.$store.commit('pushGraphError', err) } - this.$store.commit(`loadingStop`, 'admin-comments-saveengines') + this.$store.commit(`loadingStop`, 'admin-comments-saveproviders') } }, apollo: { diff --git a/client/components/admin/admin-extensions.vue b/client/components/admin/admin-extensions.vue index 1d4ef9c2..bb958576 100644 --- a/client/components/admin/admin-extensions.vue +++ b/client/components/admin/admin-extensions.vue @@ -20,7 +20,7 @@ v-chip(label, color='success', small, v-if='ext.installed') Installed v-chip(label, color='warning', small, v-else) Not Installed v-expansion-panel-content.pa-0 - v-card.grey.lighten-5.radius-7(flat) + v-card(flat, :class='$vuetify.theme.dark ? `grey darken-3` : `grey lighten-5`', tile) v-card-text .body-2 {{ext.description}} v-divider.my-4 diff --git a/client/components/admin/admin-general.vue b/client/components/admin/admin-general.vue index d66823cd..52f3cde5 100644 --- a/client/components/admin/admin-general.vue +++ b/client/components/admin/admin-general.vue @@ -146,7 +146,7 @@ //- v-divider.mt-3 v-switch( inset - label='Page Comments' + label='Comments' color='indigo' v-model='config.featurePageComments' persistent-hint diff --git a/client/components/editor/editor-markdown.vue b/client/components/editor/editor-markdown.vue index d6be7625..142bfe7c 100644 --- a/client/components/editor/editor-markdown.vue +++ b/client/components/editor/editor-markdown.vue @@ -341,7 +341,7 @@ md.renderer.rules.katex_block = (tokens, idx) => { md.renderer.rules.emoji = (token, idx) => { return twemoji.parse(token[idx].content, { callback (icon, opts) { - return `/svg/twemoji/${icon}.svg` + return `/_assets/svg/twemoji/${icon}.svg` } }) } diff --git a/client/themes/default/components/page.vue b/client/themes/default/components/page.vue index d92c374a..99406f3c 100644 --- a/client/themes/default/components/page.vue +++ b/client/themes/default/components/page.vue @@ -90,12 +90,13 @@ ) v-icon(:color='$vuetify.theme.dark ? `teal lighten-3` : `teal`', size='20') mdi-tag-multiple - v-card.mb-5 + v-card.mb-5(v-if='commentsEnabled') .pa-5 .overline.pb-2.pink--text.d-flex.align-center(:class='$vuetify.theme.dark ? `text--lighten-3` : `text--darken-4`') span Talk v-spacer v-chip.text-center( + v-if='!commentsExternal' label x-small :color='$vuetify.theme.dark ? `pink darken-3` : `pink darken-4`' @@ -260,6 +261,8 @@ span {{$t('common:page.editPage')}} .contents(ref='container') slot(name='contents') + .comments-container#discussion + slot(name='comments') nav-footer notify search-results @@ -390,6 +393,18 @@ export default { navMode: { type: String, default: 'MIXED' + }, + commentsEnabled: { + type: Boolean, + default: false + }, + commentsProvider: { + type: String, + default: 'default' + }, + commentsExternal: { + type: Boolean, + default: false } }, data() { diff --git a/client/themes/default/scss/app.scss b/client/themes/default/scss/app.scss index cc8c0471..4e8ee199 100644 --- a/client/themes/default/scss/app.scss +++ b/client/themes/default/scss/app.scss @@ -805,6 +805,16 @@ } +.comments-container { + background-color: mc('blue-grey', '50'); + border-radius: 7px; + padding: 20px; + + @at-root .theme--dark & { + background-color: darken(mc('grey', '900'), 5%); + } +} + // --------------- // RTL FIXES // Vuetify GH Issue: https://github.com/vuetifyjs/vuetify/issues/6317 diff --git a/package.json b/package.json index 7ec3e7b1..c4f432db 100644 --- a/package.json +++ b/package.json @@ -37,7 +37,7 @@ "dependencies": { "@aoberoi/passport-slack": "1.0.5", "@azure/storage-blob": "12.1.1", - "@bugsnag/js": "7.0.0", + "@bugsnag/js": "7.0.2", "@exlinc/keycloak-passport": "1.0.2", "@root/csr": "0.8.1", "@root/keypairs": "0.9.0", @@ -45,10 +45,10 @@ "acme": "3.0.3", "algoliasearch": "4.2.0", "apollo-fetch": "0.7.0", - "apollo-server": "2.12.0", - "apollo-server-express": "2.12.0", + "apollo-server": "2.13.1", + "apollo-server-express": "2.13.1", "auto-load": "3.0.4", - "aws-sdk": "2.663.0", + "aws-sdk": "2.678.0", "azure-search-client": "3.1.5", "bcryptjs-then": "1.0.1", "bluebird": "3.7.2", @@ -61,20 +61,20 @@ "connect-session-knex": "1.6.0", "cookie-parser": "1.4.5", "cors": "2.8.5", - "custom-error-instance": "2.1.1", + "custom-error-instance": "2.1.2", "dependency-graph": "0.9.0", "diff": "4.0.2", - "diff2html": "3.1.6", - "dompurify": "2.0.10", + "diff2html": "3.1.7", + "dompurify": "2.0.11", "dotize": "0.3.0", "elasticsearch6": "npm:@elastic/elasticsearch@6", "elasticsearch7": "npm:@elastic/elasticsearch@7", "emoji-regex": "9.0.0", - "eventemitter2": "6.3.1", + "eventemitter2": "6.4.0", "express": "4.17.1", "express-brute": "1.0.1", "express-session": "1.17.1", - "file-type": "14.2.0", + "file-type": "14.4.0", "filesize": "6.1.0", "fs-extra": "9.0.0", "getos": "3.2.0", @@ -84,8 +84,8 @@ "graphql-subscriptions": "1.1.0", "graphql-tools": "4.0.7", "he": "1.2.0", - "highlight.js": "10.0.0", - "i18next": "19.4.3", + "highlight.js": "10.0.3", + "i18next": "19.4.4", "i18next-express-middleware": "2.0.0", "i18next-node-fs-backend": "2.1.3", "image-size": "0.8.3", @@ -96,7 +96,7 @@ "jsonwebtoken": "8.5.1", "katex": "0.11.1", "klaw": "3.0.0", - "knex": "0.21.0", + "knex": "0.21.1", "lodash": "4.17.15", "markdown-it": "10.0.0", "markdown-it-abbr": "1.0.4", @@ -113,14 +113,14 @@ "markdown-it-task-lists": "2.1.1", "mathjax": "3.0.5", "mime-types": "2.1.27", - "moment": "2.24.0", - "moment-timezone": "0.5.28", - "mongodb": "3.5.6", + "moment": "2.25.3", + "moment-timezone": "0.5.29", + "mongodb": "3.5.7", "ms": "2.1.2", "mssql": "6.2.0", "multer": "1.4.2", "mysql2": "2.1.0", - "nanoid": "3.1.3", + "nanoid": "3.1.8", "node-2fa": "1.1.2", "node-cache": "5.1.0", "nodemailer": "6.4.6", @@ -145,10 +145,10 @@ "passport-saml": "1.3.3", "passport-twitch-oauth": "1.0.0", "pem-jwk": "2.0.0", - "pg": "8.0.3", + "pg": "8.2.1", "pg-hstore": "2.3.3", "pg-pubsub": "0.5.0", - "pg-query-stream": "3.0.7", + "pg-query-stream": "3.1.1", "pg-tsquery": "8.1.0", "pug": "2.0.4", "punycode": "2.1.1", @@ -163,17 +163,17 @@ "semver": "7.3.2", "serve-favicon": "2.5.0", "sharp": "0.25.2", - "simple-git": "1.132.0", + "simple-git": "2.4.0", "solr-node": "1.2.1", - "sqlite3": "4.1.1", + "sqlite3": "4.2.0", "ssh2": "0.8.9", - "ssh2-promise": "0.1.6", + "ssh2-promise": "0.1.7", "striptags": "3.1.1", "subscriptions-transport-ws": "0.9.16", - "tar-fs": "2.0.1", - "twemoji": "12.1.5", + "tar-fs": "2.1.0", + "twemoji": "13.0.0", "uslug": "1.0.4", - "uuid": "7.0.3", + "uuid": "8.0.0", "validate.js": "0.13.1", "winston": "3.2.1", "xss": "1.0.6", @@ -181,7 +181,7 @@ }, "devDependencies": { "@babel/cli": "^7.8.4", - "@babel/core": "^7.9.0", + "@babel/core": "^7.9.6", "@babel/plugin-proposal-class-properties": "^7.8.3", "@babel/plugin-proposal-decorators": "^7.8.3", "@babel/plugin-proposal-export-namespace-from": "^7.8.3", @@ -192,25 +192,25 @@ "@babel/plugin-syntax-dynamic-import": "^7.8.3", "@babel/plugin-syntax-import-meta": "^7.8.3", "@babel/polyfill": "^7.8.7", - "@babel/preset-env": "^7.9.5", - "@mdi/font": "5.1.45", + "@babel/preset-env": "^7.9.6", + "@mdi/font": "5.2.45", "@panter/vue-i18next": "0.15.2", "@requarks/ckeditor5": "12.4.0-wiki.16", "@vue/babel-preset-app": "4.3.1", "animate-sass": "0.8.2", "animated-number-vue": "1.0.0", - "apollo-cache-inmemory": "1.6.5", - "apollo-client": "2.6.8", + "apollo-cache-inmemory": "1.6.6", + "apollo-client": "2.6.10", "apollo-link": "1.2.14", "apollo-link-batch-http": "1.2.14", "apollo-link-error": "1.1.13", "apollo-link-http": "1.5.17", "apollo-link-persisted-queries": "0.2.2", "apollo-link-ws": "1.0.20", - "apollo-utilities": "1.3.3", + "apollo-utilities": "1.3.4", "autoprefixer": "9.7.6", "babel-eslint": "10.1.0", - "babel-jest": "25.4.0", + "babel-jest": "26.0.1", "babel-loader": "^8.1.0", "babel-plugin-graphql-tag": "2.5.0", "babel-plugin-lodash": "3.3.4", @@ -228,7 +228,7 @@ "d3": "5.16.0", "duplicate-package-checker-webpack-plugin": "3.0.0", "epic-spinners": "1.1.0", - "eslint": "6.8.0", + "eslint": "7.0.0", "eslint-config-requarks": "1.0.7", "eslint-config-standard": "14.1.1", "eslint-plugin-import": "2.20.2", @@ -238,19 +238,19 @@ "eslint-plugin-vue": "6.2.2", "fibers": "5.0.0", "file-loader": "6.0.0", - "filepond": "4.13.4", + "filepond": "4.13.6", "filepond-plugin-file-validate-type": "1.2.5", "filesize.js": "2.0.0", "graphql-persisted-document-loader": "2.0.0", "graphql-tag": "^2.10.3", "hammerjs": "2.0.8", - "html-webpack-plugin": "4.2.0", + "html-webpack-plugin": "4.3.0", "html-webpack-pug-plugin": "2.0.0", "i18next-chained-backend": "2.0.1", "i18next-localstorage-backend": "3.1.1", "i18next-xhr-backend": "3.2.2", "ignore-loader": "0.1.2", - "jest": "25.4.0", + "jest": "26.0.1", "js-beautify": "1.11.0", "js-cookie": "2.2.1", "mermaid": "8.5.0", @@ -261,7 +261,7 @@ "optimize-css-assets-webpack-plugin": "5.0.3", "pako": "1.0.11", "postcss-cssnext": "3.1.0", - "postcss-flexbugs-fixes": "4.2.0", + "postcss-flexbugs-fixes": "4.2.1", "postcss-flexibility": "2.0.0", "postcss-import": "12.0.1", "postcss-loader": "3.0.0", @@ -278,8 +278,8 @@ "sass-resources-loader": "2.0.3", "script-ext-html-webpack-plugin": "2.1.4", "simple-progress-webpack-plugin": "1.1.2", - "style-loader": "1.2.0", - "terser": "4.6.12", + "style-loader": "1.2.1", + "terser": "4.6.13", "twemoji-awesome": "1.0.6", "url-loader": "4.1.0", "velocity-animate": "1.5.2", @@ -290,7 +290,7 @@ "vue-clipboards": "1.3.0", "vue-filepond": "6.0.2", "vue-hot-reload-api": "2.3.4", - "vue-loader": "15.9.1", + "vue-loader": "15.9.2", "vue-moment": "4.1.0", "vue-router": "3.1.6", "vue-status-indicator": "1.2.1", @@ -298,9 +298,9 @@ "vue2-animate": "2.1.3", "vuedraggable": "2.23.2", "vuescroll": "4.15.0", - "vuetify": "2.2.25", + "vuetify": "2.2.28", "vuetify-loader": "1.4.3", - "vuex": "3.3.0", + "vuex": "3.4.0", "vuex-pathify": "1.4.1", "vuex-persistedstate": "3.0.1", "webpack": "4.43.0", @@ -309,11 +309,11 @@ "webpack-dev-middleware": "3.7.2", "webpack-hot-middleware": "2.25.0", "webpack-merge": "4.2.2", - "webpack-subresource-integrity": "1.4.0", + "webpack-subresource-integrity": "1.4.1", "webpackbar": "4.0.0", "whatwg-fetch": "3.0.0", "write-file-webpack-plugin": "4.5.1", - "xterm": "4.5.0", + "xterm": "4.6.0", "zxcvbn": "4.4.2" }, "browserslist": [ diff --git a/server/controllers/common.js b/server/controllers/common.js index 66f4178d..66b9656b 100644 --- a/server/controllers/common.js +++ b/server/controllers/common.js @@ -366,6 +366,7 @@ router.get('/*', async (req, res, next) => { req.i18n.changeLanguage(pageArgs.locale) try { + // -> Get Page from cache const page = await WIKI.models.pages.getPage({ path: pageArgs.path, locale: pageArgs.locale, @@ -374,6 +375,7 @@ router.get('/*', async (req, res, next) => { }) pageArgs.tags = _.get(page, 'tags', []) + // -> Check User Access if (!WIKI.auth.checkAccess(req.user, ['read:pages'], pageArgs)) { if (req.user.id === 2) { res.cookie('loginRedirect', req.path, { @@ -396,6 +398,7 @@ router.get('/*', async (req, res, next) => { _.set(res.locals, 'pageMeta.title', page.title) _.set(res.locals, 'pageMeta.description', page.description) + // -> Build sidebar navigation let sdi = 1 const sidebar = (await WIKI.models.navigation.getTree({ cache: true, locale: pageArgs.locale, groups: req.user.groups })).map(n => ({ i: `sdi-${sdi++}`, @@ -406,20 +409,46 @@ router.get('/*', async (req, res, next) => { t: n.target })) + // -> Build theme code injection const injectCode = { css: WIKI.config.theming.injectCSS, head: WIKI.config.theming.injectHead, body: WIKI.config.theming.injectBody } + // -> Convert page TOC if (!_.isString(page.toc)) { page.toc = JSON.stringify(page.toc) } if (req.query.legacy || req.get('user-agent').indexOf('Trident') >= 0) { - res.render('legacy/page', { page, sidebar, injectCode, isAuthenticated: req.user && req.user.id !== 2 }) + // -> Render legacy view + res.render('legacy/page', { + page, + sidebar, + injectCode, + isAuthenticated: req.user && req.user.id !== 2 + }) } else { - res.render('page', { page, sidebar, injectCode }) + // -> Inject comments variables + if (WIKI.config.features.featurePageComments && WIKI.data.commentProvider.codeTemplate) { + [ + { key: 'pageUrl', value: `${WIKI.config.host}/i/${page.id}` }, + { key: 'pageId', value: page.id } + ].forEach((cfg) => { + WIKI.data.commentProvider.head = _.replace(WIKI.data.commentProvider.head, new RegExp(`{{${cfg.key}}}`, 'g'), cfg.value) + WIKI.data.commentProvider.body = _.replace(WIKI.data.commentProvider.body, new RegExp(`{{${cfg.key}}}`, 'g'), cfg.value) + WIKI.data.commentProvider.main = _.replace(WIKI.data.commentProvider.main, new RegExp(`{{${cfg.key}}}`, 'g'), cfg.value) + }) + } + + // -> Render view + res.render('page', { + page, + sidebar, + injectCode, + comments: WIKI.data.commentProvider + }) } } else if (pageArgs.path === 'home') { _.set(res.locals, 'pageMeta.title', 'Welcome') diff --git a/server/core/kernel.js b/server/core/kernel.js index ebe7b7ea..adce5d6a 100644 --- a/server/core/kernel.js +++ b/server/core/kernel.js @@ -77,6 +77,7 @@ module.exports = { await WIKI.models.storage.refreshTargetsFromDisk() await WIKI.auth.activateStrategies() + await WIKI.models.commentProviders.initProvider() await WIKI.models.searchEngines.initEngine() await WIKI.models.storage.initTargets() WIKI.scheduler.start() diff --git a/server/graph/resolvers/comment.js b/server/graph/resolvers/comment.js index bee35aa6..e09f56ee 100644 --- a/server/graph/resolvers/comment.js +++ b/server/graph/resolvers/comment.js @@ -38,7 +38,7 @@ module.exports = { async updateProviders(obj, args, context) { try { for (let provider of args.providers) { - await WIKI.models.providers.query().patch({ + await WIKI.models.commentProviders.query().patch({ isEnabled: provider.isEnabled, config: _.reduce(provider.config, (result, value, key) => { _.set(result, `${value.key}`, _.get(JSON.parse(value.value), 'v', null)) @@ -46,6 +46,7 @@ module.exports = { }, {}) }).where('key', provider.key) } + await WIKI.models.commentProviders.initProvider() return { responseResult: graphHelper.generateSuccess('Comment Providers updated successfully') } diff --git a/server/models/commentProviders.js b/server/models/commentProviders.js index bfdd6636..e5338d47 100644 --- a/server/models/commentProviders.js +++ b/server/models/commentProviders.js @@ -51,38 +51,38 @@ module.exports = class CommentProvider extends Model { const def = await fs.readFile(path.join(WIKI.SERVERPATH, 'modules/comments', dir, 'definition.yml'), 'utf8') diskProviders.push(yaml.safeLoad(def)) } - WIKI.data.commentProviders = diskProviders.map(engine => ({ - ...engine, - props: commonHelper.parseModuleProps(engine.props) + WIKI.data.commentProviders = diskProviders.map(provider => ({ + ...provider, + props: commonHelper.parseModuleProps(provider.props) })) let newProviders = [] - for (let engine of WIKI.data.commentProviders) { - if (!_.some(dbProviders, ['key', engine.key])) { + for (let provider of WIKI.data.commentProviders) { + if (!_.some(dbProviders, ['key', provider.key])) { newProviders.push({ - key: engine.key, - isEnabled: engine.key === 'default', - config: _.transform(engine.props, (result, value, key) => { + key: provider.key, + isEnabled: provider.key === 'default', + config: _.transform(provider.props, (result, value, key) => { _.set(result, key, value.default) return result }, {}) }) } else { - const engineConfig = _.get(_.find(dbProviders, ['key', engine.key]), 'config', {}) + const providerConfig = _.get(_.find(dbProviders, ['key', provider.key]), 'config', {}) await WIKI.models.commentProviders.query().patch({ - config: _.transform(engine.props, (result, value, key) => { + config: _.transform(provider.props, (result, value, key) => { if (!_.has(result, key)) { _.set(result, key, value.default) } return result - }, engineConfig) - }).where('key', engine.key) + }, providerConfig) + }).where('key', provider.key) } } if (newProviders.length > 0) { trx = await WIKI.models.Objection.transaction.start(WIKI.models.knex) - for (let engine of newProviders) { - await WIKI.models.commentProviders.query(trx).insert(engine) + for (let provider of newProviders) { + await WIKI.models.commentProviders.query(trx).insert(provider) } await trx.commit() WIKI.logger.info(`Loaded ${newProviders.length} new comment providers: [ OK ]`) @@ -97,4 +97,41 @@ module.exports = class CommentProvider extends Model { } } } + + static async initProvider() { + const commentProvider = await WIKI.models.commentProviders.query().findOne('isEnabled', true) + if (commentProvider) { + WIKI.data.commentProvider = { + ..._.find(WIKI.data.commentProviders, ['key', commentProvider.key]), + head: '', + bodyStart: '', + bodyEnd: '', + main: '' + } + + if (WIKI.data.commentProvider.codeTemplate) { + const def = await fs.readFile(path.join(WIKI.SERVERPATH, 'modules/comments', commentProvider.key, 'code.yml'), 'utf8') + let code = yaml.safeLoad(def) + code.head = _.defaultTo(code.head, '') + code.body = _.defaultTo(code.body, '') + code.main = _.defaultTo(code.main, '') + + _.forOwn(commentProvider.config, (value, key) => { + code.head = _.replace(code.head, new RegExp(`{{${key}}}`, 'g'), value) + code.body = _.replace(code.body, new RegExp(`{{${key}}}`, 'g'), value) + code.main = _.replace(code.main, new RegExp(`{{${key}}}`, 'g'), value) + }) + + WIKI.data.commentProvider.head = code.head + WIKI.data.commentProvider.body = code.body + WIKI.data.commentProvider.main = code.main + } else { + WIKI.data.commentProvider = { + ...WIKI.data.commentProvider, + ...require(`../modules/comments/${commentProvider.key}/comment`) + } + } + WIKI.data.commentProvider.config = commentProvider.config + } + } } diff --git a/server/modules/comments/commento/code.yml b/server/modules/comments/commento/code.yml index c0a90dfe..2d4ca911 100644 --- a/server/modules/comments/commento/code.yml +++ b/server/modules/comments/commento/code.yml @@ -1,4 +1,12 @@ main: |
-bodyEnd: | - +body: | + diff --git a/server/modules/comments/commento/definition.yml b/server/modules/comments/commento/definition.yml index 0f614d28..904c7cf1 100644 --- a/server/modules/comments/commento/definition.yml +++ b/server/modules/comments/commento/definition.yml @@ -4,9 +4,8 @@ description: A fast, privacy-focused commenting platform. author: requarks.io logo: https://static.requarks.io/logo/commento.svg website: https://commento.io/ -displayMode: footer codeTemplate: true -isAvailable: false +isAvailable: true props: instanceUrl: type: String diff --git a/server/modules/comments/default/comment.js b/server/modules/comments/default/comment.js new file mode 100644 index 00000000..403681b2 --- /dev/null +++ b/server/modules/comments/default/comment.js @@ -0,0 +1,11 @@ +/* global WIKI */ + +// ------------------------------------ +// Default Comment Provider +// ------------------------------------ + +module.exports = { + add (args) { + + } +} diff --git a/server/modules/comments/default/definition.yml b/server/modules/comments/default/definition.yml index 097b4a16..eac1f69c 100644 --- a/server/modules/comments/default/definition.yml +++ b/server/modules/comments/default/definition.yml @@ -4,7 +4,6 @@ description: Built-in advanced comments tool. author: requarks.io logo: https://static.requarks.io/logo/wikijs-butterfly.svg website: https://wiki.js.org -displayMode: dynamic codeTemplate: false isAvailable: true props: diff --git a/server/modules/comments/disqus/code.yml b/server/modules/comments/disqus/code.yml index 5faec766..e123d5b3 100644 --- a/server/modules/comments/disqus/code.yml +++ b/server/modules/comments/disqus/code.yml @@ -1,14 +1,14 @@ main: |
-bodyEnd: | +body: |