@docsector/docsector-reader 0.13.0 → 1.0.0

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 CHANGED
@@ -46,6 +46,8 @@ Transform Markdown content into beautiful, navigable documentation sites — wit
46
46
  - ✏️ **Edit on GitHub** — Direct links to edit pages on your repository
47
47
  - 📅 **Last Updated Date** — Automatic per-page "last updated" date from git commit history, locale-formatted
48
48
  - 📊 **Translation Progress** — Automatic translation percentage based on header coverage
49
+ - 🏠 **Markdown Home at Root** — Homepage is rendered from `src/pages/Homepage.{lang}.md` directly at `/`
50
+ - 🧭 **Quick Links Custom Element** — Use `<d-quick-links>` and `<d-quick-link>` in Markdown to render rich home navigation cards
49
51
  - ⚙️ **Single Config File** — Customize branding, links, and languages via `docsector.config.js`
50
52
 
51
53
  ---
package/bin/docsector.js CHANGED
@@ -23,7 +23,7 @@ const packageRoot = resolve(__dirname, '..')
23
23
  const args = process.argv.slice(2)
24
24
  const command = args[0]
25
25
 
26
- const VERSION = '0.13.0'
26
+ const VERSION = '1.0.0'
27
27
 
28
28
  const HELP = `
29
29
  Docsector Reader v${VERSION}
@@ -341,6 +341,22 @@ export default {
341
341
  }
342
342
  `
343
343
 
344
+ const TEMPLATE_HOMEPAGE_MD = `\
345
+ # Welcome to Docsector Reader
346
+
347
+ Docsector Reader is a markdown-first documentation engine.
348
+
349
+ ## Quick Links
350
+
351
+ - [Getting Started](/guide/getting-started/overview/)
352
+ - [Configuration](/guide/configuration/overview/)
353
+ - [Pages and Routing](/guide/pages-and-routing/overview/)
354
+
355
+ ## About
356
+
357
+ - Repository: [docsector/docsector-reader](https://github.com/docsector/docsector-reader)
358
+ `
359
+
344
360
  const TEMPLATE_BOOT_PAGE = `\
345
361
  <template>
346
362
  <q-page-container>
@@ -703,6 +719,18 @@ npm-debug.log*
703
719
  .thumbs.db
704
720
  `
705
721
 
722
+ const TEMPLATE_MARKDOWNLINT = `\
723
+ {
724
+ "MD013": false,
725
+ "MD033": {
726
+ "allowed_elements": [
727
+ "d-quick-links",
728
+ "d-quick-link"
729
+ ]
730
+ }
731
+ }
732
+ `
733
+
706
734
  const TEMPLATE_ROBOTS_TXT = `\
707
735
  User-agent: *
708
736
  Allow: /
@@ -822,9 +850,11 @@ Here's an overview of the project files:
822
850
  | --- | --- |
823
851
  | \`docsector.config.js\` | Branding, links, languages, and GitHub config |
824
852
  | \`quasar.config.js\` | Quasar/Vite build configuration (via factory) |
853
+ | \`.markdownlint.json\` | Markdown lint rules (allows Docsector custom tags) |
825
854
  | \`src/pages/index.js\` | Page registry — defines all documentation pages |
826
855
  | \`src/pages/boot.js\` | Boot metadata for the home page |
827
- | \`src/pages/@/\` | Special pages (Home, 404) |
856
+ | \`src/pages/Homepage.en-US.md\` | Home page content in Markdown |
857
+ | \`src/pages/404Page.vue\` | Not found page |
828
858
  | \`src/pages/guide/\` | Guide pages (Markdown files) |
829
859
  | \`src/i18n/languages/\` | Translation files (HJSON format) |
830
860
  | \`src/css/app.sass\` | Custom styles |
@@ -927,7 +957,6 @@ function initProject (name) {
927
957
  'src/i18n',
928
958
  'src/i18n/languages',
929
959
  'src/pages',
930
- 'src/pages/@',
931
960
  'src/pages/guide',
932
961
  'public',
933
962
  'public/images',
@@ -944,6 +973,7 @@ function initProject (name) {
944
973
  ['package.json', getTemplatePackageJson(name)],
945
974
  ['quasar.config.js', TEMPLATE_QUASAR_CONFIG],
946
975
  ['docsector.config.js', TEMPLATE_DOCSECTOR_CONFIG],
976
+ ['.markdownlint.json', TEMPLATE_MARKDOWNLINT],
947
977
  ['index.html', TEMPLATE_INDEX_HTML],
948
978
  ['postcss.config.cjs', TEMPLATE_POSTCSS],
949
979
  ['.gitignore', TEMPLATE_GITIGNORE],
@@ -953,8 +983,8 @@ function initProject (name) {
953
983
  ['src/i18n/languages/en-US.hjson', TEMPLATE_I18N_HJSON],
954
984
  ['src/pages/index.js', TEMPLATE_PAGES_INDEX],
955
985
  ['src/pages/boot.js', TEMPLATE_PAGES_BOOT],
956
- ['src/pages/@/BootPage.vue', TEMPLATE_BOOT_PAGE],
957
- ['src/pages/@/404Page.vue', TEMPLATE_404_PAGE],
986
+ ['src/pages/Homepage.en-US.md', TEMPLATE_HOMEPAGE_MD],
987
+ ['src/pages/404Page.vue', TEMPLATE_404_PAGE],
958
988
  ['src/pages/guide/getting-started.overview.en-US.md', TEMPLATE_GETTING_STARTED_MD]
959
989
  ]
960
990
 
@@ -972,6 +1002,7 @@ function initProject (name) {
972
1002
  console.log(` ${name}/`)
973
1003
  console.log(' ├── docsector.config.js')
974
1004
  console.log(' ├── quasar.config.js')
1005
+ console.log(' ├── .markdownlint.json')
975
1006
  console.log(' ├── package.json')
976
1007
  console.log(' ├── index.html')
977
1008
  console.log(' ├── postcss.config.cjs')
@@ -990,9 +1021,8 @@ function initProject (name) {
990
1021
  console.log(' └── pages/')
991
1022
  console.log(' ├── index.js')
992
1023
  console.log(' ├── boot.js')
993
- console.log(' ├── @/')
994
- console.log(' ├── BootPage.vue')
995
- console.log(' │ └── 404Page.vue')
1024
+ console.log(' ├── Homepage.en-US.md')
1025
+ console.log(' ├── 404Page.vue')
996
1026
  console.log(' └── guide/')
997
1027
  console.log(' └── getting-started.overview.en-US.md')
998
1028
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@docsector/docsector-reader",
3
- "version": "0.13.0",
3
+ "version": "1.0.0",
4
4
  "description": "A documentation rendering engine built with Vue 3, Quasar v2 and Vite. Transform Markdown into beautiful, navigable documentation sites.",
5
5
  "productName": "Docsector Reader",
6
6
  "author": "Rodrigo de Araujo Vieira",
@@ -70,11 +70,19 @@ const rawMarkdown = computed(() => {
70
70
  })
71
71
 
72
72
  const markdownURL = computed(() => {
73
+ if (store.state.page.base === 'home') {
74
+ return `/Homepage.${locale.value}.md`
75
+ }
76
+
73
77
  const path = route.path.replace(/\/+$/, '')
74
78
  return `${path}.md`
75
79
  })
76
80
 
77
81
  const fullMarkdownURL = computed(() => {
82
+ if (store.state.page.base === 'home') {
83
+ return `${window.location.origin}/Homepage.${locale.value}.md`
84
+ }
85
+
78
86
  const path = route.path.replace(/\/+$/, '')
79
87
  return `${window.location.origin}${path}.md`
80
88
  })
@@ -13,6 +13,7 @@ import DH6 from './DH6.vue'
13
13
  import DPageSourceCode from './DPageSourceCode.vue'
14
14
  import DMermaidDiagram from './DMermaidDiagram.vue'
15
15
  import DPageBlockquote from './DPageBlockquote.vue'
16
+ import DQuickLinks from './DQuickLinks.vue'
16
17
 
17
18
  const props = defineProps({
18
19
  id: {
@@ -49,6 +50,71 @@ const parseAlertMarker = (rawContent = '') => {
49
50
  }
50
51
  }
51
52
 
53
+ const QUICK_LINKS_MARKER_PREFIX = '@@DOCSECTOR_QUICK_LINKS_'
54
+
55
+ const parseTagAttributes = (raw = '') => {
56
+ const attrs = {}
57
+ const pattern = /(\w+)\s*=\s*"([^"]*)"|(\w+)\s*=\s*'([^']*)'/g
58
+
59
+ let match = pattern.exec(raw)
60
+ while (match !== null) {
61
+ const key = match[1] || match[3]
62
+ const value = match[2] || match[4] || ''
63
+ attrs[key] = value
64
+ match = pattern.exec(raw)
65
+ }
66
+
67
+ return attrs
68
+ }
69
+
70
+ const extractQuickLinksBlocks = (source = '') => {
71
+ const map = new Map()
72
+ let index = 0
73
+
74
+ const blockPattern = /<d-quick-links\b([^>]*)>([\s\S]*?)<\/d-quick-links>/gi
75
+ const replaced = String(source).replace(blockPattern, (_, blockAttrsRaw, inner) => {
76
+ const blockAttrs = parseTagAttributes(blockAttrsRaw)
77
+ const items = []
78
+ const itemPattern = /<d-quick-link\b([^>]*)\/?\s*>/gi
79
+
80
+ let itemMatch = itemPattern.exec(inner)
81
+ while (itemMatch !== null) {
82
+ const attrs = parseTagAttributes(itemMatch[1])
83
+ const title = attrs.title || ''
84
+ const description = attrs.description || ''
85
+ const to = attrs.to || ''
86
+ const href = attrs.href || ''
87
+
88
+ if (title && description && (to || href)) {
89
+ items.push({
90
+ icon: attrs.icon || 'link',
91
+ title,
92
+ description,
93
+ to,
94
+ href
95
+ })
96
+ }
97
+
98
+ itemMatch = itemPattern.exec(inner)
99
+ }
100
+
101
+ const marker = `${QUICK_LINKS_MARKER_PREFIX}${index}@@`
102
+ index++
103
+
104
+ map.set(marker, {
105
+ title: blockAttrs.title || '',
106
+ items
107
+ })
108
+
109
+ return `\n${marker}\n`
110
+ })
111
+
112
+ return {
113
+ source: replaced,
114
+ quickLinksMap: map
115
+ }
116
+ }
117
+
52
118
  const tokenized = computed(() => {
53
119
  const absolute = store.state.i18n.absolute
54
120
 
@@ -62,6 +128,8 @@ const tokenized = computed(() => {
62
128
  .replace(/&#125;/g, '}')
63
129
  .replace(/&amp;/g, '&')
64
130
 
131
+ const { source: sourceWithQuickLinks, quickLinksMap } = extractQuickLinksBlocks(normalizedSource)
132
+
65
133
  const Markdown = new MarkdownIt()
66
134
  Markdown.use(attrs, {
67
135
  leftDelimiter: ':',
@@ -75,7 +143,7 @@ const tokenized = computed(() => {
75
143
 
76
144
  const markdownEnv = {}
77
145
 
78
- const parsed = Markdown.parse(normalizedSource, markdownEnv)
146
+ const parsed = Markdown.parse(sourceWithQuickLinks, markdownEnv)
79
147
 
80
148
  // @ map
81
149
  const tokens = []
@@ -213,6 +281,17 @@ const tokenized = computed(() => {
213
281
  // Push
214
282
  switch (element.type) {
215
283
  case 'inline':
284
+ if (quickLinksMap.has(element.content.trim())) {
285
+ const data = quickLinksMap.get(element.content.trim())
286
+
287
+ tokens.push({
288
+ tag: 'quick-links',
289
+ title: data.title,
290
+ items: data.items
291
+ })
292
+ break
293
+ }
294
+
216
295
  tokens.push({
217
296
  tag,
218
297
  map: element.map,
@@ -395,6 +474,12 @@ const tokenized = computed(() => {
395
474
  v-else-if="token.tag === 'mermaid'"
396
475
  :content="token.content"
397
476
  />
477
+
478
+ <d-quick-links
479
+ v-else-if="token.tag === 'quick-links'"
480
+ :title="token.title"
481
+ :items="token.items"
482
+ />
398
483
  </template>
399
484
  </section>
400
485
  </template>
@@ -0,0 +1,98 @@
1
+ <script setup>
2
+ const props = defineProps({
3
+ items: {
4
+ type: Array,
5
+ default: () => []
6
+ },
7
+ title: {
8
+ type: String,
9
+ default: ''
10
+ }
11
+ })
12
+
13
+ const isExternal = (item) => {
14
+ const href = item?.href || ''
15
+ return /^https?:\/\//i.test(href)
16
+ }
17
+
18
+ const toTarget = (item) => {
19
+ if (item?.to) return item.to
20
+ return undefined
21
+ }
22
+
23
+ const hrefTarget = (item) => {
24
+ if (item?.href) return item.href
25
+ return undefined
26
+ }
27
+
28
+ const relValue = (item) => {
29
+ if (isExternal(item)) return 'noopener noreferrer'
30
+ return undefined
31
+ }
32
+
33
+ const targetValue = (item) => {
34
+ if (isExternal(item)) return '_blank'
35
+ return undefined
36
+ }
37
+ </script>
38
+
39
+ <template>
40
+ <div class="d-quick-links">
41
+ <h3 v-if="title" class="d-quick-links__title">{{ title }}</h3>
42
+
43
+ <q-list bordered separator class="d-quick-links__list rounded-borders">
44
+ <q-item
45
+ v-for="(item, index) in props.items"
46
+ :key="index"
47
+ clickable
48
+ :to="toTarget(item)"
49
+ :href="hrefTarget(item)"
50
+ :target="targetValue(item)"
51
+ :rel="relValue(item)"
52
+ >
53
+ <q-item-section avatar>
54
+ <q-icon :name="item.icon || 'link'" color="primary" />
55
+ </q-item-section>
56
+
57
+ <q-item-section>
58
+ <q-item-label class="d-quick-links__label">{{ item.title }}</q-item-label>
59
+ <q-item-label caption class="d-quick-links__caption">{{ item.description }}</q-item-label>
60
+ </q-item-section>
61
+
62
+ <q-item-section side>
63
+ <q-icon name="chevron_right" />
64
+ </q-item-section>
65
+ </q-item>
66
+ </q-list>
67
+ </div>
68
+ </template>
69
+
70
+ <style lang="sass" scoped>
71
+ .d-quick-links
72
+ margin: 0 auto
73
+
74
+ .d-quick-links__title
75
+ text-align: center
76
+ margin: 0 0 12px
77
+
78
+ .d-quick-links__list
79
+ border-color: rgba(255, 255, 255, 0.16)
80
+
81
+ .q-item
82
+ min-height: 58px
83
+
84
+ .d-quick-links__label
85
+ font-weight: 700
86
+
87
+ .d-quick-links__caption
88
+ font-size: 0.97rem
89
+ color: #4d5563
90
+ opacity: 1
91
+
92
+
93
+ :global(body.body--dark) .d-quick-links__list
94
+ border-color: rgba(255, 255, 255, 0.16)
95
+
96
+ :global(body.body--dark) .d-quick-links__caption
97
+ color: rgba(255, 255, 255, 0.9)
98
+ </style>
@@ -144,6 +144,38 @@ export function buildMessages ({ langModules, mdModules, pages, boot, langs }) {
144
144
  return source
145
145
  }
146
146
 
147
+ function loadHomepage (lang) {
148
+ const key = `../pages/Homepage.${lang}.md`
149
+ const fallbackKey = '../pages/Homepage.en-US.md'
150
+
151
+ const content = mdModules[key] ?? mdModules[fallbackKey]
152
+ if (!content) {
153
+ console.warn(`[i18n] Missing homepage markdown: ${key}`)
154
+ return ''
155
+ }
156
+
157
+ const source = filter(typeof content === 'string' ? content : String(content))
158
+ return source
159
+ }
160
+
161
+ function extractHeadingFromHomepage (lang) {
162
+ const key = `../pages/Homepage.${lang}.md`
163
+ const fallbackKey = '../pages/Homepage.en-US.md'
164
+
165
+ const content = mdModules[key] ?? mdModules[fallbackKey]
166
+ if (!content) {
167
+ return ''
168
+ }
169
+
170
+ const raw = typeof content === 'string' ? content : String(content)
171
+ const match = raw.match(/^#\s+(.+)$/m)
172
+ if (!match) {
173
+ return ''
174
+ }
175
+
176
+ return match[1].trim()
177
+ }
178
+
147
179
  // @ Iterate langs
148
180
  for (const lang of langs) {
149
181
  // Load HJSON language file
@@ -155,6 +187,26 @@ export function buildMessages ({ langModules, mdModules, pages, boot, langs }) {
155
187
  deepMerge(i18n[lang], engineDefaults[lang])
156
188
  }
157
189
 
190
+ // @ Homepage markdown in root route
191
+ if (i18n[lang]._ === undefined) {
192
+ i18n[lang]._ = {}
193
+ }
194
+ if (i18n[lang]._.home === undefined) {
195
+ i18n[lang]._.home = {}
196
+ }
197
+
198
+ const homepageHeading = extractHeadingFromHomepage(lang)
199
+ i18n[lang]._.home._ = homepageHeading || i18n[lang]._.home._ || i18n[lang].menu?.home || 'Home'
200
+
201
+ if (i18n[lang]._.home.overview === undefined) {
202
+ i18n[lang]._.home.overview = {}
203
+ }
204
+
205
+ const homeMeta = boot?.meta?.[lang] || boot?.meta?.['en-US'] || {}
206
+ i18n[lang]._.home.overview._translations = homeMeta?.overview?._translations
207
+ i18n[lang]._.home.overview._sections = homeMeta?.overview?._sections
208
+ i18n[lang]._.home.overview.source = loadHomepage(lang)
209
+
158
210
  // @ Iterate pages
159
211
  for (const [key, page] of Object.entries(pages)) {
160
212
  const path = key.slice(1)
@@ -0,0 +1,17 @@
1
+ # Docsector Reader
2
+
3
+ Docsector Reader is a documentation rendering engine built with Vue 3, Quasar v2 and Vite.
4
+
5
+ ## Quick Links
6
+
7
+ - [Getting Started](/guide/getting-started/overview/)
8
+ - [Configuration](/guide/configuration/overview/)
9
+ - [Pages and Routing](/guide/pages-and-routing/overview/)
10
+ - [Components](/manual/components/d-page/overview/)
11
+ - [Composables](/manual/composables/use-navigator/overview/)
12
+ - [Store Modules](/manual/store/modules/overview/)
13
+
14
+ ## About
15
+
16
+ - Repository: [docsector/docsector-reader](https://github.com/docsector/docsector-reader)
17
+ - Focus: markdown-first docs with i18n, menu navigation and static deployment
@@ -0,0 +1,17 @@
1
+ # Docsector Reader
2
+
3
+ Docsector Reader e um motor de documentacao construído com Vue 3, Quasar v2 e Vite.
4
+
5
+ ## Links rapidos
6
+
7
+ - [Comecando](/guide/getting-started/overview/)
8
+ - [Configuracao](/guide/configuration/overview/)
9
+ - [Paginas e Rotas](/guide/pages-and-routing/overview/)
10
+ - [Componentes](/manual/components/d-page/overview/)
11
+ - [Composables](/manual/composables/use-navigator/overview/)
12
+ - [Modulos de Store](/manual/store/modules/overview/)
13
+
14
+ ## Sobre
15
+
16
+ - Repositorio: [docsector/docsector-reader](https://github.com/docsector/docsector-reader)
17
+ - Foco: docs markdown-first com i18n, menu de navegacao e deploy estatico
@@ -1,4 +1,5 @@
1
1
  import pages from 'pages'
2
+ import boot from 'pages/boot'
2
3
 
3
4
  const pagesRoutes = []
4
5
  for (const [path, page] of Object.entries(pages)) {
@@ -59,9 +60,27 @@ const routes = [
59
60
  ...pagesRoutes,
60
61
 
61
62
  {
62
- path: '/',
63
+ path: '/home',
64
+ alias: '/',
63
65
  component: () => import('layouts/DefaultLayout.vue'),
64
66
  meta: {
67
+ icon: 'home',
68
+ menu: {},
69
+ status: 'done',
70
+ type: 'home',
71
+ subpages: {
72
+ showcase: false,
73
+ vs: false
74
+ },
75
+ data: {
76
+ 'en-US': {
77
+ title: 'Home'
78
+ },
79
+ 'pt-BR': {
80
+ title: 'Pagina inicial'
81
+ }
82
+ },
83
+ meta: boot.meta,
65
84
  layouts: {
66
85
  footer: false,
67
86
  submenu: false
@@ -71,7 +90,7 @@ const routes = [
71
90
  children: [
72
91
  {
73
92
  path: '',
74
- component: () => import('pages/@/BootPage.vue'),
93
+ component: () => import('components/DSubpage.vue'),
75
94
  meta: {
76
95
  icon: 'home',
77
96
  menu: 'home'
@@ -89,7 +108,7 @@ const routes = [
89
108
  children: [
90
109
  {
91
110
  path: '',
92
- component: () => import('pages/@/404Page.vue')
111
+ component: () => import('pages/404Page.vue')
93
112
  }
94
113
  ]
95
114
  }
package/src/store/App.js CHANGED
@@ -12,10 +12,10 @@ export default {
12
12
  commit('page/resetNodes', null, { root: true })
13
13
 
14
14
  // Route
15
- const firstRoutePath = routeMatched[0].path
16
- const secondRoutePath = routeMatched[1].path
15
+ const firstRoutePath = routeMatched[0]?.path || ''
16
+ const secondRoutePath = routeMatched[1]?.path || ''
17
17
 
18
- const base = firstRoutePath.substr(1)
18
+ const base = firstRoutePath === '/' ? 'home' : firstRoutePath.substr(1)
19
19
  let relative = secondRoutePath.substr(firstRoutePath.length)
20
20
 
21
21
  if (relative !== '/') {
@@ -1,106 +0,0 @@
1
- <template>
2
- <q-page-container>
3
- <q-page class="content">
4
- <div class="text-center q-pa-xs q-pt-md">
5
- <h1>Docsector Reader</h1>
6
-
7
- <p class="caption">
8
- {{ $t('_.home.texts[0]') }}
9
- <a :href="projectUrl" target="_blank">{{ projectName }}</a>!
10
- </p>
11
- <hr />
12
- </div>
13
-
14
- <div class="q-pa-md" style="max-width: 700px; margin: 0 auto;">
15
- <h3 class="text-center q-mb-md">Quick Links</h3>
16
-
17
- <q-list bordered separator class="rounded-borders">
18
- <q-item clickable to="/guide/getting-started/overview/">
19
- <q-item-section avatar>
20
- <q-icon name="flag" color="primary" />
21
- </q-item-section>
22
- <q-item-section>
23
- <q-item-label>Getting Started</q-item-label>
24
- <q-item-label caption>Installation, setup, and project structure</q-item-label>
25
- </q-item-section>
26
- <q-item-section side>
27
- <q-icon name="chevron_right" />
28
- </q-item-section>
29
- </q-item>
30
-
31
- <q-item clickable to="/guide/configuration/overview/">
32
- <q-item-section avatar>
33
- <q-icon name="tune" color="primary" />
34
- </q-item-section>
35
- <q-item-section>
36
- <q-item-label>Configuration</q-item-label>
37
- <q-item-label caption>docsector.config.js reference</q-item-label>
38
- </q-item-section>
39
- <q-item-section side>
40
- <q-icon name="chevron_right" />
41
- </q-item-section>
42
- </q-item>
43
-
44
- <q-item clickable to="/guide/pages-and-routing/overview/">
45
- <q-item-section avatar>
46
- <q-icon name="route" color="primary" />
47
- </q-item-section>
48
- <q-item-section>
49
- <q-item-label>Pages &amp; Routing</q-item-label>
50
- <q-item-label caption>Page registry and route generation</q-item-label>
51
- </q-item-section>
52
- <q-item-section side>
53
- <q-icon name="chevron_right" />
54
- </q-item-section>
55
- </q-item>
56
-
57
- <q-item clickable to="/manual/components/d-page/overview/">
58
- <q-item-section avatar>
59
- <q-icon name="widgets" color="secondary" />
60
- </q-item-section>
61
- <q-item-section>
62
- <q-item-label>Components</q-item-label>
63
- <q-item-label caption>DPage, DPageSection, DH1–DH6, DMenu, and more</q-item-label>
64
- </q-item-section>
65
- <q-item-section side>
66
- <q-icon name="chevron_right" />
67
- </q-item-section>
68
- </q-item>
69
-
70
- <q-item clickable to="/manual/composables/use-navigator/overview/">
71
- <q-item-section avatar>
72
- <q-icon name="navigation" color="accent" />
73
- </q-item-section>
74
- <q-item-section>
75
- <q-item-label>Composables</q-item-label>
76
- <q-item-label caption>useNavigator — anchor navigation and ToC</q-item-label>
77
- </q-item-section>
78
- <q-item-section side>
79
- <q-icon name="chevron_right" />
80
- </q-item-section>
81
- </q-item>
82
-
83
- <q-item clickable to="/manual/store/modules/overview/">
84
- <q-item-section avatar>
85
- <q-icon name="storage" color="deep-orange" />
86
- </q-item-section>
87
- <q-item-section>
88
- <q-item-label>Vuex Store</q-item-label>
89
- <q-item-label caption>App, I18n, Page, Layout, Settings modules</q-item-label>
90
- </q-item-section>
91
- <q-item-section side>
92
- <q-icon name="chevron_right" />
93
- </q-item-section>
94
- </q-item>
95
- </q-list>
96
- </div>
97
- </q-page>
98
- </q-page-container>
99
- </template>
100
-
101
- <script setup>
102
- import docsectorConfig from 'docsector.config.js'
103
-
104
- const projectName = docsectorConfig.branding?.name || 'My Project'
105
- const projectUrl = docsectorConfig.links?.github || '#'
106
- </script>
File without changes