diff --git a/src/core/plugin.js b/src/core/plugin.js new file mode 100644 index 000000000..7592a4081 --- /dev/null +++ b/src/core/plugin.js @@ -0,0 +1,48 @@ +import { joinURL, withLeadingSlash } from 'ufo' +import settings from '~docus-cache/docus-settings.json' +import { createDocus, <%= options.isSSG ? "QueryBuilder" : "RemoteQueryBuilder" %> } from '~docus' +/* <% if (options.watch) { %> */ import { useWebSocket } from '~docus/api/websocket' /* <% } %> */ + + +/* <% if (options.isSSG) { %> */ +import Loki from '@lokidb/loki' +let db, items +function createQuery(path, { deep = false, text = false } = {}) { + const query = { + $or: [{ path }, { path: deep ? { $regex: new RegExp(`^${path}`) } : path }] + } + const postprocess = [data => (!deep && data[0]?.path === path ? data[0] : data)] + + return new QueryBuilder({ query: items.chain().find(query, !deep), path, postprocess, text }, {}) +} +/* <% } else { %> */ +function createQuery(path, options) { + path = withLeadingSlash(path) + return new RemoteQueryBuilder(joinURL('/', '<%= options.apiBase %>', path), options) +} +/* <% } %> */ + + +export default async function (ctx, inject) { + /* <% if (options.isSSG) { %> */ + if (process.client && !db) { + const { docusDbHash } = ctx.$config ? ctx.$config : ctx.nuxtState + const database = await fetch(`<%= options.dbPath %>/db-${docusDbHash}.json`).then(res => res.json()) + db = new Loki('content.db') + db.loadJSONObject(database) + items = db.getCollection('items') + } + /* <% } %> */ + + const $docus = await createDocus( + ctx, + settings, + process.server ? ctx.ssrContext.docus.createQuery : createQuery + ) + + inject('docus', $docus) + + /* <% if (options.watch) { %> */ + useWebSocket({ base: '<%= options.apiBase %>' }).connect() + /* <% } %> */ +} diff --git a/src/i18n/runtime/plugin.js b/src/i18n/runtime/plugin.js new file mode 100644 index 000000000..1929b883c --- /dev/null +++ b/src/i18n/runtime/plugin.js @@ -0,0 +1,21 @@ +export default function ({ app }, inject) { + if (process.client) { + app.i18n.onLanguageSwitched = () => { + window.$nuxt.$docus.fetchNavigation() + } + } + + // Generate local path for static contents. + // This helper does not respect `router.trailingSlash` + // and add/remove trailingSlash baded on original path + inject('contentLocalePath', path => { + let localePath = app.localePath(path) + if (path.endsWith('/') && !localePath.endsWith('/')) { + localePath += '/' + } + if (!path.endsWith('/') && localePath.endsWith('/')) { + localePath = localePath.replace(/\/*$/, '') + } + return localePath + }) +} diff --git a/src/social-image/runtime/plugin.js b/src/social-image/runtime/plugin.js new file mode 100644 index 000000000..2d5e9b855 --- /dev/null +++ b/src/social-image/runtime/plugin.js @@ -0,0 +1,64 @@ +const url = '<%= options.baseUrl %>/<%= options.outDir %>/' + +const findMeta = (meta, key) => meta.find(item => item.hid === key || item.name === key || item.property === key) + +const generateName = route => (route.replace(/^\//, '').replace(/[/]/g, '-') || 'home-page') + '.jpeg' + +export default function ({ route, app, ssrContext }) { + if (!route.matched[0]) { + return + } + const { options } = route.matched[0].components.default + const imageName = generateName(route.path) + + app.head.meta = Array.isArray(app.head.meta) ? app.head.meta : [] + if (findMeta(app.head.meta, 'og:image')) { + app.head.meta.push({ + hid: 'og:image', + property: 'og:image', + content: url + imageName + }) + } + if (findMeta(app.head.meta, 'twitter:image')) { + app.head.meta.push({ + hid: 'twitter:image', + name: 'twitter:image', + content: url + imageName + }) + } + + if (ssrContext && ssrContext.addSocialImage) { + options.__pageHead = options.__pageHead || options.head + options.head = createCustomHead({ + options, + addSocialImage: ssrContext.addSocialImage, + imageName, + route: route.path + }) + } +} + +const createCustomHead = ({ options, addSocialImage, imageName, route }) => + function socialImageCustomHead() { + let head + switch (typeof options.__pageHead) { + case 'function': + head = options.__pageHead.call(this) + break + case 'object': + head = { ...options.__pageHead } + break + default: + head = {} + } + if (head.title) { + const metaDescription = findMeta(head.meta || [], 'description') + addSocialImage({ + title: head.title, + description: metaDescription ? metaDescription.content : '', + imageName, + route + }) + } + return head + }