mirror of
https://github.com/directus/directus.git
synced 2026-04-25 03:00:53 -04:00
Update in-app docs (#3989)
* Fix root redirect * Fix html in headings * Add graphql syntax mode * Install markdown-it + plugins * Fix file copying on mac * Replace md rendering engine * Fix wrong links in guides * Scroll to top on every route change * Update in-app links * Fix home redirect * Fix deep-linking paths * Add to reference * Fix nested group scoping * Fix open path reference
This commit is contained in:
@@ -18,7 +18,7 @@
|
||||
"access": "public"
|
||||
},
|
||||
"scripts": {
|
||||
"copy-docs-images": "rimraf public/img/docs && copyfiles -u 3 ../docs/assets/* public/img/docs --verbose",
|
||||
"copy-docs-images": "rimraf public/img/docs && copyfiles -u 3 \"../docs/assets/**/*\" \"public/img/docs\" --verbose",
|
||||
"predev": "npm run copy-docs-images",
|
||||
"prebuild": "npm run copy-docs-images",
|
||||
"dev": "vue-cli-service serve",
|
||||
@@ -34,8 +34,8 @@
|
||||
},
|
||||
"gitHead": "4476da28dbbc2824e680137aa28b2b91b5afabec",
|
||||
"dependencies": {
|
||||
"@directus/format-title": "file:../packages/format-title",
|
||||
"@directus/docs": "file:../docs"
|
||||
"@directus/docs": "file:../docs",
|
||||
"@directus/format-title": "file:../packages/format-title"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@vue/cli-plugin-babel": "^4.5.8",
|
||||
|
||||
@@ -2,93 +2,183 @@
|
||||
icon: play_circle_outline
|
||||
to: '/getting-started'
|
||||
children:
|
||||
- name: Introduction
|
||||
to: '/getting-started/introduction'
|
||||
- name: Support & FAQ
|
||||
to: '/getting-started/support'
|
||||
- name: Contributing
|
||||
to: '/getting-started/contributing'
|
||||
- name: Backing Directus
|
||||
to: '/getting-started/backing-directus'
|
||||
- to: '/getting-started/introduction'
|
||||
name: Introduction
|
||||
- to: '/getting-started/support'
|
||||
name: Help & Support
|
||||
- to: '/getting-started/backing-directus'
|
||||
name: Backing Directus
|
||||
|
||||
- name: Concepts
|
||||
icon: school
|
||||
to: '/concepts'
|
||||
children:
|
||||
- name: Platform Overview
|
||||
to: '/concepts/platform-overview'
|
||||
- name: App Overview
|
||||
to: '/concepts/app-overview'
|
||||
- name: App Extensions
|
||||
to: '/concepts/app-extensions'
|
||||
- name: Activity & Versions
|
||||
to: '/concepts/activity-and-versions'
|
||||
- name: Files & Thumbnails
|
||||
to: '/concepts/files-and-thumbnails'
|
||||
- name: Internationalization
|
||||
to: '/concepts/internationalization'
|
||||
- name: Relationships
|
||||
to: '/concepts/relationships'
|
||||
- name: Users, Roles & Permissions
|
||||
to: '/concepts/users-roles-and-permissions'
|
||||
- to: '/concepts/activity'
|
||||
name: Activity
|
||||
- to: '/concepts/application'
|
||||
name: Application
|
||||
- to: '/concepts/collections'
|
||||
name: Collections
|
||||
- to: '/concepts/databases'
|
||||
name: Databases
|
||||
- to: '/concepts/displays'
|
||||
name: Displays
|
||||
- to: '/concepts/extensions'
|
||||
name: Extensions
|
||||
- to: '/concepts/fields'
|
||||
name: Fields
|
||||
- to: '/concepts/files'
|
||||
name: Files
|
||||
- to: '/concepts/interfaces'
|
||||
name: Interfaces
|
||||
- to: '/concepts/items'
|
||||
name: Items
|
||||
- to: '/concepts/layouts'
|
||||
name: Layouts
|
||||
- to: '/concepts/modules'
|
||||
name: Modules
|
||||
- to: '/concepts/permissions'
|
||||
name: Permissions
|
||||
- to: '/concepts/projects'
|
||||
name: Projects
|
||||
- to: '/concepts/relationships'
|
||||
name: Relationships
|
||||
- to: '/concepts/revisions'
|
||||
name: Revisions
|
||||
- to: '/concepts/roles'
|
||||
name: Roles
|
||||
- to: '/concepts/translations'
|
||||
name: Translations
|
||||
- to: '/concepts/types'
|
||||
name: Types
|
||||
- to: '/concepts/users'
|
||||
name: Users
|
||||
|
||||
- name: Guides
|
||||
icon: article
|
||||
to: '/guides'
|
||||
icon: article
|
||||
children:
|
||||
- name: Collections
|
||||
to: '/guides/collections'
|
||||
- name: Items
|
||||
to: '/guides/items'
|
||||
- name: Fields
|
||||
to: '/guides/fields'
|
||||
- name: Files
|
||||
to: '/guides/files'
|
||||
- name: Presets
|
||||
to: '/guides/presets'
|
||||
- name: Projects
|
||||
to: '/guides/projects'
|
||||
- name: Roles & Permissions
|
||||
to: '/guides/roles-and-permissions'
|
||||
- name: Users
|
||||
to: '/guides/users'
|
||||
- name: Webhooks
|
||||
to: '/guides/webhooks'
|
||||
- name: White-Labeling
|
||||
to: '/guides/white-labeling'
|
||||
- name: Extensions
|
||||
to: '/guides/extensions'
|
||||
children:
|
||||
- name: Accessing Data
|
||||
to: '/guides/extensions/accessing-data'
|
||||
- name: API Endpoints
|
||||
to: '/guides/extensions/api-endpoints'
|
||||
- name: API Hooks
|
||||
to: '/guides/extensions/api-hooks'
|
||||
- name: Displays
|
||||
to: '/guides/extensions/displays'
|
||||
- name: Email Templates
|
||||
to: '/guides/extensions/email-templates'
|
||||
- name: Interfaces
|
||||
to: '/guides/extensions/interfaces'
|
||||
- name: Layouts
|
||||
to: '/guides/extensions/layouts'
|
||||
- name: Modules
|
||||
to: '/guides/extensions/modules'
|
||||
- name: Storage Adapters
|
||||
to: '/guides/extensions/storage-adapters'
|
||||
- to: '/guides/api-config'
|
||||
name: API Config
|
||||
- to: '/guides/api-endpoints'
|
||||
name: API Endpoints
|
||||
- to: '/guides/api-hooks'
|
||||
name: API Hooks
|
||||
- to: '/guides/collections'
|
||||
name: Collections
|
||||
- to: '/guides/displays'
|
||||
name: Displays
|
||||
- to: '/guides/fields'
|
||||
name: Fields
|
||||
- to: '/guides/files'
|
||||
name: Files
|
||||
- to: '/guides/interfaces'
|
||||
name: Interfaces
|
||||
- to: '/guides/items'
|
||||
name: Items
|
||||
- to: '/guides/layouts'
|
||||
name: Layouts
|
||||
- to: '/guides/migrations'
|
||||
name: Migrations
|
||||
- to: '/guides/modules'
|
||||
name: Modules
|
||||
- to: '/guides/permissions'
|
||||
name: Permissions
|
||||
- to: '/guides/presets'
|
||||
name: Presets
|
||||
- to: '/guides/projects'
|
||||
name: Projects
|
||||
- to: '/guides/roles'
|
||||
name: Roles
|
||||
- to: '/guides/styles'
|
||||
name: Styles
|
||||
- to: '/guides/users'
|
||||
name: Users
|
||||
- to: '/guides/webhooks'
|
||||
name: Webhooks
|
||||
|
||||
- name: Reference
|
||||
icon: code
|
||||
to: '/reference'
|
||||
children:
|
||||
- name: Command Line Interface
|
||||
to: '/reference/command-line-interface'
|
||||
- name: Environment Variables
|
||||
to: '/reference/environment-variables'
|
||||
- name: Error Codes
|
||||
to: '/reference/error-codes'
|
||||
- name: Filter Rules
|
||||
to: '/reference/filter-rules'
|
||||
- name: Item Objects
|
||||
to: '/reference/item-objects'
|
||||
- to: '/reference/command-line-interface'
|
||||
name: Command Line Interface
|
||||
- to: '/reference/environment-variables'
|
||||
name: Environment Variables
|
||||
- to: '/reference/error-codes'
|
||||
name: Error Codes
|
||||
- to: '/reference/field-transforms'
|
||||
name: Field Transforms
|
||||
- to: '/reference/filter-rules'
|
||||
name: Filter Rules
|
||||
- to: '/reference/sdk-js'
|
||||
name: JavaScript SDK
|
||||
|
||||
- name: API Reference
|
||||
icon: api
|
||||
to: '/reference/api'
|
||||
children:
|
||||
- to: '/reference/api/introduction'
|
||||
name: Introduction
|
||||
- to: '/reference/api/authentication'
|
||||
name: Authentication
|
||||
- name: Global Query Parameters
|
||||
to: '/reference/api/query'
|
||||
- name: REST API
|
||||
to: '/reference/api/rest'
|
||||
children:
|
||||
- to: '/reference/api/rest/introduction'
|
||||
name: Introduction
|
||||
- to: '/reference/api/rest/activity'
|
||||
name: Activity
|
||||
- to: '/reference/api/rest/authentication'
|
||||
name: Authentication
|
||||
- to: '/reference/api/rest/collections'
|
||||
name: Collections
|
||||
- to: '/reference/api/rest/extensions'
|
||||
name: Extensions
|
||||
- to: '/reference/api/rest/fields'
|
||||
name: Fields
|
||||
- to: '/reference/api/rest/files'
|
||||
name: Files
|
||||
- to: '/reference/api/rest/folders'
|
||||
name: Folders
|
||||
- to: '/reference/api/rest/items'
|
||||
name: Items
|
||||
- to: '/reference/api/rest/permissions'
|
||||
name: Permissions
|
||||
- to: '/reference/api/rest/presets'
|
||||
name: Presets
|
||||
- to: '/reference/api/rest/relations'
|
||||
name: Relations
|
||||
- to: '/reference/api/rest/revisions'
|
||||
name: Revisions
|
||||
- to: '/reference/api/rest/roles'
|
||||
name: Roles
|
||||
- to: '/reference/api/rest/server'
|
||||
name: Server
|
||||
- to: '/reference/api/rest/settings'
|
||||
name: Settings
|
||||
- to: '/reference/api/rest/users'
|
||||
name: Users
|
||||
- to: '/reference/api/rest/utilities'
|
||||
name: Utilities
|
||||
- to: '/reference/api/rest/webhooks'
|
||||
name: Webhooks
|
||||
- to: '/reference/api/graphql'
|
||||
name: GraphQL API
|
||||
- to: '/reference/api/assets'
|
||||
name: Assets
|
||||
- to: '/reference/api/health'
|
||||
name: Health Check
|
||||
# - name: Contributing
|
||||
# to: '/contributing'
|
||||
# children:
|
||||
# - to: '/contributing/introduction'
|
||||
# name: Introduction
|
||||
# - to: '/contributing/codebase-overview'
|
||||
# name: Codebase Overview
|
||||
# - to: '/contributing/running-locally'
|
||||
# name: Running Locally
|
||||
# - to: '/contributing/translations'
|
||||
# name: Translating the App
|
||||
|
||||
@@ -1,38 +1,68 @@
|
||||
<template>
|
||||
<div class="md" v-html="html" @click="onClick" />
|
||||
<div class="md" :class="pageClass" v-html="html" @click="onClick" />
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent, ref, onMounted, onUpdated } from '@vue/composition-api';
|
||||
import { defineComponent, ref, onMounted, onUpdated, inject } from '@vue/composition-api';
|
||||
|
||||
import marked, { Renderer } from 'marked';
|
||||
import highlight from 'highlight.js';
|
||||
import MarkdownIt from 'markdown-it';
|
||||
import fm from 'front-matter';
|
||||
|
||||
import hljs from 'highlight.js';
|
||||
import hljsGraphQL from '../../../utils/hljs-graphql';
|
||||
|
||||
import { getRootPath } from '../../../utils/get-root-path';
|
||||
|
||||
import router from '@/router';
|
||||
|
||||
hljs.registerLanguage('graphql', hljsGraphQL);
|
||||
|
||||
const md = new MarkdownIt({
|
||||
html: true,
|
||||
highlight(str, lang) {
|
||||
if (lang && hljs.getLanguage(lang)) {
|
||||
try {
|
||||
return hljs.highlight(lang, str).value;
|
||||
} catch {
|
||||
console.warn('There was an error highlighting in Markdown');
|
||||
}
|
||||
}
|
||||
|
||||
return '';
|
||||
},
|
||||
});
|
||||
|
||||
md.use(require('markdown-it-table-of-contents'), { includeLevel: [2] });
|
||||
md.use(require('markdown-it-anchor').default, { permalink: true, permalinkSymbol: '#' });
|
||||
|
||||
function hintRenderer(type: string) {
|
||||
return (tokens: any[], idx: number) => {
|
||||
const token = tokens[idx];
|
||||
let title = token.info.trim().slice(type.length).trim() || '';
|
||||
|
||||
if (title) title = `<div class="hint-title">${title}</div>`;
|
||||
|
||||
if (token.nesting === 1) {
|
||||
return `<div class="${type} hint">${title}\n`;
|
||||
} else {
|
||||
return '</div>\n';
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
md.use(require('markdown-it-container'), 'tip', { render: hintRenderer('tip') });
|
||||
md.use(require('markdown-it-container'), 'warning', { render: hintRenderer('warning') });
|
||||
md.use(require('markdown-it-container'), 'danger', { render: hintRenderer('danger') });
|
||||
|
||||
export default defineComponent({
|
||||
setup(props, { slots }) {
|
||||
const html = ref('');
|
||||
const pageClass = ref<string>();
|
||||
|
||||
onMounted(generateHTML);
|
||||
onUpdated(generateHTML);
|
||||
|
||||
return { html, onClick };
|
||||
|
||||
async function onClick($event: Event) {
|
||||
if ($event.target instanceof HTMLElement) {
|
||||
const href = $event.target.getAttribute('href');
|
||||
|
||||
if (href && $event.target.classList.contains('copy')) {
|
||||
await navigator.clipboard.writeText(window.location.href.split('#')[0] + href);
|
||||
}
|
||||
|
||||
if (href && href.indexOf('/admin/docs/') === 0) {
|
||||
$event.preventDefault();
|
||||
await router.push(href.replace('/admin/docs/', '/docs/'));
|
||||
}
|
||||
}
|
||||
}
|
||||
return { html, onClick, pageClass };
|
||||
|
||||
function generateHTML() {
|
||||
if (slots.default === null || !slots.default()?.[0]?.text) {
|
||||
@@ -40,65 +70,78 @@ export default defineComponent({
|
||||
return;
|
||||
}
|
||||
|
||||
let htmlString = slots.default()[0].text!;
|
||||
const source = slots.default()[0].text!;
|
||||
const { attributes, body } = fm<{ pageClass?: string }>(source);
|
||||
|
||||
const renderer: Partial<Renderer> = {
|
||||
heading(text, level) {
|
||||
const escapedText = text.toLowerCase().replace(/[^\w]+/g, '-');
|
||||
return `
|
||||
<h${level} id="${escapedText}">
|
||||
<a class="heading-link copy" href="#${escapedText}">#</a>
|
||||
${text}
|
||||
</h${level}>`;
|
||||
},
|
||||
link(href, title, text) {
|
||||
let classname = 'body-link link';
|
||||
if (href && href.indexOf('/') === 0 && href.indexOf('/admin/docs/') === -1) href = `/admin/docs${href}`;
|
||||
if (href && href.indexOf('#') === 0) classname = `${classname} copy`;
|
||||
return `<a href="${href}" class="${classname}">${text}</a>`;
|
||||
},
|
||||
image(href, title, text) {
|
||||
if (!href) return '';
|
||||
let paths = href.split('/');
|
||||
let markdown = body;
|
||||
|
||||
while ((paths[0] === 'assets') === false) {
|
||||
paths = paths.slice(1);
|
||||
}
|
||||
const rawImages = body.matchAll(/!\[[^\]]*\]\((?<filename>.*?)(?=\"|\))(?<optionalpart>\".*\")?\)/g) ?? [];
|
||||
const rootPath = getRootPath();
|
||||
|
||||
const path = `/img/docs/${paths.slice(1).join('/')}`;
|
||||
for (const rawImage of rawImages) {
|
||||
const filenameParts = rawImage.groups!.filename.split('/');
|
||||
|
||||
const classname = 'body-image';
|
||||
while (filenameParts.includes('assets')) {
|
||||
filenameParts.shift();
|
||||
}
|
||||
|
||||
return `<img src="${path}" class="${classname}" alt="${text}">`;
|
||||
},
|
||||
};
|
||||
const newFilename = `${rootPath}img/docs/${filenameParts.join('/')}`;
|
||||
const newImage = rawImage[0].replace(rawImage.groups!.filename, newFilename);
|
||||
markdown = markdown.replace(rawImage[0], newImage);
|
||||
}
|
||||
|
||||
// Marked merges it's default rendered with our extension. It's typed as a full rendered however
|
||||
marked.use({ renderer } as any);
|
||||
pageClass.value = attributes?.pageClass;
|
||||
|
||||
htmlString = htmlString.replace(/::: ([^\s]+) ([^\n]+)([\s\S]*?)\n:::/gm, (match, type, title, body) => {
|
||||
body = marked(body);
|
||||
return `<div class="hint ${type}"><p class="hint-title">${title}</p><p class="hint-body">${body}</p></div>`;
|
||||
});
|
||||
|
||||
htmlString = marked(htmlString, {
|
||||
highlight: (code, lang) => {
|
||||
return highlight.highlightAuto(code, [lang]).value;
|
||||
},
|
||||
});
|
||||
const htmlString = md.render(markdown);
|
||||
|
||||
html.value = htmlString;
|
||||
|
||||
// The Markdown is fetched async on page transition, which means the # link already exists before the markdown does
|
||||
// This will force the main el to scroll down to the targetted element on updates of the content
|
||||
const mainElement = inject('main-element', ref<Element | null>(null));
|
||||
|
||||
if (router.currentRoute.hash) {
|
||||
const linkedEl = document.querySelector(router.currentRoute.hash) as HTMLElement;
|
||||
|
||||
if (linkedEl) {
|
||||
mainElement.value?.scrollTo({ top: linkedEl.offsetTop - 100 });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function onClick(event: MouseEvent) {
|
||||
if (
|
||||
event.target &&
|
||||
(event.target as HTMLElement).tagName.toLowerCase() === 'a' &&
|
||||
(event.target as HTMLAnchorElement).href
|
||||
) {
|
||||
const link = (event.target as HTMLAnchorElement).getAttribute('href')!;
|
||||
|
||||
if (link.startsWith('http') || link.startsWith('#')) return;
|
||||
|
||||
event.preventDefault();
|
||||
const parts = link.split('#');
|
||||
parts[0] = parts[0].endsWith('/') ? parts[0].slice(0, -1) : parts[0];
|
||||
router.push({
|
||||
path: `/docs${parts[0]}`,
|
||||
hash: parts[1],
|
||||
});
|
||||
}
|
||||
}
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
// stylelint-disable
|
||||
|
||||
.error {
|
||||
padding: 20vh 0;
|
||||
}
|
||||
|
||||
.md {
|
||||
max-width: 740px;
|
||||
|
||||
::v-deep {
|
||||
font-weight: 400;
|
||||
font-size: 16px;
|
||||
@@ -448,14 +491,13 @@ export default defineComponent({
|
||||
border-left: 2px solid var(--primary);
|
||||
|
||||
&-title {
|
||||
margin-bottom: 0.5em;
|
||||
margin-block-start: 1em;
|
||||
margin-block-end: 1em;
|
||||
margin-inline-start: 0px;
|
||||
margin-inline-end: 0px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
&-body {
|
||||
margin-top: 0.5em;
|
||||
}
|
||||
|
||||
&.tip {
|
||||
border-left: 2px solid var(--success);
|
||||
}
|
||||
@@ -470,6 +512,102 @@ export default defineComponent({
|
||||
border-left: 2px solid var(--danger);
|
||||
}
|
||||
}
|
||||
|
||||
.two-up {
|
||||
margin-top: 3rem;
|
||||
}
|
||||
|
||||
.two-up .right {
|
||||
margin-top: 50px;
|
||||
}
|
||||
|
||||
.table-of-contents {
|
||||
margin-top: -20px;
|
||||
}
|
||||
|
||||
pre,
|
||||
pre[class*='language-'] {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
@media (min-width: 1000px) {
|
||||
.two-up {
|
||||
display: grid;
|
||||
grid-template-columns: minmax(0, 4fr) minmax(0, 3fr);
|
||||
grid-gap: 40px;
|
||||
align-items: start;
|
||||
}
|
||||
|
||||
.two-up .left,
|
||||
.two-up .right {
|
||||
> *:first-child {
|
||||
margin-top: 0 !important;
|
||||
}
|
||||
}
|
||||
|
||||
.two-up .right {
|
||||
margin-top: 0;
|
||||
position: sticky;
|
||||
top: 100px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.page-reference {
|
||||
max-width: 1200px;
|
||||
|
||||
::v-deep {
|
||||
hr {
|
||||
width: calc(100% + 5rem);
|
||||
left: -2.5rem;
|
||||
position: relative;
|
||||
margin: 3rem 0;
|
||||
}
|
||||
|
||||
h2 {
|
||||
border-bottom: 0;
|
||||
margin-top: 3rem;
|
||||
font-size: 2rem;
|
||||
}
|
||||
|
||||
h3 {
|
||||
margin-top: 3rem;
|
||||
margin-bottom: 0.5rem;
|
||||
font-size: 1.2rem;
|
||||
}
|
||||
|
||||
h4 {
|
||||
margin-top: 2rem;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.definitions {
|
||||
font-size: 0.9rem;
|
||||
|
||||
> p {
|
||||
border-bottom: 2px solid var(--border-subdued);
|
||||
padding: 0.8rem 0;
|
||||
margin: 0;
|
||||
|
||||
&:first-child {
|
||||
border-top: 2px solid var(--border-subdued);
|
||||
}
|
||||
|
||||
> code:first-child {
|
||||
background: transparent;
|
||||
padding: 0;
|
||||
margin-right: 0.2rem;
|
||||
font-weight: 700;
|
||||
font-size: 0.9rem;
|
||||
border: 0;
|
||||
}
|
||||
|
||||
> strong {
|
||||
color: #aaa;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1,13 +1,22 @@
|
||||
<template>
|
||||
<v-divider v-if="section.divider" />
|
||||
<v-list-group v-else-if="section.children" :dense="dense" :multiple="false" :value="section.to">
|
||||
<v-list-group :scope="scope" v-else-if="section.children" :dense="dense" :multiple="false" :value="section.to">
|
||||
<template #activator>
|
||||
<v-list-item-icon v-if="section.icon !== undefined"><v-icon :name="section.icon" /></v-list-item-icon>
|
||||
<v-list-item-content>
|
||||
<v-list-item-text>{{ section.name }}</v-list-item-text>
|
||||
</v-list-item-content>
|
||||
</template>
|
||||
<navigation-list-item v-for="(child, index) in section.children" :key="index" :section="child" dense />
|
||||
|
||||
<v-item-group :scope="section.to">
|
||||
<navigation-list-item
|
||||
v-for="(child, index) in section.children"
|
||||
:key="index"
|
||||
:section="child"
|
||||
dense
|
||||
:scope="section.to"
|
||||
/>
|
||||
</v-item-group>
|
||||
</v-list-group>
|
||||
|
||||
<v-list-item v-else :to="`/docs${section.to}`" :dense="dense" :value="section.to">
|
||||
@@ -19,7 +28,7 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent, PropType, computed } from '@vue/composition-api';
|
||||
import { defineComponent, PropType } from '@vue/composition-api';
|
||||
import { Link, Group } from '@directus/docs';
|
||||
|
||||
export default defineComponent({
|
||||
@@ -33,6 +42,10 @@ export default defineComponent({
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
scope: {
|
||||
type: String,
|
||||
default: null,
|
||||
},
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
@@ -18,6 +18,11 @@ function spreadPath(path: string) {
|
||||
for (let i = 1; i < sections.length; i++) {
|
||||
paths.push(paths[i - 1] + '/' + sections[i]);
|
||||
}
|
||||
|
||||
if (paths[0] === '/reference' && paths[1] === '/reference/api') {
|
||||
paths.shift();
|
||||
}
|
||||
|
||||
return paths;
|
||||
}
|
||||
|
||||
@@ -30,35 +35,16 @@ export default defineComponent({
|
||||
},
|
||||
},
|
||||
setup(props) {
|
||||
const _selection = ref<string[] | null>(null);
|
||||
const selection = ref<string[] | null>(null);
|
||||
|
||||
watch(
|
||||
() => props.path,
|
||||
(newPath) => {
|
||||
if (newPath === null) return;
|
||||
_selection.value = spreadPath(newPath.replace('/docs', ''));
|
||||
selection.value = spreadPath(newPath.replace('/docs', ''));
|
||||
}
|
||||
);
|
||||
|
||||
const selection = computed({
|
||||
get() {
|
||||
if (_selection.value === null && props.path !== null)
|
||||
_selection.value = spreadPath(props.path.replace('/docs', ''));
|
||||
return _selection.value || [];
|
||||
},
|
||||
set(newSelection: string[]) {
|
||||
if (newSelection.length === 0) {
|
||||
_selection.value = [];
|
||||
} else {
|
||||
if (_selection.value && _selection.value.includes(newSelection[0])) {
|
||||
_selection.value = _selection.value.filter((s) => s !== newSelection[0]);
|
||||
} else {
|
||||
_selection.value = spreadPath(newSelection[0]);
|
||||
}
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
return { navSections: navLinks, selection };
|
||||
},
|
||||
});
|
||||
|
||||
@@ -8,7 +8,7 @@ export default defineModule(({ i18n }) => {
|
||||
const routes: RouteConfig[] = [
|
||||
{
|
||||
path: '/',
|
||||
component: StaticDocs,
|
||||
redirect: '/getting-started/introduction/',
|
||||
},
|
||||
...parseRoutes(files),
|
||||
{
|
||||
|
||||
@@ -1,11 +1,15 @@
|
||||
<template>
|
||||
<private-view :title="title" ref="view">
|
||||
<private-view :title="title">
|
||||
<template #title-outer:prepend>
|
||||
<v-button rounded disabled icon>
|
||||
<v-icon name="info" />
|
||||
</v-button>
|
||||
</template>
|
||||
|
||||
<template #title>
|
||||
<h1 v-html="title" class="type-title"></h1>
|
||||
</template>
|
||||
|
||||
<template #navigation>
|
||||
<docs-navigation :path="path" />
|
||||
</template>
|
||||
@@ -23,7 +27,7 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent, ref, computed, onUpdated } from '@vue/composition-api';
|
||||
import { defineComponent, ref, computed } from '@vue/composition-api';
|
||||
import DocsNavigation from '../components/navigation.vue';
|
||||
import Markdown from '../components/markdown.vue';
|
||||
import marked from 'marked';
|
||||
@@ -35,7 +39,11 @@ async function getMarkdownForPath(path: string) {
|
||||
pathParts.shift();
|
||||
}
|
||||
|
||||
const docsPath = pathParts.join('/');
|
||||
let docsPath = pathParts.join('/');
|
||||
|
||||
if (docsPath.endsWith('/')) {
|
||||
docsPath = docsPath.slice(0, -1);
|
||||
}
|
||||
|
||||
const mdModule = await import('raw-loader!@directus/docs/' + docsPath + '.md');
|
||||
|
||||
@@ -62,31 +70,36 @@ export default defineComponent({
|
||||
setup() {
|
||||
const path = ref<string | null>(null);
|
||||
const markdown = ref('');
|
||||
const view = ref<Vue>();
|
||||
|
||||
const title = computed(() => {
|
||||
const firstLine = markdown.value.split('\n').shift();
|
||||
return firstLine?.substring(2).trim();
|
||||
const lines = markdown.value.split('\n');
|
||||
|
||||
for (let i = 0; i < lines.length; i++) {
|
||||
if (lines[i].startsWith('# ')) {
|
||||
return lines[i].substring(2).trim();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
const markdownWithoutTitle = computed(() => {
|
||||
const lines = markdown.value.split('\n');
|
||||
lines.shift();
|
||||
|
||||
for (let i = 0; i < lines.length; i++) {
|
||||
if (lines[i].startsWith('# ')) {
|
||||
lines.splice(i, 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return lines.join('\n');
|
||||
});
|
||||
|
||||
onUpdated(() => {
|
||||
view.value?.$data.contentEl?.scrollTo({ top: 0 });
|
||||
});
|
||||
|
||||
return { markdown, title, markdownWithoutTitle, view, marked, path };
|
||||
return { markdown, title, markdownWithoutTitle, marked, path };
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.docs-content {
|
||||
max-width: 740px;
|
||||
padding: 0 var(--content-padding) var(--content-padding-bottom);
|
||||
}
|
||||
</style>
|
||||
|
||||
45
app/src/utils/hljs-graphql.ts
Normal file
45
app/src/utils/hljs-graphql.ts
Normal file
@@ -0,0 +1,45 @@
|
||||
import { HASH_COMMENT_MODE, QUOTE_STRING_MODE, NUMBER_MODE } from 'highlight.js';
|
||||
|
||||
export default () => ({
|
||||
aliases: ['gql'],
|
||||
keywords: {
|
||||
keyword:
|
||||
'query mutation subscription|10 type input schema directive interface union scalar fragment|10 enum on ...',
|
||||
literal: 'true false null',
|
||||
},
|
||||
contains: [
|
||||
HASH_COMMENT_MODE,
|
||||
QUOTE_STRING_MODE,
|
||||
NUMBER_MODE,
|
||||
{
|
||||
className: 'type',
|
||||
begin: '[^\\w][A-Z][a-z]',
|
||||
end: '\\W',
|
||||
excludeEnd: !0,
|
||||
},
|
||||
{
|
||||
className: 'literal',
|
||||
begin: '[^\\w][A-Z][A-Z]',
|
||||
end: '\\W',
|
||||
excludeEnd: !0,
|
||||
},
|
||||
{
|
||||
className: 'variable',
|
||||
begin: '\\$',
|
||||
end: '\\W',
|
||||
excludeEnd: !0,
|
||||
},
|
||||
{
|
||||
className: 'keyword',
|
||||
begin: '[.]{2}',
|
||||
end: '\\.',
|
||||
},
|
||||
{
|
||||
className: 'meta',
|
||||
begin: '@',
|
||||
end: '\\W',
|
||||
excludeEnd: !0,
|
||||
},
|
||||
],
|
||||
illegal: /([;<']|BEGIN)/,
|
||||
});
|
||||
@@ -61,7 +61,7 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent, ref, provide, toRefs, computed } from '@vue/composition-api';
|
||||
import { defineComponent, ref, provide, toRefs, computed, onUpdated, nextTick } from '@vue/composition-api';
|
||||
import ModuleBar from './components/module-bar/';
|
||||
import SidebarDetailGroup from './components/sidebar-detail-group/';
|
||||
import HeaderBar from './components/header-bar';
|
||||
@@ -71,8 +71,7 @@ import NotificationsGroup from './components/notifications-group/';
|
||||
import NotificationsPreview from './components/notifications-preview/';
|
||||
import NotificationDialogs from './components/notification-dialogs/';
|
||||
import { useUserStore, useAppStore } from '../../stores';
|
||||
import i18n from '../../lang';
|
||||
import emitter, { Events } from '../../events';
|
||||
import router from '../../router';
|
||||
|
||||
export default defineComponent({
|
||||
components: {
|
||||
@@ -112,6 +111,22 @@ export default defineComponent({
|
||||
|
||||
provide('main-element', contentEl);
|
||||
|
||||
router.afterEach(async (to, from) => {
|
||||
contentEl.value?.scrollTo({ top: 0 });
|
||||
|
||||
// await nextTick();
|
||||
|
||||
// const hash = to.hash;
|
||||
|
||||
// if (hash) {
|
||||
// const linkedEl = document.querySelector(hash) as HTMLElement;
|
||||
|
||||
// if (linkedEl) {
|
||||
// contentEl.value?.scrollTo({ top: linkedEl.offsetTop - 100, behavior: 'smooth' });
|
||||
// }
|
||||
// }
|
||||
});
|
||||
|
||||
return {
|
||||
navOpen,
|
||||
contentEl,
|
||||
@@ -195,21 +210,21 @@ export default defineComponent({
|
||||
}
|
||||
|
||||
.content {
|
||||
--border-radius: 6px;
|
||||
--input-height: 60px;
|
||||
--input-padding: 16px; // (60 - 4 - 24) / 2
|
||||
--form-vertical-gap: 52px;
|
||||
|
||||
position: relative;
|
||||
flex-grow: 1;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
overflow: auto;
|
||||
scroll-padding-top: 100px;
|
||||
scroll-behavior: smooth;
|
||||
|
||||
// Page Content Spacing (Could be converted to Project Setting toggle)
|
||||
font-size: 15px;
|
||||
line-height: 24px;
|
||||
--border-radius: 6px;
|
||||
--input-height: 60px;
|
||||
--input-padding: 16px; // (60 - 4 - 24) / 2
|
||||
--form-vertical-gap: 52px;
|
||||
|
||||
main {
|
||||
display: contents;
|
||||
|
||||
@@ -1,14 +1,15 @@
|
||||
# Projects
|
||||
|
||||
> A Project is a complete instance of Directus, including its **Database**, config file, asset storage, and any custom extensions. [Learn more about Projects](/concepts/projects/).
|
||||
> A Project is a complete instance of Directus, including its **Database**, config file, asset storage, and any custom
|
||||
> extensions. [Learn more about Projects](/concepts/projects/).
|
||||
|
||||
## Creating a Project
|
||||
|
||||
To install Directus, choose one of the following methods.
|
||||
|
||||
- [Command Line Interface (CLI)](/guides/installation/cli.md)
|
||||
- [Docker](/guides/installation/docker.md)
|
||||
- [Manually](/guides/installation/manual.md)
|
||||
- [Command Line Interface (CLI)](/guides/installation/cli)
|
||||
- [Docker](/guides/installation/docker)
|
||||
- [Manually](/guides/installation/manual)
|
||||
|
||||
## Configuring a Project
|
||||
|
||||
@@ -22,14 +23,14 @@ environment variables, each is explained in the following reference:
|
||||
1. Navigate to **Settings > Project Settings**
|
||||
2. Configure any of the following **branding fields**
|
||||
|
||||
- **Project Name** — The name used at the top of the [Navigation Bar](/concepts/application/#_2-navigation-bar) and on the login/public
|
||||
pages
|
||||
- **Project Name** — The name used at the top of the [Navigation Bar](/concepts/application/#_2-navigation-bar) and on
|
||||
the login/public pages
|
||||
- **Project URL** — The URL when clicking the logo at the top of the [Module Bar](/concepts/application/#_1-module-bar)
|
||||
- **Project Color** — The color used behind the logo at the top of the [Module Bar](/concepts/application/#_1-module-bar), on the
|
||||
login/public pages, and for the browser's FavIcon
|
||||
- **Project Logo** — A 40x40 pixel logo at the top of the [Module Bar](/concepts/application/#_1-module-bar) and on the login/public
|
||||
pages. The image is _inset_ within the 64x64 pixel square filled with the Project Color, so we recommend using a SVG
|
||||
or PNG logo with transparency to avoid a "boxy" look.
|
||||
- **Project Color** — The color used behind the logo at the top of the
|
||||
[Module Bar](/concepts/application/#_1-module-bar), on the login/public pages, and for the browser's FavIcon
|
||||
- **Project Logo** — A 40x40 pixel logo at the top of the [Module Bar](/concepts/application/#_1-module-bar) and on the
|
||||
login/public pages. The image is _inset_ within the 64x64 pixel square filled with the Project Color, so we recommend
|
||||
using a SVG or PNG logo with transparency to avoid a "boxy" look.
|
||||
|
||||
::: tip Browser FavIcon & Title
|
||||
|
||||
|
||||
@@ -7,8 +7,9 @@ pageClass: page-reference
|
||||
<div class="two-up">
|
||||
<div class="left">
|
||||
|
||||
> Files are the objects that contain information about the file managed through Directus. If you're looking for the actual file
|
||||
data, including thumbnails, see the [/assets](/reference/api/assets/) endpoint. [Learn more about Files](/concepts/files/).
|
||||
> Files are the objects that contain information about the file managed through Directus. If you're looking for the
|
||||
> actual file data, including thumbnails, see the [/assets](/reference/api/assets/) endpoint.
|
||||
> [Learn more about Files](/concepts/files/).
|
||||
|
||||
</div>
|
||||
<div class="right">
|
||||
@@ -45,16 +46,16 @@ Title for the file.
|
||||
Mimetype of the file.
|
||||
|
||||
`folder` **many-to-one**\
|
||||
What (virtual) folder the file is in. Many-to-one to [folders](/reference/api/folders/).
|
||||
What (virtual) folder the file is in. Many-to-one to [folders](/reference/api/rest/folders/).
|
||||
|
||||
`uploaded_by` **many-to-one**\
|
||||
Who uploaded the file. Many-to-one to [users](/reference/api/users/).
|
||||
Who uploaded the file. Many-to-one to [users](/reference/api/rest/users/).
|
||||
|
||||
`uploaded_on` **datetime**\
|
||||
When the file was uploaded.
|
||||
|
||||
`modified_by` **many-to-one**\
|
||||
Who updated the file last. Many-to-one to [users](/reference/api/users/).
|
||||
Who updated the file last. Many-to-one to [users](/reference/api/rest/users/).
|
||||
|
||||
`filesize` **number**\
|
||||
Size of the file in bytes.
|
||||
|
||||
134
package-lock.json
generated
134
package-lock.json
generated
@@ -18683,12 +18683,29 @@
|
||||
"@types/node": "*"
|
||||
}
|
||||
},
|
||||
"@types/linkify-it": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@types/linkify-it/-/linkify-it-3.0.0.tgz",
|
||||
"integrity": "sha512-x9OaQQTb1N2hPZ/LWJsqushexDvz7NgzuZxiRmZio44WPuolTZNHDBCrOxCzRVOMwamJRO2dWax5NbygOf1OTQ==",
|
||||
"dev": true
|
||||
},
|
||||
"@types/lodash": {
|
||||
"version": "4.14.168",
|
||||
"resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.168.tgz",
|
||||
"integrity": "sha512-oVfRvqHV/V6D1yifJbVRU3TMp8OT6o6BG+U9MkwuJ3U8/CsDHvalRpsxBqivn71ztOFZBTfJMvETbqHiaNSj7Q==",
|
||||
"dev": true
|
||||
},
|
||||
"@types/markdown-it": {
|
||||
"version": "12.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@types/markdown-it/-/markdown-it-12.0.1.tgz",
|
||||
"integrity": "sha512-mHfT8j/XkPb1uLEfs0/C3se6nd+webC2kcqcy8tgcVr0GDEONv/xaQzAN+aQvkxQXk/jC0Q6mPS+0xhFwRF35g==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@types/highlight.js": "^9.7.0",
|
||||
"@types/linkify-it": "*",
|
||||
"@types/mdurl": "*"
|
||||
}
|
||||
},
|
||||
"@types/marked": {
|
||||
"version": "1.2.2",
|
||||
"resolved": "https://registry.npmjs.org/@types/marked/-/marked-1.2.2.tgz",
|
||||
@@ -18704,6 +18721,12 @@
|
||||
"@types/unist": "*"
|
||||
}
|
||||
},
|
||||
"@types/mdurl": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/@types/mdurl/-/mdurl-1.0.2.tgz",
|
||||
"integrity": "sha512-eC4U9MlIcu2q0KQmXszyn5Akca/0jrQmwDRgpAMJai7qBWq4amIQhZyNau4VYGtCeALvW1/NtjzJJ567aZxfKA==",
|
||||
"dev": true
|
||||
},
|
||||
"@types/mime": {
|
||||
"version": "1.3.2",
|
||||
"resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.2.tgz",
|
||||
@@ -20790,6 +20813,42 @@
|
||||
"markdown-it-emoji": "^1.4.0",
|
||||
"markdown-it-table-of-contents": "^0.4.0",
|
||||
"prismjs": "^1.13.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"linkify-it": {
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-2.2.0.tgz",
|
||||
"integrity": "sha512-GnAl/knGn+i1U/wjBz3akz2stz+HrHLsxMwHQGofCDfPvlf+gDKN58UtfmUquTY4/MXeE2x7k19KQmeoZi94Iw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"uc.micro": "^1.0.1"
|
||||
}
|
||||
},
|
||||
"markdown-it": {
|
||||
"version": "8.4.2",
|
||||
"resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-8.4.2.tgz",
|
||||
"integrity": "sha512-GcRz3AWTqSUphY3vsUqQSFMbgR38a4Lh3GWlHRh/7MRwz8mcu9n2IO7HOh+bXHrR9kOPDl5RNCaEsrneb+xhHQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"argparse": "^1.0.7",
|
||||
"entities": "~1.1.1",
|
||||
"linkify-it": "^2.0.0",
|
||||
"mdurl": "^1.0.1",
|
||||
"uc.micro": "^1.0.5"
|
||||
}
|
||||
},
|
||||
"markdown-it-anchor": {
|
||||
"version": "5.3.0",
|
||||
"resolved": "https://registry.npmjs.org/markdown-it-anchor/-/markdown-it-anchor-5.3.0.tgz",
|
||||
"integrity": "sha512-/V1MnLL/rgJ3jkMWo84UR+K+jF1cxNG1a+KwqeXqTIJ+jtA8aWSHuigx8lTzauiIjBDbwF3NcWQMotd0Dm39jA==",
|
||||
"dev": true
|
||||
},
|
||||
"markdown-it-table-of-contents": {
|
||||
"version": "0.4.4",
|
||||
"resolved": "https://registry.npmjs.org/markdown-it-table-of-contents/-/markdown-it-table-of-contents-0.4.4.tgz",
|
||||
"integrity": "sha512-TAIHTHPwa9+ltKvKPWulm/beozQU41Ab+FIefRaQV1NRnpzwcV9QOe6wXQS5WLivm5Q/nlo0rl6laGkMDZE7Gw==",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"@vuepress/markdown-loader": {
|
||||
@@ -29225,6 +29284,14 @@
|
||||
"integrity": "sha512-cHEpEQHUg0f8XdtZCc2ZAhrHzKzT0MrFUTcvx+hfxYu7rGMDc5SKoXFh+n4YigxsHXRzc6OrCshdR1bWH6HHyg==",
|
||||
"dev": true
|
||||
},
|
||||
"front-matter": {
|
||||
"version": "4.0.2",
|
||||
"resolved": "https://registry.npmjs.org/front-matter/-/front-matter-4.0.2.tgz",
|
||||
"integrity": "sha512-I8ZuJ/qG92NWX8i5x1Y8qyj3vizhXS31OxjKDu3LKP+7/qBgfIKValiZIEwoVoJKUHlhWtYrktkxV1XsX+pPlg==",
|
||||
"requires": {
|
||||
"js-yaml": "^3.13.1"
|
||||
}
|
||||
},
|
||||
"fs-constants": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz",
|
||||
@@ -32985,10 +33052,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"linkify-it": {
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-2.2.0.tgz",
|
||||
"integrity": "sha512-GnAl/knGn+i1U/wjBz3akz2stz+HrHLsxMwHQGofCDfPvlf+gDKN58UtfmUquTY4/MXeE2x7k19KQmeoZi94Iw==",
|
||||
"dev": true,
|
||||
"version": "3.0.2",
|
||||
"resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-3.0.2.tgz",
|
||||
"integrity": "sha512-gDBO4aHNZS6coiZCKVhSNh43F9ioIL4JwRjLZPkoLIY4yZFwg264Y5lu2x6rb1Js42Gh6Yqm2f6L2AJcnkzinQ==",
|
||||
"requires": {
|
||||
"uc.micro": "^1.0.1"
|
||||
}
|
||||
@@ -33714,23 +33780,33 @@
|
||||
"dev": true
|
||||
},
|
||||
"markdown-it": {
|
||||
"version": "8.4.2",
|
||||
"resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-8.4.2.tgz",
|
||||
"integrity": "sha512-GcRz3AWTqSUphY3vsUqQSFMbgR38a4Lh3GWlHRh/7MRwz8mcu9n2IO7HOh+bXHrR9kOPDl5RNCaEsrneb+xhHQ==",
|
||||
"dev": true,
|
||||
"version": "12.0.4",
|
||||
"resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-12.0.4.tgz",
|
||||
"integrity": "sha512-34RwOXZT8kyuOJy25oJNJoulO8L0bTHYWXcdZBYZqFnjIy3NgjeoM3FmPXIOFQ26/lSHYMr8oc62B6adxXcb3Q==",
|
||||
"requires": {
|
||||
"argparse": "^1.0.7",
|
||||
"entities": "~1.1.1",
|
||||
"linkify-it": "^2.0.0",
|
||||
"argparse": "^2.0.1",
|
||||
"entities": "~2.1.0",
|
||||
"linkify-it": "^3.0.1",
|
||||
"mdurl": "^1.0.1",
|
||||
"uc.micro": "^1.0.5"
|
||||
},
|
||||
"dependencies": {
|
||||
"argparse": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
|
||||
"integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q=="
|
||||
},
|
||||
"entities": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/entities/-/entities-2.1.0.tgz",
|
||||
"integrity": "sha512-hCx1oky9PFrJ611mf0ifBLBRW8lUUVRlFolb5gWRfIELabBlbp9xZvrqZLZAs+NxFnbfQoeGd8wDkygjg7U85w=="
|
||||
}
|
||||
}
|
||||
},
|
||||
"markdown-it-anchor": {
|
||||
"version": "5.3.0",
|
||||
"resolved": "https://registry.npmjs.org/markdown-it-anchor/-/markdown-it-anchor-5.3.0.tgz",
|
||||
"integrity": "sha512-/V1MnLL/rgJ3jkMWo84UR+K+jF1cxNG1a+KwqeXqTIJ+jtA8aWSHuigx8lTzauiIjBDbwF3NcWQMotd0Dm39jA==",
|
||||
"dev": true
|
||||
"version": "7.0.2",
|
||||
"resolved": "https://registry.npmjs.org/markdown-it-anchor/-/markdown-it-anchor-7.0.2.tgz",
|
||||
"integrity": "sha512-UtYFAkce16mJlixXUMXUf14ZmOWK2YHLGKUpkZUn98w3qP8nVhb7k5sCBZmVHGMq3SpYtrxQ5XOdHQHRuLR40Q=="
|
||||
},
|
||||
"markdown-it-chain": {
|
||||
"version": "1.3.0",
|
||||
@@ -33766,10 +33842,9 @@
|
||||
}
|
||||
},
|
||||
"markdown-it-container": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/markdown-it-container/-/markdown-it-container-2.0.0.tgz",
|
||||
"integrity": "sha1-ABm0P9Au7+zi8ZYKKJX7qBpARpU=",
|
||||
"dev": true
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/markdown-it-container/-/markdown-it-container-3.0.0.tgz",
|
||||
"integrity": "sha512-y6oKTq4BB9OQuY/KLfk/O3ysFhB3IMYoIWhGJEidXt1NQFocFK2sA2t0NYZAMyMShAGL6x5OPIbrmXPIqaN9rw=="
|
||||
},
|
||||
"markdown-it-emoji": {
|
||||
"version": "1.4.0",
|
||||
@@ -33778,10 +33853,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"markdown-it-table-of-contents": {
|
||||
"version": "0.4.4",
|
||||
"resolved": "https://registry.npmjs.org/markdown-it-table-of-contents/-/markdown-it-table-of-contents-0.4.4.tgz",
|
||||
"integrity": "sha512-TAIHTHPwa9+ltKvKPWulm/beozQU41Ab+FIefRaQV1NRnpzwcV9QOe6wXQS5WLivm5Q/nlo0rl6laGkMDZE7Gw==",
|
||||
"dev": true
|
||||
"version": "0.5.2",
|
||||
"resolved": "https://registry.npmjs.org/markdown-it-table-of-contents/-/markdown-it-table-of-contents-0.5.2.tgz",
|
||||
"integrity": "sha512-6o+rxSwzXmXCUn1n8QGTSpgbcnHBG6lUU8x7A5Cssuq5vbfzTfitfGPvQ5PZkp+gP1NGS/DR2rkYqJPn0rbZ1A=="
|
||||
},
|
||||
"markdown-table": {
|
||||
"version": "1.1.3",
|
||||
@@ -33911,8 +33985,7 @@
|
||||
"mdurl": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz",
|
||||
"integrity": "sha1-/oWy7HWlkDfyrf7BAP1sYBdhFS4=",
|
||||
"dev": true
|
||||
"integrity": "sha1-/oWy7HWlkDfyrf7BAP1sYBdhFS4="
|
||||
},
|
||||
"media-typer": {
|
||||
"version": "0.3.0",
|
||||
@@ -44630,8 +44703,7 @@
|
||||
"uc.micro": {
|
||||
"version": "1.0.6",
|
||||
"resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-1.0.6.tgz",
|
||||
"integrity": "sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA==",
|
||||
"dev": true
|
||||
"integrity": "sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA=="
|
||||
},
|
||||
"uglify-js": {
|
||||
"version": "3.4.10",
|
||||
@@ -45597,6 +45669,14 @@
|
||||
"requires": {
|
||||
"@vuepress/shared-utils": "^1.2.0",
|
||||
"markdown-it-container": "^2.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"markdown-it-container": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/markdown-it-container/-/markdown-it-container-2.0.0.tgz",
|
||||
"integrity": "sha1-ABm0P9Au7+zi8ZYKKJX7qBpARpU=",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"vuepress-plugin-smooth-scroll": {
|
||||
|
||||
@@ -65,6 +65,7 @@
|
||||
"@types/jsonwebtoken": "^8.5.0",
|
||||
"@types/keyv": "^3.1.1",
|
||||
"@types/lodash": "^4.14.159",
|
||||
"@types/markdown-it": "^12.0.1",
|
||||
"@types/marked": "^1.1.0",
|
||||
"@types/mime-types": "^2.1.0",
|
||||
"@types/mocha": "^8.0.4",
|
||||
@@ -194,7 +195,12 @@
|
||||
"create-directus-project": "file:packages/create-directus-project",
|
||||
"directus": "file:api",
|
||||
"dompurify": "^2.2.6",
|
||||
"escape-string-regexp": "^4.0.0"
|
||||
"escape-string-regexp": "^4.0.0",
|
||||
"front-matter": "^4.0.2",
|
||||
"markdown-it": "^12.0.4",
|
||||
"markdown-it-anchor": "^7.0.2",
|
||||
"markdown-it-container": "^3.0.0",
|
||||
"markdown-it-table-of-contents": "^0.5.2"
|
||||
},
|
||||
"husky": {
|
||||
"hooks": {
|
||||
|
||||
Reference in New Issue
Block a user