| /* |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| */ |
| |
| // Generates the `/services` documentation section from `data/services.json` |
| // (produced by `just generate docs`). Every service gets a page with language |
| // tabs, and every supported (service, binding) pair gets a deep-linkable page |
| // such as `/services/s3/python`. These routes are registered programmatically |
| // so they stay out of the autogenerated docs sidebar while remaining real, |
| // statically rendered URLs. |
| |
| const path = require("path"); |
| const fs = require("fs"); |
| |
| // Join path segments under the site's baseUrl, collapsing duplicate slashes. |
| // Avoids depending on @docusaurus/utils, which pnpm does not hoist to a place |
| // resolvable from this plugin file. |
| function joinUrl(parts) { |
| const joined = parts.join("/").replace(/\/{2,}/g, "/"); |
| return joined.startsWith("/") ? joined : `/${joined}`; |
| } |
| |
| module.exports = function servicesDocsPlugin(context) { |
| const { baseUrl } = context; |
| |
| return { |
| name: "opendal-services-docs", |
| |
| async loadContent() { |
| const dataPath = path.resolve(__dirname, "../data/services.json"); |
| const raw = fs.readFileSync(dataPath, "utf8"); |
| return JSON.parse(raw); |
| }, |
| |
| async contentLoaded({ content, actions }) { |
| const { createData, addRoute } = actions; |
| const { bindings, services } = content; |
| |
| const indexComponent = |
| "@site/src/components/services/ServicesIndex.jsx"; |
| const pageComponent = "@site/src/components/services/ServicePage.jsx"; |
| |
| // The index only needs a slim summary per service, not full snippets. |
| const summary = services.map((s) => ({ |
| name: s.name, |
| scheme: s.scheme, |
| bindings: s.examples.map((e) => e.binding), |
| configCount: s.configs.length, |
| })); |
| const indexData = await createData( |
| "services-index.json", |
| JSON.stringify({ bindings, services: summary }) |
| ); |
| addRoute({ |
| path: joinUrl([baseUrl, "services"]), |
| component: indexComponent, |
| modules: { data: indexData }, |
| exact: true, |
| }); |
| |
| for (const service of services) { |
| const data = await createData( |
| `service-${service.scheme}.json`, |
| JSON.stringify({ bindings, service }) |
| ); |
| addRoute({ |
| path: joinUrl([baseUrl, "services", service.scheme]), |
| component: pageComponent, |
| modules: { data }, |
| exact: true, |
| }); |
| for (const example of service.examples) { |
| addRoute({ |
| path: joinUrl([ |
| baseUrl, |
| "services", |
| service.scheme, |
| example.binding, |
| ]), |
| component: pageComponent, |
| modules: { data }, |
| exact: true, |
| }); |
| } |
| } |
| }, |
| }; |
| }; |