diff --git a/.vitepress/config.ts b/.vitepress/config.ts index befcf5f0..cf9e81df 100644 --- a/.vitepress/config.ts +++ b/.vitepress/config.ts @@ -20,6 +20,8 @@ import { SwagColorCodingConfig } from "../../developer-documentation-vitepress/src/shopware/config"; +import {navigation as apisNavigation} from "./navigation/apis"; + const sections: SwagSectionsConfig[] = [ { title: 'Frontends', @@ -298,7 +300,12 @@ export default defineConfigWithTheme({ ignoreDeadLinks: true, themeConfig: { - ...navigation, // add sidebar and nav config + sidebar: { + ...navigation.sidebar, + ...apisNavigation, + }, + nav: navigation.nav, + // ...navigation, // add sidebar and nav config algolia: { indexName: "beta-developer-shopware", diff --git a/.vitepress/theme/index.ts b/.vitepress/theme/index.ts index 6b136ec0..6001b565 100644 --- a/.vitepress/theme/index.ts +++ b/.vitepress/theme/index.ts @@ -1,5 +1,6 @@ import {SWAGTheme} from "vitepress-shopware-docs"; import SwagRadialBg from "../../src/components/SwagRadialBg.vue"; +import OpenApi from "../../src/components/OpenApi.vue"; export default { ...SWAGTheme({ @@ -7,6 +8,9 @@ export default { 'layout-bottom': [ SwagRadialBg, ] + }, + enhanceApp({app}) { + app.component('OpenApi', OpenApi); } }), } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index d973e2a8..b4ce5138 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -14,6 +14,9 @@ importers: cross-env: specifier: ^7.0.3 version: 7.0.3 + highlight.js: + specifier: ^11.8.0 + version: 11.8.0 terser: specifier: ^5.17.3 version: 5.17.3 @@ -141,6 +144,9 @@ importers: lorem-ipsum: specifier: ^2.0.8 version: 2.0.8 + markdown-it: + specifier: ^13.0.1 + version: 13.0.1 mermaid: specifier: ^10.2.3 version: 10.2.3 @@ -8833,6 +8839,11 @@ packages: tapable: 2.2.1 dev: true + /entities@3.0.1: + resolution: {integrity: sha512-WiyBqoomrwMdFG1e0kqvASYfnlb0lp8M5o5Fw2OFq1hNZxxcNk8Ik0Xm7LxzBhuidnZB/UtBqVCgUz3kBOP51Q==} + engines: {node: '>=0.12'} + dev: true + /envinfo@7.10.0: resolution: {integrity: sha512-ZtUjZO6l5mwTHvc1L9+1q5p/R3wTopcfqMW8r5t8SJSKqeVI/LtajORwRFEKpEFuekjD0VBjwu1HMxL4UalIRw==} engines: {node: '>=4'} @@ -9795,6 +9806,11 @@ packages: resolution: {integrity: sha512-2bsegYkkHO+h/9MGbn6KWcE45cHZgPANo5LXF7EvWdT0yT2EguSVO1nDgU5c8+ZOPwp2vMNa7YFsJhVcDR9Sdg==} dev: true + /highlight.js@11.8.0: + resolution: {integrity: sha512-MedQhoqVdr0U6SSnWPzfiadUcDHfN/Wzq25AkXiQv9oiOO/sG0S7XkvpFIqWBl9Yq1UYyYOOVORs5UW2XlPyzg==} + engines: {node: '>=12.0.0'} + dev: false + /history@4.10.1: resolution: {integrity: sha512-36nwAD620w12kuzPAsyINPWJqlNbij+hpK1k9XRloDtym8mxzGYl2c17LnV6IAGB2Dmg4tEa7G7DlawS0+qjew==} dependencies: @@ -11264,6 +11280,12 @@ packages: resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} dev: true + /linkify-it@4.0.1: + resolution: {integrity: sha512-C7bfi1UZmoj8+PQx22XyeXCuBlokoyWQL5pWSP+EI6nzRylyThouddufc2c1NDIcP9k5agmN9fLpA7VNJfIiqw==} + dependencies: + uc.micro: 1.0.6 + dev: true + /liquid-json@0.3.1: resolution: {integrity: sha512-wUayTU8MS827Dam6MxgD72Ui+KOSF+u/eIqpatOtjnvgJ0+mnDq33uC2M7J0tPK+upe/DpUAuK4JUU89iBoNKQ==} engines: {node: '>=4'} @@ -11529,6 +11551,17 @@ packages: /mark.js@8.11.1: resolution: {integrity: sha512-1I+1qpDt4idfgLQG+BNWmrqku+7/2bi5nLf4YwF8y8zXvmfiTBY3PV3ZibfrjBueCByROpuBjLLFCajqkgYoLQ==} + /markdown-it@13.0.1: + resolution: {integrity: sha512-lTlxriVoy2criHP0JKRhO2VDG9c2ypWCsT237eDiLqi09rmbKoUetyGHq2uOIRoRS//kfoJckS0eUzzkDR+k2Q==} + hasBin: true + dependencies: + argparse: 2.0.1 + entities: 3.0.1 + linkify-it: 4.0.1 + mdurl: 1.0.1 + uc.micro: 1.0.6 + dev: true + /markdown-table@2.0.0: resolution: {integrity: sha512-Ezda85ToJUBhM6WGaG6veasyym+Tbs3cMAw/ZhOPqXiYsr0jgocBV3j3nx+4lk47plLlIqjwuTm/ywVI+zjJ/A==} dependencies: @@ -11714,7 +11747,6 @@ packages: /mdurl@1.0.1: resolution: {integrity: sha512-/sKlQJCBYVY9Ers9hqzKou4H6V5UWc/M59TH2dvkt+84itfnq7uFOMLpOiOS4ujvHP4etln18fmIxA5R5fll0g==} - dev: false /media-typer@0.3.0: resolution: {integrity: sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==} @@ -14735,6 +14767,10 @@ packages: hasBin: true dev: true + /uc.micro@1.0.6: + resolution: {integrity: sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA==} + dev: true + /ufo@1.1.2: resolution: {integrity: sha512-TrY6DsjTQQgyS3E3dBaOXf0TpPD8u9FVrVYmKVegJuFw51n/YB9XPt+U6ydzFG5ZIN7+DIjPbNmXoBj9esYhgQ==} diff --git a/src/[api]-api.md b/src/[api]-api.md new file mode 100644 index 00000000..3f519733 --- /dev/null +++ b/src/[api]-api.md @@ -0,0 +1,3 @@ +# {{ $params.api }} + + \ No newline at end of file diff --git a/src/[api]-api.paths.js b/src/[api]-api.paths.js new file mode 100644 index 00000000..2a865e5d --- /dev/null +++ b/src/[api]-api.paths.js @@ -0,0 +1,14 @@ +export default { + paths() { + return [ + { + params: {api: 'store'}, + content: 'This is content', + }, + { + params: {api: 'admin'}, + content: 'This is custom content', + } + ] + } +} \ No newline at end of file diff --git a/src/api.md b/src/api.md new file mode 100644 index 00000000..389fd4de --- /dev/null +++ b/src/api.md @@ -0,0 +1,9 @@ +--- +aside: false +sidebar: false +--- + + + \ No newline at end of file diff --git a/src/api/admin/endpoint/[method]-[path].md b/src/api/admin/endpoint/[method]-[path].md new file mode 100644 index 00000000..522af4d0 --- /dev/null +++ b/src/api/admin/endpoint/[method]-[path].md @@ -0,0 +1,9 @@ +# {{ $params.slug }} + + + +Test: {{ $params.slug }} + +{{ $params }} + + \ No newline at end of file diff --git a/src/api/admin/endpoint/[method]-[path].paths.js b/src/api/admin/endpoint/[method]-[path].paths.js new file mode 100644 index 00000000..60653fde --- /dev/null +++ b/src/api/admin/endpoint/[method]-[path].paths.js @@ -0,0 +1,7 @@ +import {makePaths} from "../../helpers"; + +export default { + paths() { + return makePaths('admin'); + } +} \ No newline at end of file diff --git a/src/api/admin/scheme/[slug].md b/src/api/admin/scheme/[slug].md new file mode 100644 index 00000000..3f519733 --- /dev/null +++ b/src/api/admin/scheme/[slug].md @@ -0,0 +1,3 @@ +# {{ $params.api }} + + \ No newline at end of file diff --git a/src/api/admin/scheme/[slug].paths.js b/src/api/admin/scheme/[slug].paths.js new file mode 100644 index 00000000..de34a51d --- /dev/null +++ b/src/api/admin/scheme/[slug].paths.js @@ -0,0 +1,14 @@ +export default { + paths() { + return [ + { + params: {slug: 'store'}, + content: 'This is content', + }, + { + params: {slug: 'admin'}, + content: 'This is custom content', + } + ] + } +} \ No newline at end of file diff --git a/src/api/helpers.ts b/src/api/helpers.ts new file mode 100644 index 00000000..bd123140 --- /dev/null +++ b/src/api/helpers.ts @@ -0,0 +1,30 @@ +import adminApi from "../components/adminapi.json"; +import storeApi from "../components/storeapi.json"; + +export const makePaths = (api: string) => { + const data = { + admin: adminApi, + store: storeApi, + }[api] || null; + + if (!data) { + throw "Incorrect api"; + } + + return Object.keys(adminApi.paths) + .reduce((reduced, path) => { + return Object.keys(adminApi.paths[path]) + .reduce((reduced, method) => { + reduced.push({ + path: path.split('/') + .splice(1) + .join('-') + .replace('{', '') + .replace('}', ''), + method: method.toLowerCase(), + }); + return reduced; + }, reduced); + }, []) + .map(route => ({params: {...route,}, content: ''})) +} \ No newline at end of file diff --git a/src/api/store/endpoint/[slug].md b/src/api/store/endpoint/[slug].md new file mode 100644 index 00000000..3f519733 --- /dev/null +++ b/src/api/store/endpoint/[slug].md @@ -0,0 +1,3 @@ +# {{ $params.api }} + + \ No newline at end of file diff --git a/src/api/store/endpoint/[slug].paths.js b/src/api/store/endpoint/[slug].paths.js new file mode 100644 index 00000000..de34a51d --- /dev/null +++ b/src/api/store/endpoint/[slug].paths.js @@ -0,0 +1,14 @@ +export default { + paths() { + return [ + { + params: {slug: 'store'}, + content: 'This is content', + }, + { + params: {slug: 'admin'}, + content: 'This is custom content', + } + ] + } +} \ No newline at end of file diff --git a/src/api/store/scheme/[slug].md b/src/api/store/scheme/[slug].md new file mode 100644 index 00000000..3f519733 --- /dev/null +++ b/src/api/store/scheme/[slug].md @@ -0,0 +1,3 @@ +# {{ $params.api }} + + \ No newline at end of file diff --git a/src/api/store/scheme/[slug].paths.js b/src/api/store/scheme/[slug].paths.js new file mode 100644 index 00000000..de34a51d --- /dev/null +++ b/src/api/store/scheme/[slug].paths.js @@ -0,0 +1,14 @@ +export default { + paths() { + return [ + { + params: {slug: 'store'}, + content: 'This is content', + }, + { + params: {slug: 'admin'}, + content: 'This is custom content', + } + ] + } +} \ No newline at end of file diff --git a/src/components/OpenAPIViewer.vue b/src/components/OpenAPIViewer.vue new file mode 100644 index 00000000..53b4fba6 --- /dev/null +++ b/src/components/OpenAPIViewer.vue @@ -0,0 +1,202 @@ + + + + + \ No newline at end of file diff --git a/src/components/OpenApi.vue b/src/components/OpenApi.vue new file mode 100644 index 00000000..d9ed5d9d --- /dev/null +++ b/src/components/OpenApi.vue @@ -0,0 +1,18 @@ + + + \ No newline at end of file diff --git a/src/components/OpenApiViewerEndpointParameters.vue b/src/components/OpenApiViewerEndpointParameters.vue new file mode 100644 index 00000000..43d84cac --- /dev/null +++ b/src/components/OpenApiViewerEndpointParameters.vue @@ -0,0 +1,64 @@ + + + \ No newline at end of file diff --git a/src/components/OpenApiViewerEndpointPlayground.vue b/src/components/OpenApiViewerEndpointPlayground.vue new file mode 100644 index 00000000..bd9750c6 --- /dev/null +++ b/src/components/OpenApiViewerEndpointPlayground.vue @@ -0,0 +1,65 @@ + + + \ No newline at end of file diff --git a/src/components/OpenApiViewerEndpointResponses.vue b/src/components/OpenApiViewerEndpointResponses.vue new file mode 100644 index 00000000..5409ca83 --- /dev/null +++ b/src/components/OpenApiViewerEndpointResponses.vue @@ -0,0 +1,32 @@ + + + \ No newline at end of file diff --git a/src/components/OpenApiViewerMagic.vue b/src/components/OpenApiViewerMagic.vue new file mode 100644 index 00000000..ea4998c3 --- /dev/null +++ b/src/components/OpenApiViewerMagic.vue @@ -0,0 +1,159 @@ + + + + + \ No newline at end of file diff --git a/src/components/OpenApiViewerSecuritySchemas.vue b/src/components/OpenApiViewerSecuritySchemas.vue new file mode 100644 index 00000000..1a6d61d8 --- /dev/null +++ b/src/components/OpenApiViewerSecuritySchemas.vue @@ -0,0 +1,45 @@ + + + + + \ No newline at end of file diff --git a/src/components/OpenApiViewerUnref.vue b/src/components/OpenApiViewerUnref.vue new file mode 100644 index 00000000..b2d588a3 --- /dev/null +++ b/src/components/OpenApiViewerUnref.vue @@ -0,0 +1,19 @@ + + + \ No newline at end of file diff --git a/src/components/openApi/markdown.ts b/src/components/openApi/markdown.ts new file mode 100644 index 00000000..c2811434 --- /dev/null +++ b/src/components/openApi/markdown.ts @@ -0,0 +1,30 @@ +import MarkdownIt from "markdown-it"; +import hljs from 'highlight.js'; +import * as shiki from "shiki"; + +export const render = async (value) => { + if (!value) { + return ''; + } + + const shikiRenderer = await shiki.getHighlighter({theme: 'nord', langs: ['js', 'json', 'php']}); + + const MarkdownRenderer = MarkdownIt({ + highlight: function (str, lang) { + + // use shiki renderer + return shikiRenderer.codeToHtml(str, {lang}); + + return ''; + if (lang && hljs.getLanguage(lang)) { + try { + return hljs.highlight(str, { language: lang }).value; + } catch (__) {} + } + + return ''; // use external default escaping + } + }); + + return MarkdownRenderer.render(value); +}; \ No newline at end of file diff --git a/src/components/openApi/openApi.ts b/src/components/openApi/openApi.ts new file mode 100644 index 00000000..ad633b6b --- /dev/null +++ b/src/components/openApi/openApi.ts @@ -0,0 +1,69 @@ +export class Document { + constructor(document) { + Object.keys(document).forEach((key) => this[key] = document[key]); + + this.components.schemas = Object.keys(this.components.schemas || {}) + .reduce((reduced, key) => { + reduced[key] = this.components.schemas[key]; + reduced[key].key = key; + return reduced; + }, {}); + + this.components.responses = Object.keys(this.components.responses || {}) + .reduce((reduced, key) => { + reduced[key] = this.components.responses[key]; + reduced[key].key = key; + return reduced; + }, {}); + + this.components.securitySchemes = Object.keys(this.components.securitySchemes || {}) + .reduce((reduced, key) => { + reduced[key] = this.components.securitySchemes[key]; + reduced[key].key = key; + + reduced[key].flows = Object.keys(reduced[key].flows || {}) + .map(flowKey => { + const flow = reduced[key].flows[flowKey]; + flow.key = flowKey; + return new Flow(flow); + }) + + reduced[key] = new SecurityScheme(reduced[key]); + + return reduced; + }, {}); + } + + static make(document) { + return new Document(document); + } +} + +export class SecurityScheme { + key: string; + + constructor(securityScheme) { + Object.keys(securityScheme).forEach((key) => this[key] = securityScheme[key]); + } + + get title() { + return { + oAuth: 'Security: OAuth 2.0', + }[this.key] || this.key; + } +} + +export class Flow { + key: string; + + constructor(flow) { + Object.keys(flow).forEach((key) => this[key] = flow[key]); + } + + get title() { + return { + password: 'Password OAuth Flow', + clientCredentials: 'Client Credentials OAuth Flow', + }[this.key] || this.key; + } +} \ No newline at end of file diff --git a/src/components/openApi/sample.ts b/src/components/openApi/sample.ts new file mode 100644 index 00000000..7ba7ff82 --- /dev/null +++ b/src/components/openApi/sample.ts @@ -0,0 +1,57 @@ +export class Sample { + hostname: string; + endpoint: string; + method: string; + + constructor(endpoint: string, method: string) { + this.endpoint = endpoint; + this.method = method; + this.hostname = 'http://localhost:8000'; + } +} + +export class PHPGuzzle extends Sample { + getCode() { + return `request('${this.method.toUpperCase()}', '${this.hostname}${this.endpoint}', [ + 'headers' => [ + 'Accept' => 'application/vnd.api+json, application/json', + 'Authorization' => '', + ], +]); + +echo $response->getBody();` + } +} + +export class HTTP extends Sample { + getCode() { + return `${this.method.toUpperCase()} ${this.endpoint} HTTP/1.1 +Accept: application/vnd.api+json, application/json +Authorization: +Host: ${this.hostname.split('//')[1]}` + } +} + +export class CURL extends Sample { + getCode() { + return `curl --request ${this.method.toUpperCase()} \\ + --url ${this.hostname}${this.endpoint} \\ + --header 'Accept: application/vnd.api+json, application/json' \\ + --header 'Authorization: '` + } +} + +export class Wget extends Sample { + getCode() { + return `wget --quiet \\ + --method ${this.method.toUpperCase()} \\ + --header 'Accept: application/vnd.api+json, application/json' \\ + --header 'Authorization: ' \\ + --output-document \\ + - ${this.hostname}${this.endpoint}`; + } +} \ No newline at end of file diff --git a/src/components/openApi/symbol.ts b/src/components/openApi/symbol.ts new file mode 100644 index 00000000..30891f0e --- /dev/null +++ b/src/components/openApi/symbol.ts @@ -0,0 +1 @@ +export const documentObjectSymbol = Symbol('documentObjectSymbol'); \ No newline at end of file diff --git a/src/components/page/OpenApiViewerPageEndpoint.vue b/src/components/page/OpenApiViewerPageEndpoint.vue new file mode 100644 index 00000000..6b50db27 --- /dev/null +++ b/src/components/page/OpenApiViewerPageEndpoint.vue @@ -0,0 +1,54 @@ + + + \ No newline at end of file diff --git a/src/components/page/OpenApiViewerPageResponse.vue b/src/components/page/OpenApiViewerPageResponse.vue new file mode 100644 index 00000000..811e170b --- /dev/null +++ b/src/components/page/OpenApiViewerPageResponse.vue @@ -0,0 +1,23 @@ + + + \ No newline at end of file diff --git a/src/components/page/OpenApiViewerPageSchema.vue b/src/components/page/OpenApiViewerPageSchema.vue new file mode 100644 index 00000000..000c9500 --- /dev/null +++ b/src/components/page/OpenApiViewerPageSchema.vue @@ -0,0 +1,35 @@ + + + \ No newline at end of file diff --git a/src/components/sidebar/OpenApiViewerSidebarEndpoints.vue b/src/components/sidebar/OpenApiViewerSidebarEndpoints.vue new file mode 100644 index 00000000..c01184b5 --- /dev/null +++ b/src/components/sidebar/OpenApiViewerSidebarEndpoints.vue @@ -0,0 +1,48 @@ + + + \ No newline at end of file diff --git a/src/components/sidebar/OpenApiViewerSidebarResponses.vue b/src/components/sidebar/OpenApiViewerSidebarResponses.vue new file mode 100644 index 00000000..2dbe3a2b --- /dev/null +++ b/src/components/sidebar/OpenApiViewerSidebarResponses.vue @@ -0,0 +1,20 @@ + + + \ No newline at end of file diff --git a/src/components/sidebar/OpenApiViewerSidebarSchemas.vue b/src/components/sidebar/OpenApiViewerSidebarSchemas.vue new file mode 100644 index 00000000..8e72d7ee --- /dev/null +++ b/src/components/sidebar/OpenApiViewerSidebarSchemas.vue @@ -0,0 +1,20 @@ + + + \ No newline at end of file