@docsector/docsector-reader 3.1.0 → 3.2.1
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 +13 -2
- package/bin/docsector.js +1 -1
- package/package.json +10 -7
- package/src/components/DH2.vue +1 -1
- package/src/components/DH3.vue +1 -1
- package/src/components/DH4.vue +1 -1
- package/src/components/DH5.vue +1 -1
- package/src/components/DH6.vue +1 -1
- package/src/components/DMenu.vue +1 -1
- package/src/components/DPage.vue +26 -6
- package/src/components/DPageAnchor.vue +3 -9
- package/src/components/DPageMeta.vue +1 -0
- package/src/components/DPageTokens.vue +5 -5
- package/src/components/page-section-tokens.js +59 -6
- package/src/composables/useNavigator.js +45 -15
- package/src/css/app.sass +12 -0
- package/src/pages/404Page.vue +2 -2
- package/src/pages/Homepage.en-US.md +3 -3
- package/src/pages/Homepage.pt-BR.md +3 -3
- package/src/pages/guide/i18n-and-markdown.overview.en-US.md +26 -4
- package/src/pages/guide/i18n-and-markdown.overview.pt-BR.md +23 -1
- package/src/pages/guide/pages-and-routing.overview.en-US.md +11 -9
- package/src/pages/guide/pages-and-routing.overview.pt-BR.md +11 -9
- package/src/pages/guide.index.js +0 -28
- package/src/pages/manual/basic/branding.overview.en-US.md +27 -0
- package/src/pages/manual/basic/branding.overview.pt-BR.md +27 -0
- package/src/pages/manual/{components → basic}/d-menu.overview.en-US.md +11 -3
- package/src/pages/manual/{components → basic}/d-menu.overview.pt-BR.md +11 -3
- package/src/pages/manual/{components → basic}/d-page-anchor.overview.en-US.md +5 -3
- package/src/pages/manual/{components → basic}/d-page-anchor.overview.pt-BR.md +5 -3
- package/src/pages/manual/{components → basic}/d-page-meta.overview.en-US.md +10 -2
- package/src/pages/manual/{components → basic}/d-page-meta.overview.pt-BR.md +10 -2
- package/src/pages/manual/basic/edit-on-github.overview.en-US.md +26 -0
- package/src/pages/manual/basic/edit-on-github.overview.pt-BR.md +26 -0
- package/src/pages/manual/basic/previous-and-next.overview.en-US.md +17 -0
- package/src/pages/manual/basic/previous-and-next.overview.pt-BR.md +17 -0
- package/src/pages/manual/basic/search.overview.en-US.md +24 -0
- package/src/pages/manual/basic/search.overview.pt-BR.md +24 -0
- package/src/pages/manual/basic/translation-progress.overview.en-US.md +19 -0
- package/src/pages/manual/basic/translation-progress.overview.pt-BR.md +19 -0
- package/src/pages/manual/basic/version-switcher.overview.en-US.md +28 -0
- package/src/pages/manual/basic/version-switcher.overview.pt-BR.md +28 -0
- package/src/pages/manual/components/d-subpage.overview.en-US.md +2 -2
- package/src/pages/manual/components/d-subpage.overview.pt-BR.md +2 -2
- package/src/pages/manual/content/blocks/code-blocks.overview.en-US.md +55 -0
- package/src/pages/manual/content/blocks/code-blocks.overview.pt-BR.md +55 -0
- package/src/pages/manual/{components/d-page-source-code.showcase.en-US.md → content/blocks/code-blocks.showcase.en-US.md} +14 -12
- package/src/pages/manual/{components/d-page-source-code.showcase.pt-BR.md → content/blocks/code-blocks.showcase.pt-BR.md} +28 -26
- package/src/pages/manual/{components/d-page-expandable.overview.en-US.md → content/blocks/expandable.overview.en-US.md} +3 -12
- package/src/pages/manual/{components/d-page-expandable.overview.pt-BR.md → content/blocks/expandable.overview.pt-BR.md} +3 -12
- package/src/pages/manual/content/blocks/headings.overview.en-US.md +45 -0
- package/src/pages/manual/content/blocks/headings.overview.pt-BR.md +45 -0
- package/src/pages/manual/{components/d-headings.showcase.en-US.md → content/blocks/headings.showcase.en-US.md} +1 -1
- package/src/pages/manual/{components/d-headings.showcase.pt-BR.md → content/blocks/headings.showcase.pt-BR.md} +1 -1
- package/src/pages/manual/content/blocks/hints.overview.en-US.md +30 -0
- package/src/pages/manual/content/blocks/hints.overview.pt-BR.md +30 -0
- package/src/pages/manual/content/blocks/hints.showcase.en-US.md +30 -0
- package/src/pages/manual/content/blocks/hints.showcase.pt-BR.md +30 -0
- package/src/pages/manual/content/blocks/images.overview.en-US.md +16 -0
- package/src/pages/manual/content/blocks/images.overview.pt-BR.md +16 -0
- package/src/pages/manual/content/blocks/images.showcase.en-US.md +11 -0
- package/src/pages/manual/content/blocks/images.showcase.pt-BR.md +11 -0
- package/src/pages/manual/content/blocks/math-and-tex.overview.en-US.md +27 -0
- package/src/pages/manual/content/blocks/math-and-tex.overview.pt-BR.md +27 -0
- package/src/pages/manual/content/blocks/math-and-tex.showcase.en-US.md +14 -0
- package/src/pages/manual/content/blocks/math-and-tex.showcase.pt-BR.md +14 -0
- package/src/pages/manual/content/blocks/mermaid-diagrams.overview.en-US.md +22 -0
- package/src/pages/manual/content/blocks/mermaid-diagrams.overview.pt-BR.md +22 -0
- package/src/pages/manual/content/blocks/ordered-lists.overview.en-US.md +19 -0
- package/src/pages/manual/content/blocks/ordered-lists.overview.pt-BR.md +19 -0
- package/src/pages/manual/content/blocks/ordered-lists.showcase.en-US.md +21 -0
- package/src/pages/manual/content/blocks/ordered-lists.showcase.pt-BR.md +21 -0
- package/src/pages/manual/content/blocks/paragraphs.overview.en-US.md +19 -0
- package/src/pages/manual/content/blocks/paragraphs.overview.pt-BR.md +19 -0
- package/src/pages/manual/content/blocks/paragraphs.showcase.en-US.md +9 -0
- package/src/pages/manual/content/blocks/paragraphs.showcase.pt-BR.md +9 -0
- package/src/pages/manual/content/blocks/quick-links.overview.en-US.md +28 -0
- package/src/pages/manual/content/blocks/quick-links.overview.pt-BR.md +28 -0
- package/src/pages/manual/content/blocks/quick-links.showcase.en-US.md +34 -0
- package/src/pages/manual/content/blocks/quick-links.showcase.pt-BR.md +34 -0
- package/src/pages/manual/content/blocks/quotes.overview.en-US.md +24 -0
- package/src/pages/manual/content/blocks/quotes.overview.pt-BR.md +24 -0
- package/src/pages/manual/content/blocks/quotes.showcase.en-US.md +17 -0
- package/src/pages/manual/content/blocks/quotes.showcase.pt-BR.md +17 -0
- package/src/pages/manual/content/blocks/raw-html.overview.en-US.md +19 -0
- package/src/pages/manual/content/blocks/raw-html.overview.pt-BR.md +19 -0
- package/src/pages/manual/content/blocks/raw-html.showcase.en-US.md +12 -0
- package/src/pages/manual/content/blocks/raw-html.showcase.pt-BR.md +12 -0
- package/src/pages/manual/content/blocks/tables.overview.en-US.md +19 -0
- package/src/pages/manual/content/blocks/tables.overview.pt-BR.md +19 -0
- package/src/pages/manual/content/blocks/tables.showcase.en-US.md +17 -0
- package/src/pages/manual/content/blocks/tables.showcase.pt-BR.md +17 -0
- package/src/pages/manual/content/blocks/unordered-lists.overview.en-US.md +21 -0
- package/src/pages/manual/content/blocks/unordered-lists.overview.pt-BR.md +21 -0
- package/src/pages/manual/content/blocks/unordered-lists.showcase.en-US.md +24 -0
- package/src/pages/manual/content/blocks/unordered-lists.showcase.pt-BR.md +24 -0
- package/src/pages/manual/content/structures/books.overview.en-US.md +36 -0
- package/src/pages/manual/content/structures/books.overview.pt-BR.md +36 -0
- package/src/pages/manual/content/structures/page.overview.en-US.md +61 -0
- package/src/pages/manual/content/structures/page.overview.pt-BR.md +61 -0
- package/src/pages/manual/content/structures/subpage.overview.en-US.md +62 -0
- package/src/pages/manual/content/structures/subpage.overview.pt-BR.md +62 -0
- package/src/pages/manual.index.js +487 -153
- package/src/router/routes.js +1 -1
- package/src/pages/guide/alerts-and-blockquotes.overview.en-US.md +0 -65
- package/src/pages/guide/alerts-and-blockquotes.overview.pt-BR.md +0 -65
- package/src/pages/manual/components/d-headings.overview.en-US.md +0 -54
- package/src/pages/manual/components/d-headings.overview.pt-BR.md +0 -54
- package/src/pages/manual/components/d-mermaid-diagram.overview.en-US.md +0 -31
- package/src/pages/manual/components/d-mermaid-diagram.overview.pt-BR.md +0 -29
- package/src/pages/manual/components/d-page-blockquote.overview.en-US.md +0 -66
- package/src/pages/manual/components/d-page-blockquote.overview.pt-BR.md +0 -66
- package/src/pages/manual/components/d-page-blockquote.showcase.en-US.md +0 -34
- package/src/pages/manual/components/d-page-blockquote.showcase.pt-BR.md +0 -34
- package/src/pages/manual/components/d-page-section.overview.en-US.md +0 -57
- package/src/pages/manual/components/d-page-section.overview.pt-BR.md +0 -57
- package/src/pages/manual/components/d-page-section.showcase.en-US.md +0 -43
- package/src/pages/manual/components/d-page-section.showcase.pt-BR.md +0 -43
- package/src/pages/manual/components/d-page-source-code.overview.en-US.md +0 -68
- package/src/pages/manual/components/d-page-source-code.overview.pt-BR.md +0 -68
- package/src/pages/manual/components/d-page.overview.en-US.md +0 -59
- package/src/pages/manual/components/d-page.overview.pt-BR.md +0 -59
- package/src/pages/manual/components/d-page.showcase.en-US.md +0 -35
- package/src/pages/manual/components/d-page.showcase.pt-BR.md +0 -35
- package/src/pages/manual/components/q-zoom.overview.en-US.md +0 -71
- package/src/pages/manual/components/q-zoom.overview.pt-BR.md +0 -71
- package/src/pages/manual/composables/use-navigator.overview.en-US.md +0 -89
- package/src/pages/manual/composables/use-navigator.overview.pt-BR.md +0 -89
- package/src/pages/manual/store/modules.overview.en-US.md +0 -96
- package/src/pages/manual/store/modules.overview.pt-BR.md +0 -96
- /package/src/pages/manual/{components/d-page-expandable.showcase.en-US.md → content/blocks/expandable.showcase.en-US.md} +0 -0
- /package/src/pages/manual/{components/d-page-expandable.showcase.pt-BR.md → content/blocks/expandable.showcase.pt-BR.md} +0 -0
- /package/src/pages/manual/{components/d-mermaid-diagram.showcase.en-US.md → content/blocks/mermaid-diagrams.showcase.en-US.md} +0 -0
- /package/src/pages/manual/{components/d-mermaid-diagram.showcase.pt-BR.md → content/blocks/mermaid-diagrams.showcase.pt-BR.md} +0 -0
package/README.md
CHANGED
|
@@ -43,13 +43,13 @@ Transform Markdown content into beautiful, navigable documentation sites — wit
|
|
|
43
43
|
- 📝 **Markdown Rendering** — Write docs in Markdown, rendered with syntax highlighting (Prism.js)
|
|
44
44
|
- 🧱 **Raw HTML in Markdown** — Renders inline and block HTML tags inside markdown sections (including homepage remote README content)
|
|
45
45
|
- 🧩 **Mermaid Diagrams** — Native support for fenced ` ```mermaid ` blocks, with automatic dark/light theme switching
|
|
46
|
+
- ➗ **Math & KaTeX** — Native support for inline `$...$` and display `$$...$$` formulas rendered with KaTeX
|
|
46
47
|
- 🚨 **GitHub-Style Alerts** — Native support for `[!NOTE]`, `[!TIP]`, `[!IMPORTANT]`, `[!WARNING]`, and `[!CAUTION]`
|
|
47
48
|
- 🌍 **Internationalization (i18n)** — Multi-language support with HJSON locale files and per-page translations
|
|
48
49
|
- 🌗 **Dark/Light Mode** — Automatic theme switching with Quasar Dark Plugin
|
|
49
50
|
- 🔗 **Anchor Navigation** — Right-side Table of Contents tree with scroll tracking and auto-scroll to active section
|
|
50
51
|
- 🖱️ **Active Menu Item UX** — Active menu entries keep pointer cursor, clear URL hash without redundant navigation, and prevent accidental label text selection
|
|
51
52
|
- 🔎 **Search** — Menu search across all documentation content and tags
|
|
52
|
-
- 🌐 **WebMCP Browser Tools** — Registers in-page tools for browser agents with `registerTool` and optional `provideContext` fallback
|
|
53
53
|
- 📱 **Responsive** — Mobile-friendly with collapsible sidebar and drawers
|
|
54
54
|
- 📚 **Book Tabs with Per-State Colors** — Define `*.book.js` tabs with icons, order, and `color.active` / `color.inactive`
|
|
55
55
|
- 🔀 **Internal Shortcut Pages** — Route entries can redirect with `config.link.to`, keeping localized titles while inheriting icon/status from the destination page
|
|
@@ -66,6 +66,7 @@ Transform Markdown content into beautiful, navigable documentation sites — wit
|
|
|
66
66
|
- 🧭 **Content Signals** — Injects `Content-Signal` policy in `robots.txt` with deterministic, idempotent build output
|
|
67
67
|
- 🏠 **Markdown Home at Root** — Homepage is rendered from `src/pages/Homepage.{lang}.md` directly at `/`
|
|
68
68
|
- 🌍 **Remote README as Home** — Optional build-time remote README source for homepage with automatic local fallback
|
|
69
|
+
- 🔗 **GitHub-Compatible Heading Anchors** — Markdown headings use GitHub-style slugs so standard README Table of Contents links work inside Docsector
|
|
69
70
|
- 🧬 **Scaffolded Homepage Override Wiring** — New consumer projects automatically wire `virtual:docsector-homepage-override` into i18n message building
|
|
70
71
|
- 📖 **Expandable Markdown Sections** — Use `<d-expandable title="...">...</d-expandable>` to collapse secondary content while keeping rich Markdown support inside the body
|
|
71
72
|
- 🧭 **Quick Links Custom Element** — Use `<d-quick-links>` and `<d-quick-link>` in Markdown to render rich home navigation cards
|
|
@@ -355,6 +356,7 @@ You can configure Docsector Reader to use a remote README as homepage content.
|
|
|
355
356
|
- Fetch happens at build-time.
|
|
356
357
|
- The same README content is used for all configured languages.
|
|
357
358
|
- If fetch fails, it falls back to local `src/pages/Homepage.{lang}.md` by default.
|
|
359
|
+
- Standard GitHub-style heading links and README Table of Contents fragments keep working in the rendered homepage.
|
|
358
360
|
|
|
359
361
|
### Configure
|
|
360
362
|
|
|
@@ -855,7 +857,12 @@ my-docs/
|
|
|
855
857
|
│ │ ├── guide.index.js # Guide page registry (routes + metadata)
|
|
856
858
|
│ │ ├── boot.js # Boot page data
|
|
857
859
|
│ │ ├── guide/ # Guide pages (.md files)
|
|
858
|
-
│ │ └── manual/
|
|
860
|
+
│ │ └── manual/
|
|
861
|
+
│ │ ├── basic/ # Core UI docs exposed in the main manual nav
|
|
862
|
+
│ │ ├── content/
|
|
863
|
+
│ │ │ ├── blocks/ # User-facing Markdown block docs
|
|
864
|
+
│ │ │ └── structures/ # User-facing page structure docs
|
|
865
|
+
│ │ └── components/ # Legacy/internal engine-facing manual docs
|
|
859
866
|
│ ├── i18n/
|
|
860
867
|
│ │ ├── index.js # Uses buildMessages() from engine
|
|
861
868
|
│ │ └── languages/ # HJSON locale files
|
|
@@ -869,6 +876,10 @@ my-docs/
|
|
|
869
876
|
└── icons/ # PWA icons
|
|
870
877
|
```
|
|
871
878
|
|
|
879
|
+
A common manual pattern is to keep core UI references under `src/pages/manual/basic/` with user-friendly page titles and focused entry pages such as Search, Branding, Version Switcher, Edit on GitHub, Translation Progress, and Previous & Next, end-user content references under `src/pages/manual/content/blocks/`, structural docs under `src/pages/manual/content/structures/`, and legacy/internal engine-specific references under `src/pages/manual/components/`.
|
|
880
|
+
|
|
881
|
+
Blocks in `src/pages/manual/content/blocks/` should normally provide both `overview` and `showcase` markdown pages, while structural topics can stay overview-only when a visual demo adds little value.
|
|
882
|
+
|
|
872
883
|
---
|
|
873
884
|
|
|
874
885
|
## 📚 Defining Books (Tabs)
|
package/bin/docsector.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@docsector/docsector-reader",
|
|
3
|
-
"version": "3.1
|
|
3
|
+
"version": "3.2.1",
|
|
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",
|
|
@@ -69,9 +69,12 @@
|
|
|
69
69
|
"autoprefixer": "^10.4.2",
|
|
70
70
|
"axios": "^1.7.7",
|
|
71
71
|
"core-js": "^3.6.5",
|
|
72
|
+
"github-slugger": "^2.0.0",
|
|
72
73
|
"hjson": "^3.2.2",
|
|
74
|
+
"katex": "^0.17.0",
|
|
73
75
|
"markdown-it": "^13.0.1",
|
|
74
76
|
"markdown-it-attrs": "^4.1.6",
|
|
77
|
+
"markdown-it-texmath": "^1.0.0",
|
|
75
78
|
"mermaid": "^11.0.0",
|
|
76
79
|
"prismjs": "^1.27.0",
|
|
77
80
|
"q-colorize-mixin": "^2.0.0-alpha.5"
|
|
@@ -86,11 +89,6 @@
|
|
|
86
89
|
},
|
|
87
90
|
"devDependencies": {
|
|
88
91
|
"@quasar/extras": "^1.16.12",
|
|
89
|
-
"quasar": "^2.16.6",
|
|
90
|
-
"vue": "^3.5.13",
|
|
91
|
-
"vue-i18n": "^9.0.0",
|
|
92
|
-
"vue-router": "^4.0.0",
|
|
93
|
-
"vuex": "^4.0.1",
|
|
94
92
|
"eslint": "^8.57.0",
|
|
95
93
|
"eslint-config-prettier": "^8.1.0",
|
|
96
94
|
"eslint-plugin-import": "^2.19.1",
|
|
@@ -98,7 +96,12 @@
|
|
|
98
96
|
"eslint-plugin-promise": "^6.0.0",
|
|
99
97
|
"eslint-plugin-vue": "^9.0.0",
|
|
100
98
|
"prettier": "^2.5.1",
|
|
101
|
-
"
|
|
99
|
+
"quasar": "^2.16.6",
|
|
100
|
+
"vitest": "^2.1.8",
|
|
101
|
+
"vue": "^3.5.13",
|
|
102
|
+
"vue-i18n": "^9.0.0",
|
|
103
|
+
"vue-router": "^4.0.0",
|
|
104
|
+
"vuex": "^4.0.1"
|
|
102
105
|
},
|
|
103
106
|
"browserslist": [
|
|
104
107
|
"last 10 Chrome versions",
|
package/src/components/DH2.vue
CHANGED
package/src/components/DH3.vue
CHANGED
package/src/components/DH4.vue
CHANGED
package/src/components/DH5.vue
CHANGED
package/src/components/DH6.vue
CHANGED
package/src/components/DMenu.vue
CHANGED
|
@@ -162,7 +162,7 @@ const normalizeRoutePath = (path) => {
|
|
|
162
162
|
}
|
|
163
163
|
|
|
164
164
|
const getTopRoutes = () => {
|
|
165
|
-
return ($router.options.routes || []).slice(0, -2)
|
|
165
|
+
return ($router.options.routes || []).slice(0, -2).filter(route => route?.meta?.menu?.hidden !== true)
|
|
166
166
|
}
|
|
167
167
|
|
|
168
168
|
const routeHasSubpage = (route, subpageName) => {
|
package/src/components/DPage.vue
CHANGED
|
@@ -150,11 +150,7 @@ const subroute = (to) => {
|
|
|
150
150
|
}
|
|
151
151
|
|
|
152
152
|
if (relative === to) {
|
|
153
|
-
|
|
154
|
-
return router.push({ hash: '#0' })
|
|
155
|
-
} else {
|
|
156
|
-
return router.push({ hash: '#1' })
|
|
157
|
-
}
|
|
153
|
+
return router.push({ hash: '#0' })
|
|
158
154
|
}
|
|
159
155
|
|
|
160
156
|
router.push(path)
|
|
@@ -237,6 +233,30 @@ const handleMainScrollKeys = (event) => {
|
|
|
237
233
|
container.scrollTop = nextTop
|
|
238
234
|
}
|
|
239
235
|
|
|
236
|
+
const handleContentAnchorClick = (event) => {
|
|
237
|
+
if (event.defaultPrevented || event.button !== 0 || event.altKey || event.ctrlKey || event.metaKey || event.shiftKey) {
|
|
238
|
+
return
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
const target = event.target
|
|
242
|
+
if (!(target instanceof Element)) {
|
|
243
|
+
return
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
const link = target.closest('a[href]')
|
|
247
|
+
if (!link) {
|
|
248
|
+
return
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
const href = link.getAttribute('href') || ''
|
|
252
|
+
if (!href.startsWith('#') || href === '#') {
|
|
253
|
+
return
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
event.preventDefault()
|
|
257
|
+
navigate(href)
|
|
258
|
+
}
|
|
259
|
+
|
|
240
260
|
const handlePageScroll = (scrollState) => {
|
|
241
261
|
scrolling(scrollState)
|
|
242
262
|
syncReadingProgress(scrollState?.position?.top)
|
|
@@ -327,7 +347,7 @@ watch(() => route.fullPath, () => {
|
|
|
327
347
|
|
|
328
348
|
<q-page id="page">
|
|
329
349
|
<q-scroll-area class="content" :class="main" ref="pageScrollArea">
|
|
330
|
-
<div id="scroll-container">
|
|
350
|
+
<div id="scroll-container" @click="handleContentAnchorClick">
|
|
331
351
|
<slot />
|
|
332
352
|
</div>
|
|
333
353
|
<d-page-meta v-if="!disableNav" />
|
|
@@ -21,19 +21,13 @@ const expanded = computed({
|
|
|
21
21
|
get() {
|
|
22
22
|
return store.getters['page/nodesExpanded']
|
|
23
23
|
},
|
|
24
|
-
set(
|
|
24
|
+
set() {
|
|
25
25
|
// console.log(value)
|
|
26
26
|
}
|
|
27
27
|
})
|
|
28
28
|
const selected = computed({
|
|
29
29
|
get() {
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
if (store.state.page.relative !== '' && anchor === 0) {
|
|
33
|
-
anchor = anchor + 1
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
return anchor
|
|
30
|
+
return store.state.page.anchor
|
|
37
31
|
},
|
|
38
32
|
set(value) {
|
|
39
33
|
navigate(value)
|
|
@@ -90,7 +84,7 @@ onMounted(() => {
|
|
|
90
84
|
const id = route.hash.replace(/^#+/g, '')
|
|
91
85
|
if (id) {
|
|
92
86
|
setTimeout(() => {
|
|
93
|
-
anchor(
|
|
87
|
+
anchor(route.hash)
|
|
94
88
|
}, 500)
|
|
95
89
|
}
|
|
96
90
|
})
|
|
@@ -156,6 +156,7 @@ const getVersionSiblingPath = (offset) => {
|
|
|
156
156
|
const currentPath = normalizeRoutePath(route.matched?.[0]?.path || `/${store.state.page.base}`)
|
|
157
157
|
const routes = router.options.routes
|
|
158
158
|
.slice(0, -2)
|
|
159
|
+
.filter(item => item?.meta?.menu?.hidden !== true)
|
|
159
160
|
.filter(item => !versionId || item?.meta?.version === versionId)
|
|
160
161
|
|
|
161
162
|
const index = routes.findIndex(item => normalizeRoutePath(item.path) === currentPath)
|
|
@@ -30,27 +30,27 @@ import DPageExpandable from './DPageExpandable.vue'
|
|
|
30
30
|
<template v-for="(token, index) in tokens" :key="`${token.tag}-${index}`">
|
|
31
31
|
<d-h2
|
|
32
32
|
v-if="token.tag === 'h2'"
|
|
33
|
-
:id="
|
|
33
|
+
:id="token.anchorId"
|
|
34
34
|
:value="token.content"
|
|
35
35
|
/>
|
|
36
36
|
<d-h3
|
|
37
37
|
v-else-if="token.tag === 'h3'"
|
|
38
|
-
:id="
|
|
38
|
+
:id="token.anchorId"
|
|
39
39
|
:value="token.content"
|
|
40
40
|
/>
|
|
41
41
|
<d-h4
|
|
42
42
|
v-else-if="token.tag === 'h4'"
|
|
43
|
-
:id="
|
|
43
|
+
:id="token.anchorId"
|
|
44
44
|
:value="token.content"
|
|
45
45
|
/>
|
|
46
46
|
<d-h5
|
|
47
47
|
v-else-if="token.tag === 'h5'"
|
|
48
|
-
:id="
|
|
48
|
+
:id="token.anchorId"
|
|
49
49
|
:value="token.content"
|
|
50
50
|
/>
|
|
51
51
|
<d-h6
|
|
52
52
|
v-else-if="token.tag === 'h6'"
|
|
53
|
-
:id="
|
|
53
|
+
:id="token.anchorId"
|
|
54
54
|
:value="token.content"
|
|
55
55
|
/>
|
|
56
56
|
|
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
import MarkdownIt from 'markdown-it'
|
|
2
2
|
import attrs from 'markdown-it-attrs'
|
|
3
|
+
import GithubSlugger from 'github-slugger'
|
|
4
|
+
import katex from 'katex'
|
|
5
|
+
import texmath from 'markdown-it-texmath'
|
|
3
6
|
|
|
4
7
|
const ALERT_MESSAGE_TYPES = new Set([
|
|
5
8
|
'note',
|
|
@@ -12,6 +15,10 @@ const ALERT_MESSAGE_TYPES = new Set([
|
|
|
12
15
|
const QUICK_LINKS_MARKER_PREFIX = '@@DOCSECTOR_QUICK_LINKS_'
|
|
13
16
|
const EXPANDABLE_MARKER_PREFIX = '@@DOCSECTOR_EXPANDABLE_'
|
|
14
17
|
const CODE_SEGMENT_MARKER_PREFIX = '@@DOCSECTOR_CODE_SEGMENT_'
|
|
18
|
+
const MATH_KATEX_OPTIONS = {
|
|
19
|
+
throwOnError: false,
|
|
20
|
+
strict: 'ignore'
|
|
21
|
+
}
|
|
15
22
|
|
|
16
23
|
const parseAlertMarker = (rawContent = '') => {
|
|
17
24
|
const match = String(rawContent).trim().match(/^\[!\s*([A-Za-z]+)\s*\]\s*(.*)$/s)
|
|
@@ -100,7 +107,7 @@ const restoreShieldedCodeSegments = (source = '', codeSegmentsMap = new Map()) =
|
|
|
100
107
|
let restored = String(source)
|
|
101
108
|
|
|
102
109
|
codeSegmentsMap.forEach((content, marker) => {
|
|
103
|
-
restored = restored.replaceAll(marker, content)
|
|
110
|
+
restored = restored.replaceAll(marker, () => content)
|
|
104
111
|
})
|
|
105
112
|
|
|
106
113
|
return restored
|
|
@@ -299,10 +306,24 @@ const pushSourceCodeToken = (tokens, element, parserState) => {
|
|
|
299
306
|
})
|
|
300
307
|
}
|
|
301
308
|
|
|
309
|
+
const installMathSupport = (markdown) => {
|
|
310
|
+
markdown.use(texmath, {
|
|
311
|
+
engine: katex,
|
|
312
|
+
delimiters: 'dollars',
|
|
313
|
+
katexOptions: MATH_KATEX_OPTIONS
|
|
314
|
+
})
|
|
315
|
+
|
|
316
|
+
return markdown
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
const renderBlockToken = (markdown, element, env) => {
|
|
320
|
+
return markdown.renderer.render([element], markdown.options, env).trim()
|
|
321
|
+
}
|
|
322
|
+
|
|
302
323
|
const createMarkdownBlockParser = () => {
|
|
303
|
-
const markdown = new MarkdownIt({
|
|
324
|
+
const markdown = installMathSupport(new MarkdownIt({
|
|
304
325
|
html: true
|
|
305
|
-
})
|
|
326
|
+
}))
|
|
306
327
|
|
|
307
328
|
markdown.use(attrs, {
|
|
308
329
|
leftDelimiter: ':',
|
|
@@ -314,9 +335,9 @@ const createMarkdownBlockParser = () => {
|
|
|
314
335
|
}
|
|
315
336
|
|
|
316
337
|
const createMarkdownInlineParser = () => {
|
|
317
|
-
return new MarkdownIt({
|
|
338
|
+
return installMathSupport(new MarkdownIt({
|
|
318
339
|
html: true
|
|
319
|
-
})
|
|
340
|
+
}))
|
|
320
341
|
}
|
|
321
342
|
|
|
322
343
|
const normalizePageSectionSource = (source = '') => {
|
|
@@ -326,10 +347,24 @@ const normalizePageSectionSource = (source = '') => {
|
|
|
326
347
|
.replace(/&/g, '&')
|
|
327
348
|
}
|
|
328
349
|
|
|
350
|
+
const createParserState = () => ({
|
|
351
|
+
codeIndex: 0,
|
|
352
|
+
headingSlugger: new GithubSlugger()
|
|
353
|
+
})
|
|
354
|
+
|
|
355
|
+
const getHeadingAnchorId = (markdown, currentTag, element, env, parserState) => {
|
|
356
|
+
if (!currentTag || !currentTag.match(/^h[2-6]$/)) {
|
|
357
|
+
return ''
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
const headingText = markdown.renderer.renderInlineAsText(element.children || [], markdown.options, env).trim()
|
|
361
|
+
return parserState.headingSlugger.slug(headingText)
|
|
362
|
+
}
|
|
363
|
+
|
|
329
364
|
export const tokenizePageSectionSource = (source = '', options = {}) => {
|
|
330
365
|
const {
|
|
331
366
|
allowHeadingTokens = true,
|
|
332
|
-
parserState =
|
|
367
|
+
parserState = createParserState()
|
|
333
368
|
} = options
|
|
334
369
|
const normalizedSource = normalizePageSectionSource(source)
|
|
335
370
|
const { source: sourceWithShieldedCode, codeSegmentsMap } = shieldMarkdownCodeSegments(normalizedSource)
|
|
@@ -444,6 +479,11 @@ export const tokenizePageSectionSource = (source = '', options = {}) => {
|
|
|
444
479
|
return
|
|
445
480
|
}
|
|
446
481
|
|
|
482
|
+
if (element.type === 'math_block') {
|
|
483
|
+
blockquote.content += renderBlockToken(markdown, element, markdownEnv)
|
|
484
|
+
return
|
|
485
|
+
}
|
|
486
|
+
|
|
447
487
|
if (element.type.endsWith('_open')) {
|
|
448
488
|
appendBlockquoteTag(element, true)
|
|
449
489
|
return
|
|
@@ -481,6 +521,8 @@ export const tokenizePageSectionSource = (source = '', options = {}) => {
|
|
|
481
521
|
|
|
482
522
|
switch (element.type) {
|
|
483
523
|
case 'inline':
|
|
524
|
+
const anchorId = getHeadingAnchorId(markdown, tag, element, markdownEnv, parserState)
|
|
525
|
+
|
|
484
526
|
if (expandableMap.has(element.content.trim())) {
|
|
485
527
|
const data = expandableMap.get(element.content.trim())
|
|
486
528
|
|
|
@@ -510,6 +552,7 @@ export const tokenizePageSectionSource = (source = '', options = {}) => {
|
|
|
510
552
|
tokens.push({
|
|
511
553
|
tag,
|
|
512
554
|
map: element.map,
|
|
555
|
+
anchorId,
|
|
513
556
|
content: element.content,
|
|
514
557
|
info: element.info
|
|
515
558
|
})
|
|
@@ -519,6 +562,13 @@ export const tokenizePageSectionSource = (source = '', options = {}) => {
|
|
|
519
562
|
pushSourceCodeToken(tokens, element, parserState)
|
|
520
563
|
break
|
|
521
564
|
|
|
565
|
+
case 'math_block':
|
|
566
|
+
tokens.push({
|
|
567
|
+
tag: 'html',
|
|
568
|
+
content: renderBlockToken(markdown, element, markdownEnv)
|
|
569
|
+
})
|
|
570
|
+
break
|
|
571
|
+
|
|
522
572
|
case 'html_block':
|
|
523
573
|
tokens.push({
|
|
524
574
|
tag: 'html',
|
|
@@ -574,6 +624,9 @@ export const tokenizePageSectionSource = (source = '', options = {}) => {
|
|
|
574
624
|
case 'inline':
|
|
575
625
|
parent.content += element.content
|
|
576
626
|
break
|
|
627
|
+
case 'math_block':
|
|
628
|
+
parent.content += renderBlockToken(markdown, element, markdownEnv)
|
|
629
|
+
break
|
|
577
630
|
case 'html_inline':
|
|
578
631
|
case 'html_block':
|
|
579
632
|
parent.content += element.content
|
|
@@ -9,13 +9,34 @@ export default function useNavigator() {
|
|
|
9
9
|
const route = useRoute()
|
|
10
10
|
const selected = ref(null)
|
|
11
11
|
|
|
12
|
+
const normalizeDomAnchorId = (id) => {
|
|
13
|
+
if (id === null || id === undefined || id === false) {
|
|
14
|
+
return ''
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
let normalized = String(id).replace(/^#+/g, '')
|
|
18
|
+
|
|
19
|
+
try {
|
|
20
|
+
normalized = decodeURIComponent(normalized)
|
|
21
|
+
} catch {
|
|
22
|
+
// Keep the raw fragment when it is not valid percent-encoding.
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
return normalized
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const normalizeStoreAnchorId = (id) => {
|
|
29
|
+
const normalized = normalizeDomAnchorId(id)
|
|
30
|
+
return normalized === '0' ? 0 : normalized
|
|
31
|
+
}
|
|
32
|
+
|
|
12
33
|
const register = (id) => {
|
|
13
|
-
store.commit('page/pushAnchors', id)
|
|
34
|
+
store.commit('page/pushAnchors', normalizeStoreAnchorId(id))
|
|
14
35
|
}
|
|
15
36
|
|
|
16
37
|
const index = (id, child = false) => {
|
|
17
38
|
store.commit('page/pushNodes', {
|
|
18
|
-
id,
|
|
39
|
+
id: normalizeStoreAnchorId(id),
|
|
19
40
|
label: selected.value,
|
|
20
41
|
child,
|
|
21
42
|
children: []
|
|
@@ -23,15 +44,17 @@ export default function useNavigator() {
|
|
|
23
44
|
}
|
|
24
45
|
|
|
25
46
|
const select = (id) => {
|
|
26
|
-
|
|
27
|
-
|
|
47
|
+
const normalized = normalizeStoreAnchorId(id)
|
|
48
|
+
|
|
49
|
+
store.commit('page/setAnchor', normalized)
|
|
50
|
+
store.commit('page/pushNodesExpanded', normalized)
|
|
28
51
|
}
|
|
29
52
|
|
|
30
53
|
const anchor = (id, toSelect = true) => {
|
|
31
54
|
store.commit('page/setScrolling', false)
|
|
32
55
|
|
|
33
|
-
|
|
34
|
-
const Anchor = document.getElementById(
|
|
56
|
+
const anchorId = normalizeDomAnchorId(id)
|
|
57
|
+
const Anchor = document.getElementById(anchorId)
|
|
35
58
|
|
|
36
59
|
if (Anchor !== null && typeof Anchor === 'object') {
|
|
37
60
|
const ScrollTarget = scroll.getScrollTarget(Anchor)
|
|
@@ -45,7 +68,7 @@ export default function useNavigator() {
|
|
|
45
68
|
}
|
|
46
69
|
|
|
47
70
|
if (toSelect) {
|
|
48
|
-
select(
|
|
71
|
+
select(anchorId)
|
|
49
72
|
}
|
|
50
73
|
}
|
|
51
74
|
|
|
@@ -60,12 +83,13 @@ export default function useNavigator() {
|
|
|
60
83
|
|
|
61
84
|
for (let i = 0; i < anchors.length; i++) {
|
|
62
85
|
const anchorId = anchors[i]
|
|
86
|
+
const domAnchorId = normalizeDomAnchorId(anchorId)
|
|
63
87
|
|
|
64
|
-
if (
|
|
88
|
+
if (domAnchorId === '0') {
|
|
65
89
|
continue
|
|
66
90
|
}
|
|
67
91
|
|
|
68
|
-
const Anchor = document.getElementById(
|
|
92
|
+
const Anchor = document.getElementById(domAnchorId)
|
|
69
93
|
let AnchorOffsetTop = 20
|
|
70
94
|
if (Anchor !== null && typeof Anchor === 'object') {
|
|
71
95
|
AnchorOffsetTop = Anchor.offsetTop
|
|
@@ -78,24 +102,30 @@ export default function useNavigator() {
|
|
|
78
102
|
}
|
|
79
103
|
|
|
80
104
|
const navigate = (value, toAnchor = true) => {
|
|
105
|
+
const domAnchorId = normalizeDomAnchorId(value)
|
|
106
|
+
const currentRouteAnchorId = normalizeDomAnchorId(route.hash)
|
|
107
|
+
|
|
81
108
|
if (toAnchor) {
|
|
82
|
-
if (
|
|
83
|
-
anchor(
|
|
109
|
+
if (domAnchorId !== '' && domAnchorId === currentRouteAnchorId) {
|
|
110
|
+
anchor(domAnchorId)
|
|
84
111
|
return
|
|
85
112
|
} else if (value === null) {
|
|
86
|
-
anchor(
|
|
113
|
+
anchor(store.state.page.anchor, false)
|
|
87
114
|
return
|
|
88
115
|
}
|
|
89
116
|
}
|
|
90
117
|
|
|
91
|
-
router.push(
|
|
118
|
+
router.push({
|
|
119
|
+
path: route.path,
|
|
120
|
+
hash: domAnchorId === '' ? '' : `#${domAnchorId}`
|
|
121
|
+
})
|
|
92
122
|
|
|
93
123
|
if (toAnchor) {
|
|
94
124
|
if (Platform.is.desktop) {
|
|
95
|
-
anchor(
|
|
125
|
+
anchor(domAnchorId)
|
|
96
126
|
} else {
|
|
97
127
|
setTimeout(() => {
|
|
98
|
-
anchor(
|
|
128
|
+
anchor(domAnchorId)
|
|
99
129
|
}, 600)
|
|
100
130
|
}
|
|
101
131
|
}
|
package/src/css/app.sass
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
@import 'katex/dist/katex.min.css'
|
|
2
|
+
|
|
1
3
|
/* --- Docsector Reader --- */
|
|
2
4
|
@font-face
|
|
3
5
|
font-family: "Fira Code Nerd Font"
|
|
@@ -187,6 +189,16 @@ body.body--dark
|
|
|
187
189
|
display: inline
|
|
188
190
|
line-height: 0.85em
|
|
189
191
|
|
|
192
|
+
.katex
|
|
193
|
+
color: inherit
|
|
194
|
+
max-width: 100%
|
|
195
|
+
|
|
196
|
+
.katex-display
|
|
197
|
+
max-width: 100%
|
|
198
|
+
overflow-x: auto
|
|
199
|
+
overflow-y: hidden
|
|
200
|
+
padding: 0.35rem 0.1rem
|
|
201
|
+
|
|
190
202
|
a
|
|
191
203
|
text-decoration: none
|
|
192
204
|
outline: 0
|
package/src/pages/404Page.vue
CHANGED
|
@@ -3,12 +3,12 @@
|
|
|
3
3
|
<q-page class="row" padding>
|
|
4
4
|
<q-scroll-area class="content col text-center">
|
|
5
5
|
<p>
|
|
6
|
-
<img src="sad.svg" style="width:30vw;max-width:150px;" />
|
|
6
|
+
<img src="/sad.svg" alt="404 illustration" style="width:30vw;max-width:150px;" />
|
|
7
7
|
</p>
|
|
8
8
|
<p class="text-faded">Sorry, nothing here...
|
|
9
9
|
<strong>(404)</strong>
|
|
10
10
|
</p>
|
|
11
|
-
<q-btn color="secondary" style="width:200px;" @click="$router.
|
|
11
|
+
<q-btn color="secondary" style="width:200px;" @click="$router.push('/')">Go home</q-btn>
|
|
12
12
|
</q-scroll-area>
|
|
13
13
|
</q-page>
|
|
14
14
|
</q-page-container>
|
|
@@ -7,9 +7,9 @@ Docsector Reader is a documentation rendering engine built with Vue 3, Quasar v2
|
|
|
7
7
|
- [Getting Started](/guide/getting-started/overview/)
|
|
8
8
|
- [Configuration](/guide/configuration/overview/)
|
|
9
9
|
- [Pages and Routing](/guide/pages-and-routing/overview/)
|
|
10
|
-
- [
|
|
11
|
-
- [
|
|
12
|
-
- [
|
|
10
|
+
- [Basic](/manual/basic/d-menu/overview/)
|
|
11
|
+
- [Content](/manual/content/blocks/paragraphs/overview/)
|
|
12
|
+
- [Structures](/manual/content/structures/books/overview/)
|
|
13
13
|
|
|
14
14
|
## About
|
|
15
15
|
|
|
@@ -7,9 +7,9 @@ Docsector Reader e um motor de documentacao construído com Vue 3, Quasar v2 e V
|
|
|
7
7
|
- [Comecando](/guide/getting-started/overview/)
|
|
8
8
|
- [Configuracao](/guide/configuration/overview/)
|
|
9
9
|
- [Paginas e Rotas](/guide/pages-and-routing/overview/)
|
|
10
|
-
- [
|
|
11
|
-
- [
|
|
12
|
-
- [
|
|
10
|
+
- [Básico](/manual/basic/d-menu/overview/)
|
|
11
|
+
- [Conteúdo](/manual/content/blocks/paragraphs/overview/)
|
|
12
|
+
- [Estruturas](/manual/content/structures/books/overview/)
|
|
13
13
|
|
|
14
14
|
## Sobre
|
|
15
15
|
|