@startupjs-ui/docs 0.1.3

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.
Files changed (51) hide show
  1. package/CHANGELOG.md +19 -0
  2. package/README.md +99 -0
  3. package/client/app/Layout/Sidebar/Content/Docs/index.js +118 -0
  4. package/client/app/Layout/Sidebar/Content/Docs/index.styl +12 -0
  5. package/client/app/Layout/Sidebar/Content/Options/index.js +52 -0
  6. package/client/app/Layout/Sidebar/Content/Options/index.styl +11 -0
  7. package/client/app/Layout/Sidebar/Content/index.js +38 -0
  8. package/client/app/Layout/Sidebar/Content/index.styl +35 -0
  9. package/client/app/Layout/Sidebar/index.js +24 -0
  10. package/client/app/Layout/index.js +97 -0
  11. package/client/app/Layout/index.styl +31 -0
  12. package/client/app/constants.styl +1 -0
  13. package/client/app/index.js +5 -0
  14. package/client/app/pages/PDoc/index.js +46 -0
  15. package/client/app/pages/PDoc/index.styl +21 -0
  16. package/client/app/pages/PHome/index.js +33 -0
  17. package/client/app/pages/index.js +2 -0
  18. package/client/app/routes.js +15 -0
  19. package/client/clientHelpers/getTitle.js +11 -0
  20. package/client/clientHelpers/hooks/index.js +6 -0
  21. package/client/clientHelpers/hooks/useLang.js +12 -0
  22. package/client/clientHelpers/hooks/useLocalStorage.js +37 -0
  23. package/client/clientHelpers/hooks/useLocalWithDefault.js +18 -0
  24. package/client/clientHelpers/hooks/useShowGrid.js +6 -0
  25. package/client/clientHelpers/hooks/useShowSizes.js +6 -0
  26. package/client/clientHelpers/hooks/useValidateWidth.js +6 -0
  27. package/client/clientHelpers/index.js +2 -0
  28. package/client/components/Props/Constructor/Table/index.js +10 -0
  29. package/client/components/Props/Constructor/Table/index.styl +2 -0
  30. package/client/components/Props/Constructor/Tbody/index.js +9 -0
  31. package/client/components/Props/Constructor/Td/index.js +10 -0
  32. package/client/components/Props/Constructor/Td/index.styl +4 -0
  33. package/client/components/Props/Constructor/Thead/index.js +9 -0
  34. package/client/components/Props/Constructor/Tr/index.js +11 -0
  35. package/client/components/Props/Constructor/Tr/index.styl +6 -0
  36. package/client/components/Props/Constructor/TypeCell/index.js +55 -0
  37. package/client/components/Props/Constructor/ValueCell/index.js +246 -0
  38. package/client/components/Props/Constructor/index.js +84 -0
  39. package/client/components/Props/Constructor/index.styl +55 -0
  40. package/client/components/Props/Renderer/GridVisualizer/index.js +88 -0
  41. package/client/components/Props/Renderer/GridVisualizer/index.styl +108 -0
  42. package/client/components/Props/Renderer/index.js +44 -0
  43. package/client/components/Props/index.js +160 -0
  44. package/client/components/Props/index.styl +25 -0
  45. package/client/components/Sandbox/index.js +64 -0
  46. package/client/components/Sandbox/index.styl +2 -0
  47. package/client/components/index.js +2 -0
  48. package/client/const/index.js +2 -0
  49. package/docsContext.js +17 -0
  50. package/index.js +13 -0
  51. package/package.json +29 -0
package/CHANGELOG.md ADDED
@@ -0,0 +1,19 @@
1
+ # Change Log
2
+
3
+ All notable changes to this project will be documented in this file.
4
+ See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
+
6
+ ## [0.1.3](https://github.com/startupjs/startupjs-ui/compare/v0.1.2...v0.1.3) (2025-12-29)
7
+
8
+ **Note:** Version bump only for package @startupjs-ui/docs
9
+
10
+
11
+
12
+
13
+
14
+ ## [0.1.2](https://github.com/startupjs/startupjs-ui/compare/v0.1.1...v0.1.2) (2025-12-29)
15
+
16
+
17
+ ### Features
18
+
19
+ * add mdx and docs packages. Refactor docs to get rid of any @startupjs/ui usage and use startupjs-ui instead ([703c926](https://github.com/startupjs/startupjs-ui/commit/703c92636efb0421ffd11783f692fc892b74018f))
package/README.md ADDED
@@ -0,0 +1,99 @@
1
+ # startupjs docs
2
+ > MDX Documentation generator
3
+
4
+ ## TODO:
5
+
6
+ - currently only the Sandbox is usable, still need to update the docs app fully to use the new Expo project and new 'startupjs-ui' components in it.
7
+
8
+ ## Prerequisites
9
+
10
+ You must be using `@startupjs/app` for routing.
11
+
12
+ You can create a new application with the routing system using the `routing` template: `npx startupjs init myapp -t routing`
13
+
14
+ ## Installation
15
+
16
+ ```sh
17
+ yarn add @startupjs/docs
18
+ ```
19
+
20
+ ## Requirements
21
+
22
+ ```
23
+ react: 16.9 - 17
24
+ react-native: >= 0.61.4 < 0.64.0
25
+ startupjs: >= 0.33.0
26
+ ```
27
+
28
+ ## Usage
29
+
30
+ 1. Create the `docs/` folder in your project root.
31
+
32
+ 2. Create `docs/index.js` file with the following content:
33
+ ```js
34
+ import docs from '@startupjs-ui/docs'
35
+ export default docs({
36
+ typography: {
37
+ type: 'mdx',
38
+ // different titles for mdx documentation in English and Russian
39
+ title: {
40
+ en: 'Typography',
41
+ ru: 'Типографика'
42
+ },
43
+ // different components to display for English and Russian documentation
44
+ component: {
45
+ en: require('../components/typography/Typography.en.mdx').default,
46
+ ru: require('../components/typography/Typography.ru.mdx').default
47
+ }
48
+ },
49
+ cssGuide: {
50
+ type: 'mdx',
51
+ // the same title for both English and Russian mdx documentation
52
+ title: 'Typography',
53
+ // the same component to display for English and Russian documentation
54
+ component: require('../components/typography/Typography.en.mdx').default
55
+ },
56
+ // docs in collapse
57
+ // items have the same api as mdx docs
58
+ components: {
59
+ type: 'collapse',
60
+ title: {
61
+ en: 'Components',
62
+ ru: 'Компоненты'
63
+ },
64
+ items: {
65
+ Button: {
66
+ type: 'mdx',
67
+ title: {
68
+ en: 'Button',
69
+ ru: 'Кнопка'
70
+ }
71
+ component: {
72
+ en: require('../components/Button/Button.en.mdx').default,
73
+ ru: require('../components/Button/Button.ru.mdx').default
74
+ }
75
+ },
76
+ Card: {
77
+ type: 'mdx',
78
+ title: 'Card',
79
+ component: require('../components/Card/Card.en.mdx').default
80
+ }
81
+ }
82
+ }
83
+ })
84
+ ```
85
+
86
+ 3. Add client-side `docs` app to your `Root/App.js` file:
87
+
88
+ ```js
89
+ import docs from '../docs'
90
+ // ...
91
+ <App
92
+ apps={{ main, docs }}
93
+ // ...
94
+ />
95
+ ```
96
+
97
+ ## License
98
+
99
+ MIT
@@ -0,0 +1,118 @@
1
+ import React, { useCallback, useEffect, useMemo } from 'react'
2
+ import { pug, observer, useModel, useLocal } from 'startupjs'
3
+ import { pathFor } from 'startupjs/app'
4
+ import { useMedia, Menu, Collapse } from '@startupjs/ui'
5
+ import { faAngleRight } from '@fortawesome/free-solid-svg-icons/faAngleRight'
6
+ import { getTitle, useLang } from '../../../../../clientHelpers'
7
+ import { useDocsContext } from '../../../../../../docsContext'
8
+ import './index.styl'
9
+
10
+ const MenuItem = observer(function MenuItemComponent ({
11
+ active,
12
+ doc,
13
+ docName,
14
+ docPath,
15
+ nestingLevel,
16
+ superPath
17
+ }) {
18
+ const [lang] = useLang()
19
+ const { desktop } = useMedia()
20
+ const $mainSidebar = useModel('_session.Sidebar.mainSidebar')
21
+ const $openedCollapses = useModel('_session.SidebarCollapses')
22
+
23
+ const menuItemStyle = useMemo(() => ({ paddingLeft: nestingLevel * 24 }), [nestingLevel])
24
+ const title = useMemo(() => getTitle(doc, lang), [doc, lang])
25
+ const rootPath = useMemo(() => pathFor('docs:doc', { lang, path: docPath }), [lang, docPath])
26
+
27
+ if (doc.type === 'collapse') {
28
+ return pug`
29
+ Collapse(
30
+ variant='pure'
31
+ $open=$openedCollapses.at(docPath)
32
+ )
33
+ Collapse.Header.header(
34
+ iconPosition='right'
35
+ icon=faAngleRight
36
+ iconStyleName='collapse-icon'
37
+ )
38
+ Menu.Item(
39
+ style=menuItemStyle
40
+ active=active
41
+ to=doc.component ? rootPath : null
42
+ bold
43
+ icon=doc.icon
44
+ )= title
45
+ Collapse.Content
46
+ Docs(
47
+ docs=doc.items
48
+ superPath=docPath
49
+ nestingLevel=nestingLevel + 1
50
+ )
51
+ `
52
+ }
53
+
54
+ return pug`
55
+ Menu.Item.item(
56
+ style=menuItemStyle
57
+ active=active
58
+ to=rootPath
59
+ onPress=desktop ? undefined : () => $mainSidebar.set(false)
60
+ )= title
61
+ `
62
+ })
63
+
64
+ const Docs = observer(function DocsComponent ({ docs, superPath, nestingLevel = 1 }) {
65
+ const [path] = useLocal('$render.params.path')
66
+ const $openedCollapses = useModel('_session.SidebarCollapses')
67
+
68
+ // HACK: open parent collapse on initial render
69
+ useEffect(() => {
70
+ if (superPath && path.startsWith(superPath)) {
71
+ $openedCollapses.setDiff(superPath, true)
72
+ }
73
+ }, [])
74
+
75
+ const getDocPath = useCallback(
76
+ docName => {
77
+ return superPath ? superPath + '/' + docName : docName
78
+ },
79
+ [superPath]
80
+ )
81
+
82
+ const getActive = useCallback(
83
+ docName => {
84
+ return getDocPath(docName) === path
85
+ },
86
+ [path]
87
+ )
88
+
89
+ return pug`
90
+ Menu
91
+ each docName in Object.keys(docs)
92
+ MenuItem(
93
+ key=docName
94
+ active=getActive(docName)
95
+ doc=docs[docName]
96
+ docName=docName
97
+ docPath=getDocPath(docName)
98
+ nestingLevel=nestingLevel
99
+ superPath=superPath
100
+ )
101
+ `
102
+ })
103
+
104
+ export default observer(function DocsRoot () {
105
+ const docs = useDocsContext()
106
+ const [path] = useLocal('$render.params.path')
107
+
108
+ // NOTE
109
+ // since layout renders before page loads
110
+ // and $render is created when page loads
111
+ // we need to wait for the 'path' to appear
112
+ // in the params
113
+ if (!path) return null
114
+
115
+ return pug`
116
+ Docs(docs=docs)
117
+ `
118
+ })
@@ -0,0 +1,12 @@
1
+ .header
2
+ padding-right 3u
3
+ padding-top 0.5u
4
+ padding-bottom 0.5u
5
+
6
+ .collapse
7
+ &-icon
8
+ color var(--color-text-description)
9
+
10
+ .link
11
+ text-decoration none
12
+ bleed()
@@ -0,0 +1,52 @@
1
+ import React from 'react'
2
+ import { pug, observer, useValue, $ } from 'startupjs'
3
+ import { Br, Input, Button, Modal } from '@startupjs/ui'
4
+ import { faSlidersH } from '@fortawesome/free-solid-svg-icons/faSlidersH'
5
+ import {
6
+ useShowGrid,
7
+ useShowSizes
8
+ // useValidateWidth
9
+ } from '../../../../../clientHelpers'
10
+ import './index.styl'
11
+
12
+ export default observer(function Options ({
13
+ style
14
+ }) {
15
+ const [, $open] = useValue(false)
16
+ const [, $showGrid] = useShowGrid()
17
+ // TODO: figure out why getting showSizes here leads to a bug of being non-reactive
18
+ // initially. While $showSizes.get() works fine for some reason.
19
+ const [, $showSizes] = useShowSizes()
20
+ // const [, $validateWidth] = useValidateWidth()
21
+ const $theme = $.session.theme
22
+ const theme = $theme.get() || 'light'
23
+
24
+ function toggleTheme () {
25
+ if (theme === 'light') {
26
+ $theme.set('dark')
27
+ } else {
28
+ $theme.set('light')
29
+ }
30
+ }
31
+
32
+ return pug`
33
+ Button(
34
+ style=style
35
+ icon=faSlidersH
36
+ color='text-description'
37
+ variant='text'
38
+ onPress=() => $open.set(true)
39
+ )
40
+ Modal(
41
+ title='Settings'
42
+ $visible=$open
43
+ )
44
+ Input.input(type='checkbox' label='Dark theme' value=theme === 'dark' onChange=toggleTheme)
45
+ if $showSizes.get()
46
+ //- TODO: Maybe bring width check back in future
47
+ // Input.input(type='checkbox' label='Validate width' $value=$validateWidth)
48
+ Input.input(type='checkbox' label='Show grid' $value=$showGrid)
49
+ Input.input(type='checkbox' label='Show sizes' $value=$showSizes)
50
+ Br
51
+ `
52
+ })
@@ -0,0 +1,11 @@
1
+ .header
2
+ padding 1u 1u 1u 2u
3
+ background-color var(--color-bg-main)
4
+
5
+ .content
6
+ padding-top 2u
7
+ padding-bottom 2u
8
+ padding-left 1u
9
+
10
+ .input
11
+ margin-top 1u
@@ -0,0 +1,38 @@
1
+ import React from 'react'
2
+ import { ScrollView, Image } from 'react-native'
3
+ import { pug, observer } from 'startupjs'
4
+ import { Div, Select } from '@startupjs/ui'
5
+ import { BASE_URL } from '@env'
6
+ import { useLang } from '../../../../clientHelpers'
7
+ import Options from './Options'
8
+ import Docs from './Docs'
9
+ import './index.styl'
10
+
11
+ const LANGUAGES = [
12
+ { value: 'en', label: 'English' },
13
+ { value: 'ru', label: 'Русский' }
14
+ ]
15
+
16
+ export default observer(function Content ({
17
+ style
18
+ }) {
19
+ const [lang, setLang] = useLang()
20
+ // TODO: Change logo image to base64 and pass it through context
21
+ const baseUrl = BASE_URL
22
+
23
+ return pug`
24
+ Div.root
25
+ ScrollView
26
+ Image.logo(testID='logo' source={ uri: baseUrl + '/img/docs.png' })
27
+ Docs
28
+ Div.footer(row)
29
+ Select.lang(
30
+ testID='languagesSelect'
31
+ options=LANGUAGES
32
+ value=lang
33
+ onChange=setLang
34
+ showEmptyValue=false
35
+ )
36
+ Options.options
37
+ `
38
+ })
@@ -0,0 +1,35 @@
1
+ .root
2
+ background-color var(--color-bg-main)
3
+ flex 1
4
+
5
+ .main
6
+ flex 1
7
+
8
+ .subMenuItem
9
+ padding-left 4u
10
+
11
+ .logo
12
+ width 7.5u
13
+ height 7.5u
14
+ align-self center
15
+ margin-top 4u
16
+ margin-bottom 4u
17
+
18
+ .hr
19
+ border-bottom-color var(--color-border-main)
20
+
21
+ .footer
22
+ padding-top 1u
23
+ padding-bottom 1u
24
+ padding-left 2u
25
+ padding-right 0.5u
26
+ background-color var(--color-bg-main-subtle)
27
+
28
+ .lang
29
+ // TODO: flex-grow 1 for some reason gets removed. Research.
30
+ flex-grow 2
31
+ flex-shrink 1
32
+
33
+ .options
34
+ margin-left 0.5u
35
+ flex-shrink 0
@@ -0,0 +1,24 @@
1
+ import React from 'react'
2
+ import { pug, observer, useModel } from 'startupjs'
3
+ import { SmartSidebar } from '@startupjs/ui'
4
+ import Content from './Content'
5
+
6
+ export const SIDEBAR_PATH = '_session.Sidebar.mainSidebar'
7
+
8
+ function renderContent () {
9
+ return pug`Content`
10
+ }
11
+
12
+ export default observer(function Sidebar ({ children }) {
13
+ const $open = useModel(SIDEBAR_PATH)
14
+
15
+ return pug`
16
+ SmartSidebar(
17
+ $open=$open
18
+ width=280
19
+ renderContent=renderContent
20
+ defaultOpen
21
+ )
22
+ = children
23
+ `
24
+ })
@@ -0,0 +1,97 @@
1
+ import React, { useState } from 'react'
2
+ import { pug, emit, observer, useModel } from 'startupjs'
3
+ import { pathFor, useLocation } from 'startupjs/app'
4
+ import { AutoSuggest, Button, Div, Layout, Menu, Span } from '@startupjs/ui'
5
+ import { ScrollableProvider } from '@startupjs/scrollable-anchors'
6
+ import { faBars } from '@fortawesome/free-solid-svg-icons/faBars'
7
+ import { faSearch } from '@fortawesome/free-solid-svg-icons/faSearch'
8
+ import Sidebar, { SIDEBAR_PATH } from './Sidebar'
9
+ import { useDocsContext } from '../../../docsContext'
10
+ import { useLang, getTitle } from '../../clientHelpers'
11
+ import './index.styl'
12
+
13
+ function getItems (item, lang, subpath) {
14
+ const docKey = item[0]
15
+ const docPath = subpath ? `${subpath}/${docKey}` : docKey
16
+ const rootPath = pathFor('docs:doc', { lang, path: docPath })
17
+ if (item[1].items) {
18
+ return Object.entries(item[1].items).reduce((acc, item) => {
19
+ return [...acc, ...getItems(item, lang, docPath)]
20
+ }, [])
21
+ } else {
22
+ return [{
23
+ value: rootPath,
24
+ label: getTitle(item[1], lang)
25
+ }]
26
+ }
27
+ }
28
+
29
+ function renderItem (item, path) {
30
+ const active = item.value === path
31
+ return pug`
32
+ Menu.Item(
33
+ key=item.value
34
+ )
35
+ Span(
36
+ styleName={active}
37
+ numberOfLines=1
38
+ )= item.label
39
+ `
40
+ }
41
+
42
+ const Search = observer(function Search () {
43
+ const [value, setValue] = useState({})
44
+ const { pathname } = useLocation()
45
+ const docs = useDocsContext()
46
+ const [lang] = useLang()
47
+
48
+ const options = Object.entries(docs).reduce((acc, item) => {
49
+ return [...acc, ...getItems(item, lang)]
50
+ }, [])
51
+
52
+ function onChange (value) {
53
+ if (!value) return
54
+ setValue({})
55
+ // TODO: replaced from Menu.Item 'to' property
56
+ emit('url', value.value)
57
+ }
58
+
59
+ return pug`
60
+ AutoSuggest.search(
61
+ testID='searchInput'
62
+ value=value
63
+ options=options
64
+ placeholder='Search...'
65
+ inputIcon=faSearch
66
+ renderItem=item => renderItem(item, pathname)
67
+ onChange=onChange
68
+ )
69
+ `
70
+ })
71
+
72
+ const Topbar = observer(function Topbar () {
73
+ const $open = useModel(SIDEBAR_PATH)
74
+
75
+ function toggleSidebar () {
76
+ $open.set(!$open.get())
77
+ }
78
+
79
+ return pug`
80
+ Div.topbar(row)
81
+ Button(testID='button' variant='text' icon=faBars onPress=toggleSidebar color='text-description')
82
+ Div.searchWrapper
83
+ Search
84
+ `
85
+ })
86
+
87
+ export default observer(function StyleguideLayout ({ children }) {
88
+ // Note: Topbar height is compensated in PDoc
89
+ // to achieve a semi-transparent effect
90
+ return pug`
91
+ Layout.layout(testID="Layout")
92
+ Sidebar
93
+ Topbar
94
+ ScrollableProvider
95
+ = children
96
+ `
97
+ })
@@ -0,0 +1,31 @@
1
+ @require '../constants.styl'
2
+
3
+ .layout
4
+ background-color var(--color-bg-main-strong)
5
+
6
+ .topbar
7
+ align-items center
8
+ justify-content space-between
9
+ border-bottom-width 1px
10
+ border-bottom-color var(--color-border-main-strong-alt)
11
+ height $TOPBAR_HEIGHT
12
+ padding 0 1u
13
+
14
+ .searchWrapper
15
+ width 32u
16
+ border-left-width 1px
17
+ border-left-color var(--color-border-main)
18
+ padding-left 2u
19
+
20
+ +tablet()
21
+ width 42u
22
+
23
+ .search
24
+ max-height 20u
25
+ &:part(input)
26
+ border none
27
+ &:part(icon)
28
+ color var(--color-text-description)
29
+
30
+ .active
31
+ color var(--color-text-primary)
@@ -0,0 +1 @@
1
+ $TOPBAR_HEIGHT = 6u
@@ -0,0 +1,5 @@
1
+ import * as pages from './pages'
2
+ import getRoutes from './routes'
3
+
4
+ export { default as Layout } from './Layout'
5
+ export const routes = getRoutes(pages)
@@ -0,0 +1,46 @@
1
+ import React from 'react'
2
+ import { pug, observer, useLocal } from 'startupjs'
3
+ import { Span, Br, Div } from '@startupjs/ui'
4
+ import { useDocsContext } from '../../../../docsContext'
5
+ import { useLang } from '../../../clientHelpers'
6
+ import './index.styl'
7
+
8
+ export default observer(function PDoc ({
9
+ style
10
+ }) {
11
+ const docs = useDocsContext()
12
+ const [docPath] = useLocal('$render.params.path')
13
+ const segments = docPath.split('/')
14
+ const [lang] = useLang()
15
+ const Component = segments.reduce((docs, segment, index) => {
16
+ const doc = docs[segment]
17
+ if (!doc) return PageNotFound
18
+ // when page with 'collapse' type has a component to render
19
+ // to display it we have to figure out if it is the last segment or not
20
+ if (doc.type === 'collapse' && segments.length - 1 !== index) {
21
+ return doc.items
22
+ }
23
+ const Component = getComponent(doc, lang)
24
+ return Component || PageNotFound
25
+ }, docs)
26
+
27
+ return pug`
28
+ Div.content
29
+ Br
30
+ Component
31
+ Br(lines=4)
32
+ `
33
+ })
34
+
35
+ function PageNotFound () {
36
+ return pug`
37
+ Span.message Page not found
38
+ `
39
+ }
40
+
41
+ function getComponent (item, lang) {
42
+ if (!item) return
43
+ if (!item.component) return
44
+ if (item.component[lang]) return item.component[lang]
45
+ return item.component
46
+ }
@@ -0,0 +1,21 @@
1
+ $gutter-l = 6u
2
+ $gutter-xl = 10u
3
+
4
+ .root
5
+ flex 1
6
+
7
+ .content
8
+ padding-left $UI.gutters.m
9
+ padding-right $UI.gutters.m
10
+ max-width $UI.media.tablet + $UI.gutters.m * 2
11
+ +tablet()
12
+ max-width $UI.media.tablet + $gutter-l * 2
13
+ padding-left $gutter-l
14
+ padding-right $gutter-l
15
+ +wide()
16
+ max-width $UI.media.tablet + $gutter-xl * 2
17
+ padding-left $gutter-xl
18
+ padding-right $gutter-xl
19
+
20
+ .message
21
+ font(h2)
@@ -0,0 +1,33 @@
1
+ import { useEffect } from 'react'
2
+ import { observer, emit } from 'startupjs'
3
+ import { useDocsContext } from '../../../../docsContext'
4
+
5
+ export default observer(function PHome () {
6
+ const docs = useDocsContext()
7
+
8
+ function getDocPath (docs) {
9
+ let path = '/'
10
+ const docName = Object.keys(docs)[0]
11
+ const doc = docs[docName]
12
+ switch (doc.type) {
13
+ case 'mdx':
14
+ path += docName
15
+ break
16
+ case 'collapse':
17
+ path += docName
18
+ if (!doc.component) path += getDocPath(doc.items)
19
+ break
20
+ }
21
+ return path
22
+ }
23
+
24
+ useEffect(() => {
25
+ emit(
26
+ 'url',
27
+ '/docs' + getDocPath(docs),
28
+ { replace: true }
29
+ )
30
+ }, [])
31
+
32
+ return null
33
+ })
@@ -0,0 +1,2 @@
1
+ export { default as PHome } from './PHome'
2
+ export { default as PDoc } from './PDoc'
@@ -0,0 +1,15 @@
1
+ export default function (components = {}) {
2
+ return [
3
+ {
4
+ path: '/docs',
5
+ exact: true,
6
+ component: components.PHome
7
+ },
8
+ {
9
+ path: '/docs/:path+',
10
+ exact: true,
11
+ component: components.PDoc,
12
+ name: 'docs:doc'
13
+ }
14
+ ]
15
+ }
@@ -0,0 +1,11 @@
1
+ import { DEFAULT_LANGUAGE } from '../const'
2
+
3
+ export default function getTitle (item, lang) {
4
+ const title = item.title
5
+ ? typeof item.title === 'string'
6
+ ? item.title
7
+ : item.title[lang] || item.title[DEFAULT_LANGUAGE]
8
+ : null
9
+ if (!title) throw Error('No title specified')
10
+ return title
11
+ }