@docsector/docsector-reader 4.0.0 โ†’ 4.1.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
@@ -3,7 +3,7 @@
3
3
  </p>
4
4
  <h1 align="center">Docsector Reader ๐Ÿ“–</h1>
5
5
  <p align="center">
6
- <i>A documentation rendering engine built with Vue 3, Quasar v2 and Vite.</i>
6
+ <i>A documentation rendering engine built with Vue 3, Quasar v2 and Vite with AI features.</i>
7
7
  </p>
8
8
  <p align="center">
9
9
  <a href="https://www.npmjs.com/package/@docsector/docsector-reader">
@@ -50,7 +50,7 @@ Transform Markdown content into beautiful, navigable documentation sites โ€” wit
50
50
  - ๐Ÿšจ **GitHub-Style Alerts** โ€” Native support for `[!NOTE]`, `[!TIP]`, `[!IMPORTANT]`, `[!WARNING]`, and `[!CAUTION]`
51
51
  - ๐ŸŒ **Internationalization (i18n)** โ€” Multi-language support with HJSON locale files and per-page translations
52
52
  - ๐ŸŒ— **Dark/Light Mode** โ€” Automatic theme switching with Quasar Dark Plugin
53
- - ๐Ÿ”— **Anchor Navigation** โ€” Right-side Table of Contents tree with scroll tracking and auto-scroll to active section
53
+ - ๐Ÿ”— **Anchor Navigation** โ€” Right-side Table of Contents tree with stable scroll tracking, auto-scroll to the active section, and active-heading resolution based on the last heading that crossed the content threshold
54
54
  - ๐Ÿ–ฑ๏ธ **Active Menu Item UX** โ€” Active menu entries keep pointer cursor, clear URL hash without redundant navigation, and prevent accidental label text selection
55
55
  - ๐Ÿ”Ž **Search** โ€” Menu search across all documentation content and tags
56
56
  - ๐Ÿ“ฑ **Responsive** โ€” Mobile-friendly with collapsible sidebar and drawers
@@ -65,7 +65,7 @@ Transform Markdown content into beautiful, navigable documentation sites โ€” wit
65
65
  - ๐Ÿ“Š **Translation Progress** โ€” Automatic translation percentage based on header coverage
66
66
  - ๐ŸŒ **Accurate Available Translations** โ€” Locale availability counter now uses actual localized page source presence, avoiding false negatives when metadata is equal
67
67
  - ๐Ÿ  **Markdown Home at Root** โ€” Homepage is rendered from `src/pages/Homepage.{lang}.md` directly at `/`
68
- - ๐ŸŒ **Remote README as Home** โ€” Optional build-time remote README source for homepage with automatic local fallback
68
+ - ๐ŸŒ **Remote README as Home** โ€” Optional build-time remote README source for homepage with automatic local fallback and automatic primary-title handoff when the remote README already provides the project heading
69
69
  - ๐Ÿ”— **GitHub-Compatible Heading Anchors** โ€” Markdown headings use GitHub-style slugs so standard README Table of Contents links work inside Docsector
70
70
  - ๐Ÿงฌ **Scaffolded Homepage Override Wiring** โ€” New consumer projects automatically wire `virtual:docsector-homepage-override` into i18n message building
71
71
  - ๐Ÿ“– **Expandable Markdown Sections** โ€” Use `<d-block-expandable title="...">...</d-block-expandable>` to collapse secondary content while keeping rich Markdown support inside the body
@@ -79,6 +79,7 @@ Transform Markdown content into beautiful, navigable documentation sites โ€” wit
79
79
  - ๐Ÿ—ƒ๏ธ **Multi-Version History** โ€” Archive older major versions under `src/pages/.old/<version>/` and expose them at prefixed routes (e.g. `/v0.x/guide/...`) while keeping the current docs at unprefixed routes
80
80
  - ๐Ÿท๏ธ **Version Selector Badges** โ€” Every version in the sidebar selector displays a color-coded badge: green for released, orange for draft, red for deprecated; fully customizable via `badge: { label, color, textColor }`
81
81
  - ๐Ÿ“‚ **Tabbed Code Blocks** โ€” Group consecutive fenced code blocks into tabs using the `group` and `tab` attributes in the fence info line
82
+ - ๐Ÿงช **Live Code Example Blocks** โ€” Use `<d-block-code-example src="..." />` to render bundled Vue SFC examples with a live preview, GitHub source link, source toggle, and CodePen export for compatible examples
82
83
  - ๐Ÿž **Breadcrumb Path Display** โ€” Show a file path breadcrumb above code blocks with the `breadcrumb` attribute; renders as clickable path segments
83
84
  - ๐ŸŽจ **File Type Icons** โ€” Automatically resolves file extension or filename to a Material Icon Theme SVG icon, shown inline in tabs and beside the last breadcrumb segment
84
85
  - โš™๏ธ **Single Config File** โ€” Customize branding, links, and languages via `docsector.config.js`
@@ -360,7 +361,8 @@ You can configure Docsector Reader to use a remote README as homepage content.
360
361
 
361
362
  - Fetch happens at build-time.
362
363
  - The same README content is used for all configured languages.
363
- - If fetch fails, it falls back to local `src/pages/Homepage.{lang}.md` by default.
364
+ - When the remote README resolves successfully, Docsector hides the autogenerated homepage title and uses the README's own primary heading in the rendered content.
365
+ - If fetch fails, it falls back to local `src/pages/Homepage.{lang}.md` by default and keeps the usual autogenerated homepage title.
364
366
  - Standard GitHub-style heading links and README Table of Contents fragments keep working in the rendered homepage.
365
367
 
366
368
  ### Configure
@@ -1022,6 +1024,22 @@ Notes:
1022
1024
  Supported alert types: `NOTE`, `TIP`, `IMPORTANT`, `WARNING`, `CAUTION`.
1023
1025
  Regular blockquotes without `[!TYPE]` continue to work normally.
1024
1026
 
1027
+ ### Code Example Blocks
1028
+
1029
+ ```html
1030
+ <d-block-code-example src="manual/code-examples/basic-counter" title="Basic counter">
1031
+ Optional caption rendered as inline Markdown.
1032
+ </d-block-code-example>
1033
+ ```
1034
+
1035
+ Notes:
1036
+
1037
+ - Store live examples as Vue SFCs under `src/examples/**/*.vue`; for example, `src="manual/code-examples/basic-counter"` resolves `src/examples/manual/code-examples/BasicCounter.vue` after kebab-case normalization.
1038
+ - Readers get a live preview, a GitHub button for the example SFC, a source button with Template / Script / Style / All tabs, and a CodePen button when the example can be exported safely.
1039
+ - Use `expanded="true"` only when the source code should be visible by default.
1040
+ - CodePen export currently supports plain Vue SFCs with a template, optional style, and an Options API `export default` script. Named imports from `vue` and `quasar` are converted to browser globals.
1041
+ - Examples using `<script setup>`, TypeScript scripts, or local imports still render in Docsector, but the CodePen action is disabled. Use `codepen="false"` to hide it intentionally.
1042
+
1025
1043
  ### File Attachment Blocks
1026
1044
 
1027
1045
  ```html
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 = '4.0.0'
26
+ const VERSION = '4.1.0'
27
27
 
28
28
  const HELP = `
29
29
  Docsector Reader v${VERSION}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@docsector/docsector-reader",
3
- "version": "4.0.0",
3
+ "version": "4.1.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",
@@ -0,0 +1,423 @@
1
+ <script setup>
2
+ import { computed, markRaw, ref, watch } from 'vue'
3
+ import { openURL, Quasar, useQuasar } from 'quasar'
4
+
5
+ import { resolveCodeExample } from 'virtual:docsector-code-examples'
6
+ import docsectorConfig from 'docsector.config.js'
7
+
8
+ import DBlockSourceCode from './DBlockSourceCode.vue'
9
+ import {
10
+ canCreateCodepenPayload,
11
+ createCodeExampleGitHubUrl,
12
+ createCodeExampleTabs,
13
+ createCodepenPayload,
14
+ getCodepenUnsupportedReason
15
+ } from './code-example-source'
16
+
17
+ defineOptions({
18
+ name: 'DBlockCodeExample'
19
+ })
20
+
21
+ const props = defineProps({
22
+ index: {
23
+ type: Number,
24
+ required: true
25
+ },
26
+ src: {
27
+ type: String,
28
+ default: ''
29
+ },
30
+ title: {
31
+ type: String,
32
+ default: ''
33
+ },
34
+ caption: {
35
+ type: String,
36
+ default: ''
37
+ },
38
+ expanded: {
39
+ type: Boolean,
40
+ default: false
41
+ },
42
+ codepen: {
43
+ type: Boolean,
44
+ default: true
45
+ },
46
+ scrollable: {
47
+ type: Boolean,
48
+ default: false
49
+ },
50
+ overflow: {
51
+ type: Boolean,
52
+ default: false
53
+ },
54
+ height: {
55
+ type: String,
56
+ default: ''
57
+ }
58
+ })
59
+
60
+ const $q = useQuasar()
61
+
62
+ const isBusy = ref(false)
63
+ const errorMessage = ref('')
64
+ const component = ref(null)
65
+ const sourceText = ref('')
66
+ const sourceTabs = ref([])
67
+ const sourceOpen = ref(props.expanded)
68
+ const exampleFilePath = ref('')
69
+ let requestIndex = 0
70
+
71
+ const displayTitle = computed(() => props.title || props.src || 'Code example')
72
+ const frameTone = computed(() => $q.dark.isActive ? 'dark' : 'light')
73
+ const hasSource = computed(() => sourceText.value.trim().length > 0)
74
+ const codepenUnsupportedReason = computed(() => {
75
+ if (!hasSource.value) {
76
+ return 'Source code is still loading.'
77
+ }
78
+
79
+ return getCodepenUnsupportedReason(sourceText.value)
80
+ })
81
+ const canOpenCodepen = computed(() => props.codepen && hasSource.value && canCreateCodepenPayload(sourceText.value))
82
+ const codepenTooltip = computed(() => canOpenCodepen.value ? 'Edit in CodePen' : codepenUnsupportedReason.value)
83
+ const githubUrl = computed(() => createCodeExampleGitHubUrl(exampleFilePath.value, docsectorConfig))
84
+ const canOpenGitHub = computed(() => githubUrl.value !== '')
85
+ const previewStyle = computed(() => {
86
+ const style = {}
87
+ const normalizedHeight = normalizeCssLength(props.height)
88
+
89
+ if (normalizedHeight) {
90
+ style.height = normalizedHeight
91
+ } else if (props.scrollable) {
92
+ style.height = '500px'
93
+ }
94
+
95
+ return style
96
+ })
97
+
98
+ watch(() => props.expanded, (value) => {
99
+ sourceOpen.value = value
100
+ })
101
+
102
+ watch(() => props.src, () => {
103
+ loadExample()
104
+ }, { immediate: true })
105
+
106
+ function normalizeCssLength (value = '') {
107
+ const normalized = String(value || '').trim()
108
+
109
+ if (!normalized) {
110
+ return ''
111
+ }
112
+
113
+ if (/^-?\d+(?:\.\d+)?$/.test(normalized)) {
114
+ return `${normalized}px`
115
+ }
116
+
117
+ return normalized
118
+ }
119
+
120
+ async function loadExample () {
121
+ const currentRequest = ++requestIndex
122
+ const resolved = resolveCodeExample(props.src)
123
+
124
+ isBusy.value = true
125
+ errorMessage.value = ''
126
+ component.value = null
127
+ sourceText.value = ''
128
+ sourceTabs.value = []
129
+ exampleFilePath.value = ''
130
+
131
+ if (!props.src) {
132
+ errorMessage.value = 'Code example source is missing.'
133
+ isBusy.value = false
134
+ return
135
+ }
136
+
137
+ if (!resolved.exists || typeof resolved.loadComponent !== 'function' || typeof resolved.loadSource !== 'function') {
138
+ errorMessage.value = `Code example not found: ${resolved.id || props.src}`
139
+ isBusy.value = false
140
+ return
141
+ }
142
+
143
+ try {
144
+ const [componentModule, rawSource] = await Promise.all([
145
+ resolved.loadComponent(),
146
+ resolved.loadSource()
147
+ ])
148
+
149
+ if (currentRequest !== requestIndex) {
150
+ return
151
+ }
152
+
153
+ component.value = markRaw(componentModule.default || componentModule)
154
+ sourceText.value = String(rawSource || '')
155
+ sourceTabs.value = createCodeExampleTabs(sourceText.value)
156
+ exampleFilePath.value = resolved.filePath || ''
157
+ } catch (err) {
158
+ if (currentRequest !== requestIndex) {
159
+ return
160
+ }
161
+
162
+ errorMessage.value = err?.message || `Unable to load code example: ${props.src}`
163
+ } finally {
164
+ if (currentRequest === requestIndex) {
165
+ isBusy.value = false
166
+ }
167
+ }
168
+ }
169
+
170
+ function toggleSource () {
171
+ sourceOpen.value = !sourceOpen.value
172
+ }
173
+
174
+ function submitCodepenPayload (payload) {
175
+ if (typeof document === 'undefined') {
176
+ return
177
+ }
178
+
179
+ const form = document.createElement('form')
180
+ const input = document.createElement('input')
181
+
182
+ form.method = 'post'
183
+ form.action = 'https://codepen.io/pen/define/'
184
+ form.target = '_blank'
185
+ form.rel = 'noopener'
186
+ form.style.display = 'none'
187
+
188
+ input.type = 'hidden'
189
+ input.name = 'data'
190
+ input.value = JSON.stringify(payload)
191
+
192
+ form.appendChild(input)
193
+ document.body.appendChild(form)
194
+ form.submit()
195
+ form.remove()
196
+ }
197
+
198
+ function openCodepen () {
199
+ if (!canOpenCodepen.value) {
200
+ return
201
+ }
202
+
203
+ const sourceUrl = typeof window === 'undefined'
204
+ ? ''
205
+ : `${window.location.origin}${window.location.pathname}${window.location.hash}`
206
+
207
+ submitCodepenPayload(createCodepenPayload(sourceText.value, {
208
+ title: displayTitle.value,
209
+ quasarVersion: Quasar.version,
210
+ sourceUrl
211
+ }))
212
+ }
213
+
214
+ function openGitHub () {
215
+ if (canOpenGitHub.value) {
216
+ openURL(githubUrl.value)
217
+ }
218
+ }
219
+ </script>
220
+
221
+ <template>
222
+ <div
223
+ class="d-block-code-example"
224
+ :class="`d-block-code-example--${frameTone}`"
225
+ >
226
+ <div class="d-block-code-example__toolbar">
227
+ <div class="d-block-code-example__title">{{ displayTitle }}</div>
228
+
229
+ <q-space />
230
+
231
+ <q-btn
232
+ class="d-block-code-example__button"
233
+ dense
234
+ flat
235
+ round
236
+ icon="fab fa-github"
237
+ :disable="!canOpenGitHub"
238
+ aria-label="View example on GitHub"
239
+ @click="openGitHub"
240
+ >
241
+ <q-tooltip>{{ canOpenGitHub ? 'View on GitHub' : 'GitHub source is unavailable' }}</q-tooltip>
242
+ </q-btn>
243
+
244
+ <q-btn
245
+ v-if="codepen"
246
+ class="d-block-code-example__button"
247
+ dense
248
+ flat
249
+ round
250
+ icon="fab fa-codepen"
251
+ :disable="!canOpenCodepen"
252
+ aria-label="Edit in CodePen"
253
+ @click="openCodepen"
254
+ >
255
+ <q-tooltip>{{ codepenTooltip }}</q-tooltip>
256
+ </q-btn>
257
+
258
+ <q-btn
259
+ class="d-block-code-example__button"
260
+ dense
261
+ flat
262
+ round
263
+ icon="code"
264
+ :disable="!hasSource"
265
+ :aria-label="sourceOpen ? 'Hide source' : 'View source'"
266
+ @click="toggleSource"
267
+ >
268
+ <q-tooltip>{{ sourceOpen ? 'Hide source' : 'View source' }}</q-tooltip>
269
+ </q-btn>
270
+ </div>
271
+
272
+ <q-slide-transition>
273
+ <div
274
+ v-show="sourceOpen && hasSource"
275
+ class="d-block-code-example__source"
276
+ >
277
+ <d-block-source-code
278
+ :index="index"
279
+ language="vue"
280
+ :text="sourceText"
281
+ :tabs="sourceTabs"
282
+ />
283
+ </div>
284
+ </q-slide-transition>
285
+
286
+ <q-linear-progress
287
+ v-if="isBusy"
288
+ color="primary"
289
+ indeterminate
290
+ />
291
+
292
+ <div
293
+ class="d-block-code-example__preview"
294
+ :class="{
295
+ 'd-block-code-example__preview--scrollable': scrollable,
296
+ 'd-block-code-example__preview--overflow': overflow
297
+ }"
298
+ :style="previewStyle"
299
+ >
300
+ <component
301
+ v-if="component && !errorMessage"
302
+ :is="component"
303
+ class="d-block-code-example__component"
304
+ />
305
+
306
+ <div
307
+ v-else-if="errorMessage"
308
+ class="d-block-code-example__fallback"
309
+ >
310
+ <q-icon
311
+ name="warning"
312
+ size="22px"
313
+ />
314
+ <span>{{ errorMessage }}</span>
315
+ </div>
316
+ </div>
317
+
318
+ <div
319
+ v-if="caption"
320
+ class="d-block-code-example__caption"
321
+ v-html="caption"
322
+ ></div>
323
+ </div>
324
+ </template>
325
+
326
+ <style lang="sass">
327
+ body.body--light
328
+ --d-code-example-bg: #ffffff
329
+ --d-code-example-border: rgba(37, 67, 45, 0.16)
330
+ --d-code-example-toolbar-bg: #f6f8f5
331
+ --d-code-example-toolbar-text: #26352b
332
+ --d-code-example-preview-bg: #ffffff
333
+ --d-code-example-caption: #405148
334
+ --d-code-example-muted: #5d7563
335
+
336
+ body.body--dark
337
+ --d-code-example-bg: #111512
338
+ --d-code-example-border: rgba(197, 220, 200, 0.18)
339
+ --d-code-example-toolbar-bg: #1a211c
340
+ --d-code-example-toolbar-text: #e8efe9
341
+ --d-code-example-preview-bg: #0c0f0d
342
+ --d-code-example-caption: #c7d4ca
343
+ --d-code-example-muted: #9aafa0
344
+
345
+ .d-block-code-example
346
+ background: var(--d-code-example-bg)
347
+ border: 1px solid var(--d-code-example-border)
348
+ border-radius: 6px
349
+ box-shadow: 0 1px 1px rgb(0 0 0 / 8%)
350
+ margin: 18px 0
351
+ max-width: calc(100vw - 40px)
352
+ overflow: hidden
353
+
354
+ &__toolbar
355
+ align-items: center
356
+ background: var(--d-code-example-toolbar-bg)
357
+ color: var(--d-code-example-toolbar-text)
358
+ display: flex
359
+ gap: 4px
360
+ min-height: 42px
361
+ min-width: 0
362
+ padding: 4px 8px 4px 14px
363
+
364
+ &__title
365
+ font-size: 14px
366
+ font-weight: 600
367
+ line-height: 20px
368
+ min-width: 0
369
+ overflow: hidden
370
+ text-overflow: ellipsis
371
+ white-space: nowrap
372
+
373
+ &__button
374
+ color: var(--d-code-example-muted)
375
+ flex: 0 0 auto
376
+
377
+ &__source
378
+ border-top: 1px solid var(--d-code-example-border)
379
+
380
+ .source-code
381
+ box-shadow: none
382
+ margin: 0
383
+ max-width: 100%
384
+
385
+ .source-code-frame
386
+ border: 0
387
+ border-radius: 0
388
+
389
+ &__preview
390
+ background: var(--d-code-example-preview-bg)
391
+ min-height: 96px
392
+ min-width: 0
393
+ overflow: hidden
394
+ position: relative
395
+
396
+ &--scrollable
397
+ overflow-y: auto
398
+
399
+ &--overflow
400
+ overflow: auto
401
+
402
+ &__component
403
+ display: block
404
+ min-width: 0
405
+
406
+ &__fallback
407
+ align-items: center
408
+ color: var(--d-code-example-muted)
409
+ display: flex
410
+ gap: 8px
411
+ min-height: 96px
412
+ padding: 18px
413
+
414
+ &__caption
415
+ border-top: 1px solid var(--d-code-example-border)
416
+ color: var(--d-code-example-caption)
417
+ font-size: 14px
418
+ line-height: 1.55
419
+ padding: 10px 14px 12px
420
+
421
+ p
422
+ margin: 0
423
+ </style>
@@ -59,6 +59,7 @@ body.body--dark
59
59
  .q-item
60
60
  min-height: 0
61
61
  padding: 0
62
+ height: 35px
62
63
 
63
64
  .q-item__section--side
64
65
  padding-left: 0.55rem
@@ -2,13 +2,7 @@
2
2
  import { ref, computed, watch } from 'vue'
3
3
  import { useQuasar } from 'quasar'
4
4
  import { useStore } from 'vuex'
5
- import Prism from 'prismjs'
6
- // @ Load Prism languages
7
- import 'prismjs/components/prism-markup-templating' // dependency for prism-php extension
8
- // PHP
9
- import 'prismjs/components/prism-php'
10
- // Bash
11
- import 'prismjs/components/prism-bash'
5
+ import Prism from './code-block-highlighting'
12
6
  import { looksLikeFileName, resolveFileIconUrl } from '../composables/useFileIcon'
13
7
 
14
8
  defineOptions({
@@ -11,6 +11,10 @@ defineProps({
11
11
  id: {
12
12
  type: Number,
13
13
  required: true
14
+ },
15
+ renderPrimaryHeading: {
16
+ type: Boolean,
17
+ default: false
14
18
  }
15
19
  })
16
20
 
@@ -32,6 +36,7 @@ const tokenized = computed(() => {
32
36
  <section>
33
37
  <d-page-tokens
34
38
  :id="id"
39
+ :render-primary-heading="renderPrimaryHeading"
35
40
  :tokens="tokenized"
36
41
  />
37
42
  </section>
@@ -8,6 +8,10 @@ defineProps({
8
8
  type: Number,
9
9
  default: 0
10
10
  },
11
+ renderPrimaryHeading: {
12
+ type: Boolean,
13
+ default: false
14
+ },
11
15
  tokens: {
12
16
  type: Array,
13
17
  default: () => []
@@ -30,12 +34,18 @@ import DBlockQuickLinks from './DBlockQuickLinks.vue'
30
34
  import DBlockTimeline from './DBlockTimeline.vue'
31
35
  import DBlockExpandable from './DBlockExpandable.vue'
32
36
  import DBlockStepper from './DBlockStepper.vue'
37
+ import DBlockCodeExample from './DBlockCodeExample.vue'
33
38
  </script>
34
39
 
35
40
  <template>
36
41
  <template v-for="(token, index) in tokens" :key="`${token.tag}-${index}`">
42
+ <h1
43
+ v-if="token.tag === 'h1' && renderPrimaryHeading"
44
+ :id="token.anchorId"
45
+ v-html="token.content"
46
+ ></h1>
37
47
  <d-h2
38
- v-if="token.tag === 'h2'"
48
+ v-else-if="token.tag === 'h2'"
39
49
  :id="token.anchorId"
40
50
  :value="token.content"
41
51
  />
@@ -126,6 +136,19 @@ import DBlockStepper from './DBlockStepper.vue'
126
136
  :tabs="token.tabs"
127
137
  />
128
138
 
139
+ <d-block-code-example
140
+ v-else-if="token.tag === 'code-example'"
141
+ :index="id + token.codeIndex"
142
+ :src="token.src"
143
+ :title="token.title"
144
+ :caption="token.caption"
145
+ :expanded="token.expanded"
146
+ :codepen="token.codepen"
147
+ :scrollable="token.scrollable"
148
+ :overflow="token.overflow"
149
+ :height="token.height"
150
+ />
151
+
129
152
  <d-block-mermaid-diagram
130
153
  v-else-if="token.tag === 'mermaid'"
131
154
  :content="token.content"
@@ -1,13 +1,17 @@
1
1
  <script setup>
2
2
  import { computed } from 'vue'
3
3
  import { useRoute } from 'vue-router'
4
+ import { useStore } from 'vuex'
5
+ import { homePageSourceMode } from 'virtual:docsector-homepage-override'
4
6
  // components
5
7
  import DPage from "./DPage.vue";
6
8
  import DPageBar from "./DPageBar.vue";
7
9
  import DH1 from "./DH1.vue";
8
10
  import DPageSection from "./DPageSection.vue";
11
+ import { usesRemoteReadmeHomeContent } from '../home-page-mode'
9
12
 
10
13
  const route = useRoute()
14
+ const store = useStore()
11
15
 
12
16
  const id = computed(() => {
13
17
  const path = route.path
@@ -19,6 +23,13 @@ const id = computed(() => {
19
23
 
20
24
  return hash >>> 0
21
25
  })
26
+
27
+ const usesRemoteReadmeHome = computed(() => {
28
+ return usesRemoteReadmeHomeContent({
29
+ pageBase: store.state.page.base,
30
+ homePageSourceMode
31
+ })
32
+ })
22
33
  </script>
23
34
 
24
35
  <template>
@@ -26,11 +37,12 @@ const id = computed(() => {
26
37
  <header>
27
38
  <d-page-bar />
28
39
  <hr />
29
- <d-h1 :id="0" />
40
+ <d-h1 v-if="!usesRemoteReadmeHome" :id="0" />
41
+ <span v-else id="0" aria-hidden="true"></span>
30
42
  </header>
31
43
 
32
44
  <main>
33
- <d-page-section :id="id" />
45
+ <d-page-section :id="id" :render-primary-heading="usesRemoteReadmeHome" />
34
46
  </main>
35
47
  </d-page>
36
48
  </template>
@@ -0,0 +1,16 @@
1
+ import Prism from 'prismjs'
2
+
3
+ import 'prismjs/components/prism-markup'
4
+ import 'prismjs/components/prism-markup-templating'
5
+ import 'prismjs/components/prism-javascript'
6
+ import 'prismjs/components/prism-css'
7
+ import 'prismjs/components/prism-php'
8
+ import 'prismjs/components/prism-bash'
9
+
10
+ if (!Prism.languages.vue && Prism.languages.markup?.tag?.addInlined) {
11
+ Prism.languages.markup.tag.addInlined('script', 'javascript')
12
+ Prism.languages.markup.tag.addInlined('style', 'css')
13
+ Prism.languages.vue = Prism.languages.markup
14
+ }
15
+
16
+ export default Prism