@octanejs/docusaurus 0.0.3 → 0.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +143 -5
- package/package.json +26 -4
- package/src/bin.js +1 -1
- package/src/client-components.tsrx +134 -0
- package/src/client.js +18 -0
- package/src/document.js +153 -0
- package/src/hydrate.js +52 -0
- package/src/manifest.js +89 -8
- package/src/route-modules.js +56 -0
- package/src/routes.js +133 -0
- package/src/server.js +64 -0
- package/src/theme/DocCategoryGeneratedIndexPage.js +1 -0
- package/src/theme/DocItem.js +1 -0
- package/src/theme/DocRoot.js +1 -0
- package/src/theme/DocTagDocListPage.js +1 -0
- package/src/theme/DocTagsListPage.js +1 -0
- package/src/theme/DocVersionRoot.js +1 -0
- package/src/theme/DocsRoot.js +1 -0
- package/src/theme/Root.js +1 -0
- package/src/theme/styles.css +183 -0
- package/src/theme-components.tsrx +462 -0
- package/src/theme.js +25 -0
- package/src/vite.js +50 -2
- package/types/client.d.ts +58 -0
- package/types/hydrate.d.ts +21 -0
- package/types/index.d.ts +63 -4
- package/types/server.d.ts +80 -0
- package/types/theme.d.ts +8 -0
- package/types/virtual.d.ts +10 -0
- package/types/vite.d.ts +12 -0
package/src/manifest.js
CHANGED
|
@@ -48,12 +48,22 @@ function moduleId(module) {
|
|
|
48
48
|
throw new TypeError(`Expected a Docusaurus module reference, received ${String(module)}.`);
|
|
49
49
|
}
|
|
50
50
|
|
|
51
|
+
function routeModules(value) {
|
|
52
|
+
if (typeof value === 'string' || (value && value.__import === true)) {
|
|
53
|
+
return moduleId(value);
|
|
54
|
+
}
|
|
55
|
+
if (Array.isArray(value)) return value.map(routeModules);
|
|
56
|
+
if (value && typeof value === 'object') {
|
|
57
|
+
return Object.fromEntries(
|
|
58
|
+
Object.entries(value).map(([name, item]) => [name, routeModules(item)]),
|
|
59
|
+
);
|
|
60
|
+
}
|
|
61
|
+
throw new TypeError(`Expected a Docusaurus route module, received ${String(value)}.`);
|
|
62
|
+
}
|
|
63
|
+
|
|
51
64
|
function normalizeRoute(route, index, parentId = 'root') {
|
|
52
65
|
const id = `${parentId}/${index}:${route.path}`;
|
|
53
|
-
const modules = {};
|
|
54
|
-
for (const [name, value] of Object.entries(route.modules ?? {})) {
|
|
55
|
-
modules[name] = Array.isArray(value) ? value.map(moduleId) : moduleId(value);
|
|
56
|
-
}
|
|
66
|
+
const modules = routeModules(route.modules ?? {});
|
|
57
67
|
const known = new Set([
|
|
58
68
|
'path',
|
|
59
69
|
'component',
|
|
@@ -79,9 +89,7 @@ function normalizeRoute(route, index, parentId = 'root') {
|
|
|
79
89
|
exact: route.exact === true,
|
|
80
90
|
...(route.priority === undefined ? {} : { priority: Number(route.priority) }),
|
|
81
91
|
...(Object.keys(modules).length === 0 ? {} : { modules }),
|
|
82
|
-
...(route.context === undefined
|
|
83
|
-
? {}
|
|
84
|
-
: { context: toJsonValue(route.context, `route(${route.path}).context`) }),
|
|
92
|
+
...(route.context === undefined ? {} : { context: routeModules(route.context) }),
|
|
85
93
|
...(route.props === undefined
|
|
86
94
|
? {}
|
|
87
95
|
: { props: toJsonValue(route.props, `route(${route.path}).props`) }),
|
|
@@ -154,6 +162,68 @@ async function createThemeAliases(plugins, siteDir) {
|
|
|
154
162
|
return { theme, themeOriginal, themeInit };
|
|
155
163
|
}
|
|
156
164
|
|
|
165
|
+
async function clientModules(plugins) {
|
|
166
|
+
const modules = [];
|
|
167
|
+
const seen = new Set();
|
|
168
|
+
for (const plugin of plugins) {
|
|
169
|
+
if (typeof plugin.getClientModules !== 'function') continue;
|
|
170
|
+
for (const supplied of (await plugin.getClientModules()) ?? []) {
|
|
171
|
+
if (typeof supplied !== 'string') {
|
|
172
|
+
throw new TypeError(
|
|
173
|
+
`Docusaurus plugin ${JSON.stringify(plugin.name)} returned a non-string client module.`,
|
|
174
|
+
);
|
|
175
|
+
}
|
|
176
|
+
const resolved = path.isAbsolute(supplied) ? supplied : path.resolve(plugin.path, supplied);
|
|
177
|
+
if (seen.has(resolved)) continue;
|
|
178
|
+
seen.add(resolved);
|
|
179
|
+
modules.push(resolved);
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
return modules;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
function siteManifest(siteConfig) {
|
|
186
|
+
return toJsonValue(
|
|
187
|
+
{
|
|
188
|
+
title: siteConfig.title,
|
|
189
|
+
tagline: siteConfig.tagline,
|
|
190
|
+
url: siteConfig.url,
|
|
191
|
+
baseUrl: siteConfig.baseUrl,
|
|
192
|
+
favicon: siteConfig.favicon,
|
|
193
|
+
noIndex: siteConfig.noIndex,
|
|
194
|
+
trailingSlash: siteConfig.trailingSlash,
|
|
195
|
+
themeConfig: siteConfig.themeConfig,
|
|
196
|
+
customFields: siteConfig.customFields,
|
|
197
|
+
},
|
|
198
|
+
'$.site',
|
|
199
|
+
);
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
function i18nManifest(i18n) {
|
|
203
|
+
return toJsonValue(
|
|
204
|
+
{
|
|
205
|
+
defaultLocale: i18n.defaultLocale,
|
|
206
|
+
locales: i18n.locales,
|
|
207
|
+
currentLocale: i18n.currentLocale,
|
|
208
|
+
localeConfigs: i18n.localeConfigs,
|
|
209
|
+
},
|
|
210
|
+
'$.i18n',
|
|
211
|
+
);
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
function documentManifest(props) {
|
|
215
|
+
const locale = props.i18n.localeConfigs[props.i18n.currentLocale];
|
|
216
|
+
return {
|
|
217
|
+
htmlAttributes: {
|
|
218
|
+
lang: String(locale.htmlLang),
|
|
219
|
+
dir: String(locale.direction),
|
|
220
|
+
},
|
|
221
|
+
headTags: String(props.headTags ?? ''),
|
|
222
|
+
preBodyTags: String(props.preBodyTags ?? ''),
|
|
223
|
+
postBodyTags: String(props.postBodyTags ?? ''),
|
|
224
|
+
};
|
|
225
|
+
}
|
|
226
|
+
|
|
157
227
|
function readJsonIfPresent(filename, fallback) {
|
|
158
228
|
if (!existsSync(filename)) return fallback;
|
|
159
229
|
return JSON.parse(readFileSync(filename, 'utf8'));
|
|
@@ -185,7 +255,11 @@ function contentMetadata(generatedFilesDir) {
|
|
|
185
255
|
export async function createDocusaurusManifest(loaded) {
|
|
186
256
|
const { props } = loaded.site;
|
|
187
257
|
const { siteDir, generatedFilesDir } = props;
|
|
188
|
-
const
|
|
258
|
+
const plugins = props.plugins ?? [];
|
|
259
|
+
const [themeAliases, discoveredClientModules] = await Promise.all([
|
|
260
|
+
createThemeAliases(plugins, siteDir),
|
|
261
|
+
clientModules(plugins),
|
|
262
|
+
]);
|
|
189
263
|
return {
|
|
190
264
|
schemaVersion: 1,
|
|
191
265
|
docusaurusVersion: loaded.docusaurusVersion,
|
|
@@ -193,6 +267,13 @@ export async function createDocusaurusManifest(loaded) {
|
|
|
193
267
|
generatedFilesDir,
|
|
194
268
|
outDir: props.outDir,
|
|
195
269
|
baseUrl: props.baseUrl,
|
|
270
|
+
site: siteManifest(props.siteConfig),
|
|
271
|
+
i18n: i18nManifest(props.i18n),
|
|
272
|
+
siteMetadata: toJsonValue(props.siteMetadata, '$.siteMetadata'),
|
|
273
|
+
document: documentManifest(props),
|
|
274
|
+
assets: {
|
|
275
|
+
clientModules: discoveredClientModules,
|
|
276
|
+
},
|
|
196
277
|
routesPaths: [...props.routesPaths],
|
|
197
278
|
routes: props.routes.map((route, index) => normalizeRoute(route, index)),
|
|
198
279
|
globalData: readJsonIfPresent(path.join(generatedFilesDir, 'globalData.json'), {}),
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
function appendQuery(path, query) {
|
|
2
|
+
if (query === undefined) return path;
|
|
3
|
+
const search = new URLSearchParams();
|
|
4
|
+
for (const key of Object.keys(query).sort()) {
|
|
5
|
+
const value = query[key];
|
|
6
|
+
if (Array.isArray(value)) {
|
|
7
|
+
for (const item of value) search.append(key, String(item));
|
|
8
|
+
} else if (value !== undefined) {
|
|
9
|
+
search.append(key, String(value));
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
const serialized = search.toString();
|
|
13
|
+
const separator = path.includes('?') ? '&' : '?';
|
|
14
|
+
return serialized === '' ? path : `${path}${separator}${serialized}`;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export function docusaurusModuleKey(reference) {
|
|
18
|
+
return typeof reference === 'string' ? reference : appendQuery(reference.path, reference.query);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
function isImportedModule(value) {
|
|
22
|
+
return (
|
|
23
|
+
value !== null &&
|
|
24
|
+
typeof value === 'object' &&
|
|
25
|
+
value.__import === true &&
|
|
26
|
+
typeof value.path === 'string'
|
|
27
|
+
);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function collectModuleReferences(value, result) {
|
|
31
|
+
if (typeof value === 'string' || isImportedModule(value)) {
|
|
32
|
+
const key = docusaurusModuleKey(value);
|
|
33
|
+
result.set(key, key);
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
if (Array.isArray(value)) {
|
|
37
|
+
for (const item of value) collectModuleReferences(item, result);
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
if (value !== null && typeof value === 'object') {
|
|
41
|
+
for (const item of Object.values(value)) collectModuleReferences(item, result);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function collectRouteReferences(route, result) {
|
|
46
|
+
collectModuleReferences(route.component, result);
|
|
47
|
+
collectModuleReferences(route.modules, result);
|
|
48
|
+
collectModuleReferences(route.context, result);
|
|
49
|
+
for (const child of route.children ?? []) collectRouteReferences(child, result);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export function collectDocusaurusRouteModuleReferences(routes) {
|
|
53
|
+
const result = new Map();
|
|
54
|
+
for (const route of routes) collectRouteReferences(route, result);
|
|
55
|
+
return result;
|
|
56
|
+
}
|
package/src/routes.js
ADDED
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
import { createElement } from 'octane';
|
|
2
|
+
import { DocusaurusRouteRenderer } from './client-components.tsrx';
|
|
3
|
+
import { docusaurusModuleKey } from './route-modules.js';
|
|
4
|
+
|
|
5
|
+
function isImportedModule(value) {
|
|
6
|
+
return (
|
|
7
|
+
value !== null &&
|
|
8
|
+
typeof value === 'object' &&
|
|
9
|
+
value.__import === true &&
|
|
10
|
+
typeof value.path === 'string'
|
|
11
|
+
);
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
function moduleValue(module) {
|
|
15
|
+
if (
|
|
16
|
+
module === null ||
|
|
17
|
+
typeof module !== 'object' ||
|
|
18
|
+
!Object.prototype.hasOwnProperty.call(module, 'default')
|
|
19
|
+
) {
|
|
20
|
+
return module;
|
|
21
|
+
}
|
|
22
|
+
const value = module.default;
|
|
23
|
+
if (typeof value === 'function' || (value !== null && typeof value === 'object')) {
|
|
24
|
+
for (const [name, exported] of Object.entries(module)) {
|
|
25
|
+
if (name !== 'default') value[name] = exported;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
return value;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
async function loadModule(reference, registry, cache) {
|
|
32
|
+
const key = docusaurusModuleKey(reference);
|
|
33
|
+
const importer = registry[key];
|
|
34
|
+
if (typeof importer !== 'function') {
|
|
35
|
+
throw new Error(
|
|
36
|
+
`[@octanejs/docusaurus] No route importer was generated for ${JSON.stringify(key)}.`,
|
|
37
|
+
);
|
|
38
|
+
}
|
|
39
|
+
let pending = cache.get(key);
|
|
40
|
+
if (pending === undefined) {
|
|
41
|
+
pending = Promise.resolve().then(importer);
|
|
42
|
+
cache.set(key, pending);
|
|
43
|
+
pending.catch(() => {
|
|
44
|
+
if (cache.get(key) === pending) cache.delete(key);
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
return moduleValue(await pending);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
async function loadRouteModules(value, registry, cache) {
|
|
51
|
+
if (typeof value === 'string' || isImportedModule(value)) {
|
|
52
|
+
return loadModule(value, registry, cache);
|
|
53
|
+
}
|
|
54
|
+
if (Array.isArray(value)) {
|
|
55
|
+
return Promise.all(value.map((item) => loadRouteModules(item, registry, cache)));
|
|
56
|
+
}
|
|
57
|
+
if (value !== null && typeof value === 'object') {
|
|
58
|
+
const entries = await Promise.all(
|
|
59
|
+
Object.entries(value).map(async ([name, item]) => [
|
|
60
|
+
name,
|
|
61
|
+
await loadRouteModules(item, registry, cache),
|
|
62
|
+
]),
|
|
63
|
+
);
|
|
64
|
+
return Object.fromEntries(entries);
|
|
65
|
+
}
|
|
66
|
+
return value;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
function routePath(route, parentPath) {
|
|
70
|
+
let pathname = route.path;
|
|
71
|
+
if (parentPath !== undefined && pathname.startsWith('/')) {
|
|
72
|
+
if (pathname === parentPath) {
|
|
73
|
+
pathname = '';
|
|
74
|
+
} else {
|
|
75
|
+
const prefix = parentPath.endsWith('/') ? parentPath : `${parentPath}/`;
|
|
76
|
+
if (pathname.startsWith(prefix)) pathname = pathname.slice(prefix.length);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
if (
|
|
80
|
+
pathname === '' ||
|
|
81
|
+
pathname === '*' ||
|
|
82
|
+
route.exact === true ||
|
|
83
|
+
(route.children !== undefined && route.children.length > 0)
|
|
84
|
+
) {
|
|
85
|
+
return pathname;
|
|
86
|
+
}
|
|
87
|
+
return pathname.endsWith('/') ? `${pathname}*` : `${pathname}/*`;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
function createRouteComponent(route, Component, modules, context) {
|
|
91
|
+
return function DocusaurusResolvedRoute() {
|
|
92
|
+
return createElement(DocusaurusRouteRenderer, {
|
|
93
|
+
Component,
|
|
94
|
+
context,
|
|
95
|
+
modules,
|
|
96
|
+
route,
|
|
97
|
+
});
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
function createRoute(route, registry, cache, parentPath) {
|
|
102
|
+
return {
|
|
103
|
+
id: route.id,
|
|
104
|
+
path: routePath(route, parentPath),
|
|
105
|
+
handle: {
|
|
106
|
+
docusaurus: route,
|
|
107
|
+
},
|
|
108
|
+
async lazy() {
|
|
109
|
+
const [Component, modules, context] = await Promise.all([
|
|
110
|
+
loadModule(route.component, registry, cache),
|
|
111
|
+
loadRouteModules(route.modules ?? {}, registry, cache),
|
|
112
|
+
loadRouteModules(route.context ?? {}, registry, cache),
|
|
113
|
+
]);
|
|
114
|
+
if (typeof Component !== 'function') {
|
|
115
|
+
throw new TypeError(
|
|
116
|
+
`[@octanejs/docusaurus] Route ${JSON.stringify(route.path)} component ` +
|
|
117
|
+
`${JSON.stringify(docusaurusModuleKey(route.component))} has no default component export.`,
|
|
118
|
+
);
|
|
119
|
+
}
|
|
120
|
+
return {
|
|
121
|
+
Component: createRouteComponent(route, Component, modules, context),
|
|
122
|
+
};
|
|
123
|
+
},
|
|
124
|
+
children: (route.children ?? []).map((child) =>
|
|
125
|
+
createRoute(child, registry, cache, route.path),
|
|
126
|
+
),
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
export function createDocusaurusRoutes(manifest, registry) {
|
|
131
|
+
const cache = new Map();
|
|
132
|
+
return manifest.routes.map((route) => createRoute(route, registry, cache));
|
|
133
|
+
}
|
package/src/server.js
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { prerender } from 'octane/static';
|
|
2
|
+
import { createStaticHandler, createStaticRouter } from '@octanejs/remix-router';
|
|
3
|
+
import { DocusaurusRouterProvider } from './client-components.tsrx';
|
|
4
|
+
import { renderDocusaurusDocument } from './document.js';
|
|
5
|
+
import { createDocusaurusRoutes } from './routes.js';
|
|
6
|
+
|
|
7
|
+
export { renderDocusaurusDocument };
|
|
8
|
+
|
|
9
|
+
function toRequest(value) {
|
|
10
|
+
if (value instanceof Request) return value;
|
|
11
|
+
return new Request(new URL(value, 'http://localhost'));
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export function createDocusaurusStaticHandler(manifest, registry, options) {
|
|
15
|
+
return createStaticHandler(createDocusaurusRoutes(manifest, registry), options);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export async function prerenderDocusaurusRoute(request, manifest, registry, options = {}) {
|
|
19
|
+
const { basename, requestContext, ...renderOptions } = options;
|
|
20
|
+
const handler = createDocusaurusStaticHandler(
|
|
21
|
+
manifest,
|
|
22
|
+
registry,
|
|
23
|
+
basename === undefined ? undefined : { basename },
|
|
24
|
+
);
|
|
25
|
+
const context = await handler.query(
|
|
26
|
+
toRequest(request),
|
|
27
|
+
requestContext === undefined ? undefined : { requestContext },
|
|
28
|
+
);
|
|
29
|
+
if (context instanceof Response) return context;
|
|
30
|
+
|
|
31
|
+
const router = createStaticRouter(handler.dataRoutes, context);
|
|
32
|
+
// Use the hydration provider on both sides so Octane adopts the same
|
|
33
|
+
// component and control-flow ranges. Router effects are inert on the server.
|
|
34
|
+
const result = await prerender(
|
|
35
|
+
DocusaurusRouterProvider,
|
|
36
|
+
{
|
|
37
|
+
manifest,
|
|
38
|
+
router,
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
headChannel: 'separate',
|
|
42
|
+
...renderOptions,
|
|
43
|
+
},
|
|
44
|
+
);
|
|
45
|
+
return {
|
|
46
|
+
...result,
|
|
47
|
+
context,
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export async function prerenderDocusaurusDocument(request, manifest, registry, options = {}) {
|
|
52
|
+
const { document: documentOptions = {}, ...renderOptions } = options;
|
|
53
|
+
const result = await prerenderDocusaurusRoute(request, manifest, registry, renderOptions);
|
|
54
|
+
if (result instanceof Response) return result;
|
|
55
|
+
const bodyHtml = result.html;
|
|
56
|
+
return {
|
|
57
|
+
...result,
|
|
58
|
+
bodyHtml,
|
|
59
|
+
html: renderDocusaurusDocument(result, manifest, {
|
|
60
|
+
...documentOptions,
|
|
61
|
+
nonce: documentOptions.nonce ?? renderOptions.nonce,
|
|
62
|
+
}),
|
|
63
|
+
};
|
|
64
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { DocCategoryGeneratedIndexPage as default } from '../theme-components.tsrx';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { DocItem as default } from '../theme-components.tsrx';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { DocRoot as default } from '../theme-components.tsrx';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { DocTagDocListPage as default } from '../theme-components.tsrx';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { DocTagsListPage as default } from '../theme-components.tsrx';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { DocVersionRoot as default } from '../theme-components.tsrx';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { DocsRoot as default } from '../theme-components.tsrx';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { Root as default } from '../theme-components.tsrx';
|
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
.octane-docusaurus {
|
|
2
|
+
--octane-docs-accent: #5a45ff;
|
|
3
|
+
--octane-docs-border: #d9dce5;
|
|
4
|
+
--octane-docs-muted: #5f6574;
|
|
5
|
+
--octane-docs-surface: #f7f7fa;
|
|
6
|
+
color: #1d2029;
|
|
7
|
+
font-family:
|
|
8
|
+
Inter,
|
|
9
|
+
ui-sans-serif,
|
|
10
|
+
system-ui,
|
|
11
|
+
-apple-system,
|
|
12
|
+
BlinkMacSystemFont,
|
|
13
|
+
'Segoe UI',
|
|
14
|
+
sans-serif;
|
|
15
|
+
line-height: 1.6;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
.octane-docusaurus a {
|
|
19
|
+
color: var(--octane-docs-accent);
|
|
20
|
+
text-decoration-thickness: 0.08em;
|
|
21
|
+
text-underline-offset: 0.16em;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
.octane-docs-navbar {
|
|
25
|
+
align-items: center;
|
|
26
|
+
border-bottom: 1px solid var(--octane-docs-border);
|
|
27
|
+
display: flex;
|
|
28
|
+
gap: 1.5rem;
|
|
29
|
+
min-height: 3.75rem;
|
|
30
|
+
padding: 0 1.5rem;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
.octane-docs-navbar__brand {
|
|
34
|
+
color: inherit;
|
|
35
|
+
font-size: 1.05rem;
|
|
36
|
+
font-weight: 700;
|
|
37
|
+
text-decoration: none;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
.octane-docs-navbar__items {
|
|
41
|
+
align-items: center;
|
|
42
|
+
display: flex;
|
|
43
|
+
gap: 1rem;
|
|
44
|
+
list-style: none;
|
|
45
|
+
margin: 0 0 0 auto;
|
|
46
|
+
padding: 0;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
.octane-docs-layout {
|
|
50
|
+
display: grid;
|
|
51
|
+
grid-template-columns: minmax(13rem, 17rem) minmax(0, 1fr);
|
|
52
|
+
margin: 0 auto;
|
|
53
|
+
max-width: 90rem;
|
|
54
|
+
min-height: calc(100vh - 7.5rem);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
.octane-docs-sidebar {
|
|
58
|
+
border-right: 1px solid var(--octane-docs-border);
|
|
59
|
+
padding: 1.5rem;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
.octane-docs-sidebar ul {
|
|
63
|
+
list-style: none;
|
|
64
|
+
margin: 0;
|
|
65
|
+
padding: 0;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
.octane-docs-sidebar ul ul {
|
|
69
|
+
border-left: 1px solid var(--octane-docs-border);
|
|
70
|
+
margin: 0.35rem 0 0.75rem 0.45rem;
|
|
71
|
+
padding-left: 0.85rem;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
.octane-docs-sidebar a {
|
|
75
|
+
border-radius: 0.35rem;
|
|
76
|
+
color: inherit;
|
|
77
|
+
display: block;
|
|
78
|
+
padding: 0.35rem 0.5rem;
|
|
79
|
+
text-decoration: none;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
.octane-docs-sidebar a[aria-current='page'] {
|
|
83
|
+
background: color-mix(in srgb, var(--octane-docs-accent) 12%, transparent);
|
|
84
|
+
color: var(--octane-docs-accent);
|
|
85
|
+
font-weight: 650;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
.octane-docs-sidebar__category {
|
|
89
|
+
color: var(--octane-docs-muted);
|
|
90
|
+
display: block;
|
|
91
|
+
font-size: 0.8rem;
|
|
92
|
+
font-weight: 700;
|
|
93
|
+
letter-spacing: 0.045em;
|
|
94
|
+
margin: 0.75rem 0 0.25rem;
|
|
95
|
+
text-transform: uppercase;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
.octane-docs-main {
|
|
99
|
+
min-width: 0;
|
|
100
|
+
padding: clamp(1.5rem, 4vw, 4rem);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
.octane-docs-article,
|
|
104
|
+
.octane-docs-list-page {
|
|
105
|
+
margin: 0 auto;
|
|
106
|
+
max-width: 52rem;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
.octane-docs-paginator {
|
|
110
|
+
border-top: 1px solid var(--octane-docs-border);
|
|
111
|
+
display: grid;
|
|
112
|
+
gap: 1rem;
|
|
113
|
+
grid-template-columns: repeat(2, minmax(0, 1fr));
|
|
114
|
+
margin-top: 3rem;
|
|
115
|
+
padding-top: 1.5rem;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
.octane-docs-paginator__next {
|
|
119
|
+
text-align: right;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
.octane-docs-card-list {
|
|
123
|
+
display: grid;
|
|
124
|
+
gap: 1rem;
|
|
125
|
+
list-style: none;
|
|
126
|
+
padding: 0;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
.octane-docs-card {
|
|
130
|
+
border: 1px solid var(--octane-docs-border);
|
|
131
|
+
border-radius: 0.6rem;
|
|
132
|
+
padding: 1rem 1.15rem;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
.octane-docs-footer {
|
|
136
|
+
background: var(--octane-docs-surface);
|
|
137
|
+
border-top: 1px solid var(--octane-docs-border);
|
|
138
|
+
padding: 2rem 1.5rem;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
.octane-docs-footer__links {
|
|
142
|
+
display: grid;
|
|
143
|
+
gap: 2rem;
|
|
144
|
+
grid-template-columns: repeat(auto-fit, minmax(10rem, 1fr));
|
|
145
|
+
list-style: none;
|
|
146
|
+
margin: 0 auto 1.5rem;
|
|
147
|
+
max-width: 70rem;
|
|
148
|
+
padding: 0;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
.octane-docs-footer__items {
|
|
152
|
+
list-style: none;
|
|
153
|
+
padding: 0;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
.octane-docs-footer__copyright {
|
|
157
|
+
color: var(--octane-docs-muted);
|
|
158
|
+
margin: 0 auto;
|
|
159
|
+
max-width: 70rem;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
@media (max-width: 48rem) {
|
|
163
|
+
.octane-docs-navbar {
|
|
164
|
+
align-items: flex-start;
|
|
165
|
+
flex-direction: column;
|
|
166
|
+
gap: 0.5rem;
|
|
167
|
+
padding-block: 0.85rem;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
.octane-docs-navbar__items {
|
|
171
|
+
flex-wrap: wrap;
|
|
172
|
+
margin-left: 0;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
.octane-docs-layout {
|
|
176
|
+
display: block;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
.octane-docs-sidebar {
|
|
180
|
+
border-bottom: 1px solid var(--octane-docs-border);
|
|
181
|
+
border-right: 0;
|
|
182
|
+
}
|
|
183
|
+
}
|