@docsector/docsector-reader 4.0.1 → 4.2.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 +19 -0
- package/bin/docsector.js +1 -1
- package/package.json +1 -1
- package/public/api/manual/http-client.json +91 -0
- package/public/quasar-api/QSeparator.json +39 -0
- package/src/components/DBlockApi.vue +634 -0
- package/src/components/DBlockApiEntry.js +623 -0
- package/src/components/DBlockCodeExample.vue +445 -0
- package/src/components/DBlockSourceCode.vue +3 -11
- package/src/components/DMenu.vue +70 -25
- package/src/components/DPageTokens.vue +22 -0
- package/src/components/api-block-model.js +326 -0
- package/src/components/code-block-highlighting.js +16 -0
- package/src/components/code-example-source.js +363 -0
- package/src/components/page-section-tokens.js +141 -1
- package/src/components/source-code-lines.js +17 -0
- package/src/examples/manual/code-examples/BasicCounter.vue +63 -0
- package/src/examples/manual/code-examples/InlineNotice.vue +60 -0
- package/src/pages/manual/content/blocks/api-reference.overview.en-US.md +40 -0
- package/src/pages/manual/content/blocks/api-reference.overview.pt-BR.md +40 -0
- package/src/pages/manual/content/blocks/api-reference.showcase.en-US.md +33 -0
- package/src/pages/manual/content/blocks/api-reference.showcase.pt-BR.md +33 -0
- package/src/pages/manual/content/blocks/code-examples.overview.en-US.md +56 -0
- package/src/pages/manual/content/blocks/code-examples.overview.pt-BR.md +56 -0
- package/src/pages/manual/content/blocks/code-examples.showcase.en-US.md +38 -0
- package/src/pages/manual/content/blocks/code-examples.showcase.pt-BR.md +38 -0
- package/src/pages/manual.index.js +56 -0
- package/src/quasar.factory.js +77 -0
- package/src/store/Page.js +26 -2
|
@@ -20,6 +20,8 @@ const STEPPER_MARKER_PREFIX = '@@DOCSECTOR_STEPPER_'
|
|
|
20
20
|
const EXPANDABLE_MARKER_PREFIX = '@@DOCSECTOR_EXPANDABLE_'
|
|
21
21
|
const FILE_MARKER_PREFIX = '@@DOCSECTOR_FILE_'
|
|
22
22
|
const EMBEDDED_URL_MARKER_PREFIX = '@@DOCSECTOR_EMBEDDED_URL_'
|
|
23
|
+
const CODE_EXAMPLE_MARKER_PREFIX = '@@DOCSECTOR_CODE_EXAMPLE_'
|
|
24
|
+
const API_BLOCK_MARKER_PREFIX = '@@DOCSECTOR_API_BLOCK_'
|
|
23
25
|
const CODE_SEGMENT_MARKER_PREFIX = '@@DOCSECTOR_CODE_SEGMENT_'
|
|
24
26
|
const MATH_KATEX_OPTIONS = {
|
|
25
27
|
throwOnError: false,
|
|
@@ -246,6 +248,24 @@ const parseExpandableOpenState = (raw = '') => {
|
|
|
246
248
|
return ['1', 'true', 'yes', 'on'].includes(String(raw).trim().toLowerCase())
|
|
247
249
|
}
|
|
248
250
|
|
|
251
|
+
const parseBooleanAttribute = (raw, fallback = false) => {
|
|
252
|
+
if (raw === undefined || raw === null || raw === '') {
|
|
253
|
+
return fallback
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
const normalized = String(raw).trim().toLowerCase()
|
|
257
|
+
|
|
258
|
+
if (['1', 'true', 'yes', 'on'].includes(normalized)) {
|
|
259
|
+
return true
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
if (['0', 'false', 'no', 'off'].includes(normalized)) {
|
|
263
|
+
return false
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
return fallback
|
|
267
|
+
}
|
|
268
|
+
|
|
249
269
|
const parseTimelineTags = (raw = '') => {
|
|
250
270
|
return decodeHtmlEntities(raw)
|
|
251
271
|
.split(',')
|
|
@@ -517,6 +537,83 @@ const extractEmbeddedUrlBlocks = (source = '') => {
|
|
|
517
537
|
}
|
|
518
538
|
}
|
|
519
539
|
|
|
540
|
+
const extractCodeExampleBlocks = (source = '') => {
|
|
541
|
+
const map = new Map()
|
|
542
|
+
let index = 0
|
|
543
|
+
|
|
544
|
+
const replaceBlock = (match, rawAttrs, rawCaption = '') => {
|
|
545
|
+
const attrs = parseCustomTagAttributes(rawAttrs)
|
|
546
|
+
const src = decodeHtmlEntities(attrs.src || attrs.file || '').trim()
|
|
547
|
+
|
|
548
|
+
if (!src) {
|
|
549
|
+
return match
|
|
550
|
+
}
|
|
551
|
+
|
|
552
|
+
const marker = `${CODE_EXAMPLE_MARKER_PREFIX}${index}@@`
|
|
553
|
+
index++
|
|
554
|
+
|
|
555
|
+
map.set(marker, {
|
|
556
|
+
src,
|
|
557
|
+
title: decodeHtmlEntities(attrs.title || '').trim(),
|
|
558
|
+
expanded: parseBooleanAttribute(attrs.expanded, false),
|
|
559
|
+
codepen: parseBooleanAttribute(attrs.codepen, true),
|
|
560
|
+
scrollable: parseBooleanAttribute(attrs.scrollable, false),
|
|
561
|
+
overflow: parseBooleanAttribute(attrs.overflow, false),
|
|
562
|
+
height: decodeHtmlEntities(attrs.height || '').trim(),
|
|
563
|
+
caption: String(rawCaption).trim()
|
|
564
|
+
})
|
|
565
|
+
|
|
566
|
+
return `\n${marker}\n`
|
|
567
|
+
}
|
|
568
|
+
|
|
569
|
+
const replacedSelfClosing = String(source).replace(/<d-block-code-example\b([^>]*)\/\s*>/gi, (match, rawAttrs) => {
|
|
570
|
+
return replaceBlock(match, rawAttrs)
|
|
571
|
+
})
|
|
572
|
+
const replaced = replacedSelfClosing.replace(/<d-block-code-example\b([^>]*)>([\s\S]*?)<\/d-block-code-example>/gi, replaceBlock)
|
|
573
|
+
|
|
574
|
+
return {
|
|
575
|
+
source: replaced,
|
|
576
|
+
codeExampleMap: map
|
|
577
|
+
}
|
|
578
|
+
}
|
|
579
|
+
|
|
580
|
+
const extractApiBlocks = (source = '') => {
|
|
581
|
+
const map = new Map()
|
|
582
|
+
let index = 0
|
|
583
|
+
|
|
584
|
+
const replaceBlock = (match, rawAttrs) => {
|
|
585
|
+
const attrs = parseCustomTagAttributes(rawAttrs)
|
|
586
|
+
const src = decodeHtmlEntities(attrs.src || '').trim()
|
|
587
|
+
|
|
588
|
+
if (!src) {
|
|
589
|
+
return match
|
|
590
|
+
}
|
|
591
|
+
|
|
592
|
+
const marker = `${API_BLOCK_MARKER_PREFIX}${index}@@`
|
|
593
|
+
index++
|
|
594
|
+
|
|
595
|
+
map.set(marker, {
|
|
596
|
+
src,
|
|
597
|
+
title: decodeHtmlEntities(attrs.title || '').trim(),
|
|
598
|
+
pageLink: parseBooleanAttribute(attrs['page-link'], false)
|
|
599
|
+
})
|
|
600
|
+
|
|
601
|
+
return `\n${marker}\n`
|
|
602
|
+
}
|
|
603
|
+
|
|
604
|
+
const replacedSelfClosing = String(source).replace(/<d-block-api\b([^>]*)\/\s*>/gi, (match, rawAttrs) => {
|
|
605
|
+
return replaceBlock(match, rawAttrs)
|
|
606
|
+
})
|
|
607
|
+
const replaced = replacedSelfClosing.replace(/<d-block-api\b([^>]*)>([\s\S]*?)<\/d-block-api>/gi, (match, rawAttrs) => {
|
|
608
|
+
return replaceBlock(match, rawAttrs)
|
|
609
|
+
})
|
|
610
|
+
|
|
611
|
+
return {
|
|
612
|
+
source: replaced,
|
|
613
|
+
apiBlockMap: map
|
|
614
|
+
}
|
|
615
|
+
}
|
|
616
|
+
|
|
520
617
|
const parseFenceAttributes = (raw = '') => {
|
|
521
618
|
const parsed = {}
|
|
522
619
|
const pattern = /([\w-]+)\s*=\s*(?:"([^"]*)"|'([^']*)'|([^\s;]+))/g
|
|
@@ -871,6 +968,8 @@ export const tokenizePageSectionSource = (source = '', options = {}) => {
|
|
|
871
968
|
const { source: sourceWithQuickLinks, quickLinksMap } = extractQuickLinksBlocks(sourceWithCards)
|
|
872
969
|
const { source: sourceWithFiles, fileMap } = extractFileBlocks(sourceWithQuickLinks)
|
|
873
970
|
const { source: sourceWithEmbeddedUrls, embeddedUrlMap } = extractEmbeddedUrlBlocks(sourceWithFiles)
|
|
971
|
+
const { source: sourceWithCodeExamples, codeExampleMap } = extractCodeExampleBlocks(sourceWithEmbeddedUrls)
|
|
972
|
+
const { source: sourceWithApiBlocks, apiBlockMap } = extractApiBlocks(sourceWithCodeExamples)
|
|
874
973
|
|
|
875
974
|
fileMap.forEach((data, marker) => {
|
|
876
975
|
fileMap.set(marker, {
|
|
@@ -886,10 +985,17 @@ export const tokenizePageSectionSource = (source = '', options = {}) => {
|
|
|
886
985
|
})
|
|
887
986
|
})
|
|
888
987
|
|
|
988
|
+
codeExampleMap.forEach((data, marker) => {
|
|
989
|
+
codeExampleMap.set(marker, {
|
|
990
|
+
...data,
|
|
991
|
+
caption: restoreShieldedCodeSegments(data.caption, codeSegmentsMap)
|
|
992
|
+
})
|
|
993
|
+
})
|
|
994
|
+
|
|
889
995
|
const markdown = createMarkdownBlockParser()
|
|
890
996
|
const markdownInline = createMarkdownInlineParser()
|
|
891
997
|
const markdownEnv = {}
|
|
892
|
-
const parsed = markdown.parse(restoreShieldedCodeSegments(
|
|
998
|
+
const parsed = markdown.parse(restoreShieldedCodeSegments(sourceWithApiBlocks, codeSegmentsMap), markdownEnv)
|
|
893
999
|
const tokens = []
|
|
894
1000
|
|
|
895
1001
|
let level = 0
|
|
@@ -1146,6 +1252,40 @@ export const tokenizePageSectionSource = (source = '', options = {}) => {
|
|
|
1146
1252
|
break
|
|
1147
1253
|
}
|
|
1148
1254
|
|
|
1255
|
+
if (codeExampleMap.has(element.content.trim())) {
|
|
1256
|
+
const data = codeExampleMap.get(element.content.trim())
|
|
1257
|
+
|
|
1258
|
+
tokens.push({
|
|
1259
|
+
tag: 'code-example',
|
|
1260
|
+
map: element.map,
|
|
1261
|
+
codeIndex: parserState.codeIndex++,
|
|
1262
|
+
src: data.src,
|
|
1263
|
+
title: data.title,
|
|
1264
|
+
expanded: data.expanded,
|
|
1265
|
+
codepen: data.codepen,
|
|
1266
|
+
scrollable: data.scrollable,
|
|
1267
|
+
overflow: data.overflow,
|
|
1268
|
+
height: data.height,
|
|
1269
|
+
caption: data.caption !== ''
|
|
1270
|
+
? markdownInline.renderInline(data.caption, markdownEnv)
|
|
1271
|
+
: ''
|
|
1272
|
+
})
|
|
1273
|
+
break
|
|
1274
|
+
}
|
|
1275
|
+
|
|
1276
|
+
if (apiBlockMap.has(element.content.trim())) {
|
|
1277
|
+
const data = apiBlockMap.get(element.content.trim())
|
|
1278
|
+
|
|
1279
|
+
tokens.push({
|
|
1280
|
+
tag: 'api',
|
|
1281
|
+
map: element.map,
|
|
1282
|
+
src: data.src,
|
|
1283
|
+
title: data.title,
|
|
1284
|
+
pageLink: data.pageLink
|
|
1285
|
+
})
|
|
1286
|
+
break
|
|
1287
|
+
}
|
|
1288
|
+
|
|
1149
1289
|
if (tag === 'p') {
|
|
1150
1290
|
const imageToken = parseStandaloneImageToken(element.content)
|
|
1151
1291
|
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
const normalizeLineBreaks = (text = '') => String(text || '').replace(/\r\n/g, '\n')
|
|
2
|
+
|
|
3
|
+
export const countRenderedCodeLines = (text = '') => {
|
|
4
|
+
const normalized = normalizeLineBreaks(text)
|
|
5
|
+
|
|
6
|
+
if (normalized === '') {
|
|
7
|
+
return 0
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
const withoutTerminalBreak = normalized.replace(/\n$/, '')
|
|
11
|
+
|
|
12
|
+
if (withoutTerminalBreak === '') {
|
|
13
|
+
return 1
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
return withoutTerminalBreak.split('\n').length
|
|
17
|
+
}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div class="basic-counter-example q-pa-md">
|
|
3
|
+
<q-card class="basic-counter-example__card" flat bordered>
|
|
4
|
+
<q-card-section>
|
|
5
|
+
<div class="text-subtitle2 text-grey-7">Interactive preview</div>
|
|
6
|
+
<div class="basic-counter-example__value">{{ count }}</div>
|
|
7
|
+
<div class="text-body2 text-grey-7">{{ countLabel }}</div>
|
|
8
|
+
</q-card-section>
|
|
9
|
+
|
|
10
|
+
<q-separator></q-separator>
|
|
11
|
+
|
|
12
|
+
<q-card-actions align="right">
|
|
13
|
+
<q-btn flat color="primary" label="Reset" @click="reset"></q-btn>
|
|
14
|
+
<q-btn unelevated color="primary" label="Increment" @click="increment"></q-btn>
|
|
15
|
+
</q-card-actions>
|
|
16
|
+
</q-card>
|
|
17
|
+
</div>
|
|
18
|
+
</template>
|
|
19
|
+
|
|
20
|
+
<script>
|
|
21
|
+
import { computed, ref } from 'vue'
|
|
22
|
+
|
|
23
|
+
export default {
|
|
24
|
+
setup () {
|
|
25
|
+
const count = ref(0)
|
|
26
|
+
const countLabel = computed(() => count.value === 1 ? 'click recorded' : 'clicks recorded')
|
|
27
|
+
|
|
28
|
+
function increment () {
|
|
29
|
+
count.value++
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function reset () {
|
|
33
|
+
count.value = 0
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
return {
|
|
37
|
+
count,
|
|
38
|
+
countLabel,
|
|
39
|
+
increment,
|
|
40
|
+
reset
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
</script>
|
|
45
|
+
|
|
46
|
+
<style scoped>
|
|
47
|
+
.basic-counter-example {
|
|
48
|
+
display: flex;
|
|
49
|
+
justify-content: center;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
.basic-counter-example__card {
|
|
53
|
+
max-width: 360px;
|
|
54
|
+
width: 100%;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
.basic-counter-example__value {
|
|
58
|
+
font-size: 48px;
|
|
59
|
+
font-weight: 700;
|
|
60
|
+
line-height: 1;
|
|
61
|
+
margin: 12px 0 6px;
|
|
62
|
+
}
|
|
63
|
+
</style>
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div class="inline-notice-example q-pa-md">
|
|
3
|
+
<q-banner rounded class="inline-notice-example__banner">
|
|
4
|
+
<template #avatar>
|
|
5
|
+
<q-icon name="tips_and_updates" color="primary"></q-icon>
|
|
6
|
+
</template>
|
|
7
|
+
|
|
8
|
+
<div class="text-weight-medium">{{ title }}</div>
|
|
9
|
+
<div class="text-body2">{{ message }}</div>
|
|
10
|
+
|
|
11
|
+
<template #action>
|
|
12
|
+
<q-btn flat color="primary" label="Dismiss" @click="dismiss"></q-btn>
|
|
13
|
+
</template>
|
|
14
|
+
</q-banner>
|
|
15
|
+
|
|
16
|
+
<div v-if="dismissed" class="inline-notice-example__status text-caption">
|
|
17
|
+
The notice was dismissed.
|
|
18
|
+
</div>
|
|
19
|
+
</div>
|
|
20
|
+
</template>
|
|
21
|
+
|
|
22
|
+
<script>
|
|
23
|
+
import { ref } from 'vue'
|
|
24
|
+
|
|
25
|
+
export default {
|
|
26
|
+
setup () {
|
|
27
|
+
const title = 'Documentation tip'
|
|
28
|
+
const message = 'Use expanded examples when the source code is part of the lesson.'
|
|
29
|
+
const dismissed = ref(false)
|
|
30
|
+
|
|
31
|
+
function dismiss () {
|
|
32
|
+
dismissed.value = true
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
return {
|
|
36
|
+
dismissed,
|
|
37
|
+
dismiss,
|
|
38
|
+
message,
|
|
39
|
+
title
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
</script>
|
|
44
|
+
|
|
45
|
+
<style scoped>
|
|
46
|
+
.inline-notice-example {
|
|
47
|
+
display: grid;
|
|
48
|
+
gap: 10px;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
.inline-notice-example__banner {
|
|
52
|
+
background: rgba(25, 118, 210, 0.08);
|
|
53
|
+
border: 1px solid rgba(25, 118, 210, 0.18);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
.inline-notice-example__status {
|
|
57
|
+
color: #607d68;
|
|
58
|
+
padding-left: 8px;
|
|
59
|
+
}
|
|
60
|
+
</style>
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
## Overview
|
|
2
|
+
|
|
3
|
+
API Reference blocks render a JSON document that follows the existing Quasar API schema directly inside Markdown.
|
|
4
|
+
|
|
5
|
+
This keeps the viewer compatible with Quasar-style API files while still allowing non-Vue APIs to reuse the same section model for props, methods, events, values, arguments, and config shapes.
|
|
6
|
+
|
|
7
|
+
The block is authored with the custom Markdown element `<d-block-api>`.
|
|
8
|
+
|
|
9
|
+
## Markdown Syntax
|
|
10
|
+
|
|
11
|
+
```html
|
|
12
|
+
<d-block-api src="/quasar-api/QSeparator.json" />
|
|
13
|
+
|
|
14
|
+
<d-block-api
|
|
15
|
+
src="/api/manual/http-client.json"
|
|
16
|
+
title="HTTP Client API"
|
|
17
|
+
page-link="true"
|
|
18
|
+
/>
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## Attributes
|
|
22
|
+
|
|
23
|
+
| Attribute | Purpose |
|
|
24
|
+
|-----------|---------|
|
|
25
|
+
| `src` | Same-origin JSON path to fetch in the browser |
|
|
26
|
+
| `title` | Optional header override shown above the API card |
|
|
27
|
+
| `page-link` | Shows the Docs button when the JSON has `meta.docsUrl` |
|
|
28
|
+
|
|
29
|
+
## JSON Source Model
|
|
30
|
+
|
|
31
|
+
- The first implementation follows the same delivery model as Quasar Docs: the JSON file is served as a public asset and fetched on demand.
|
|
32
|
+
- No Docsector-specific schema is required. If your file already follows the Quasar API structure, it can be rendered as-is.
|
|
33
|
+
- Non-Vue APIs can still use the same shape by filling the sections they need, such as `props`, `methods`, `events`, `value`, `arg`, or `quasarConfOptions`.
|
|
34
|
+
|
|
35
|
+
## Notes
|
|
36
|
+
|
|
37
|
+
- `props` are grouped into subtabs when more than one `category` is present.
|
|
38
|
+
- Entries marked with `internal: true` are hidden from the rendered block.
|
|
39
|
+
- The current version expects same-origin JSON assets so the browser can fetch them without CORS workarounds.
|
|
40
|
+
- If the JSON exposes `meta.docsUrl`, `page-link="true"` can surface a Docs button without changing the schema.
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
## Visão geral
|
|
2
|
+
|
|
3
|
+
Os blocos de Referência de API renderizam um documento JSON que segue o schema de API já existente do Quasar diretamente dentro do Markdown.
|
|
4
|
+
|
|
5
|
+
Isso mantém o viewer compatível com arquivos de API no estilo do Quasar e ainda permite que APIs não-Vue reutilizem o mesmo modelo de seções para props, methods, events, values, arguments e estruturas de configuração.
|
|
6
|
+
|
|
7
|
+
O bloco é escrito com o elemento Markdown customizado `<d-block-api>`.
|
|
8
|
+
|
|
9
|
+
## Sintaxe Markdown
|
|
10
|
+
|
|
11
|
+
```html
|
|
12
|
+
<d-block-api src="/quasar-api/QSeparator.json" />
|
|
13
|
+
|
|
14
|
+
<d-block-api
|
|
15
|
+
src="/api/manual/http-client.json"
|
|
16
|
+
title="HTTP Client API"
|
|
17
|
+
page-link="true"
|
|
18
|
+
/>
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## Atributos
|
|
22
|
+
|
|
23
|
+
| Atributo | Finalidade |
|
|
24
|
+
|----------|------------|
|
|
25
|
+
| `src` | Caminho same-origin do JSON a ser buscado no navegador |
|
|
26
|
+
| `title` | Sobrescreve opcionalmente o título exibido acima do card |
|
|
27
|
+
| `page-link` | Exibe o botão Docs quando o JSON possui `meta.docsUrl` |
|
|
28
|
+
|
|
29
|
+
## Modelo da Fonte JSON
|
|
30
|
+
|
|
31
|
+
- A primeira implementação segue o mesmo modelo de entrega do Quasar Docs: o arquivo JSON é servido como asset público e carregado sob demanda.
|
|
32
|
+
- Nenhum schema específico do Docsector é exigido. Se o arquivo já seguir a estrutura de API do Quasar, ele pode ser renderizado sem alterações.
|
|
33
|
+
- APIs não-Vue ainda podem usar a mesma forma preenchendo apenas as seções necessárias, como `props`, `methods`, `events`, `value`, `arg` ou `quasarConfOptions`.
|
|
34
|
+
|
|
35
|
+
## Notas
|
|
36
|
+
|
|
37
|
+
- `props` são agrupadas em subtabs quando mais de uma `category` está presente.
|
|
38
|
+
- Entradas marcadas com `internal: true` são ocultadas do bloco renderizado.
|
|
39
|
+
- A versão atual espera assets JSON same-origin para que o navegador faça o fetch sem workarounds de CORS.
|
|
40
|
+
- Se o JSON expuser `meta.docsUrl`, `page-link="true"` pode exibir um botão Docs sem alterar o schema.
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
## Showcase
|
|
2
|
+
|
|
3
|
+
### Quasar JSON Without Refactoring
|
|
4
|
+
|
|
5
|
+
This example renders a real Quasar API JSON file copied into `public/quasar-api/`.
|
|
6
|
+
|
|
7
|
+
<d-block-api src="/quasar-api/QSeparator.json" />
|
|
8
|
+
|
|
9
|
+
### Generic SDK JSON With the Same Schema
|
|
10
|
+
|
|
11
|
+
This example uses the same section model for a non-Vue HTTP client and also enables the optional Docs button.
|
|
12
|
+
|
|
13
|
+
<d-block-api src="/api/manual/http-client.json" title="HTTP Client API" page-link="true" />
|
|
14
|
+
|
|
15
|
+
## Authoring Syntax
|
|
16
|
+
|
|
17
|
+
```html
|
|
18
|
+
<d-block-api src="/quasar-api/QSeparator.json" />
|
|
19
|
+
|
|
20
|
+
<d-block-api
|
|
21
|
+
src="/api/manual/http-client.json"
|
|
22
|
+
title="HTTP Client API"
|
|
23
|
+
page-link="true"
|
|
24
|
+
/>
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
## Features Visible Above
|
|
28
|
+
|
|
29
|
+
- **Quasar JSON compatibility** with a real file served from `public/quasar-api/`
|
|
30
|
+
- **Generic API support** without introducing a new schema
|
|
31
|
+
- **Local filter** across names and descriptions inside the loaded API sections
|
|
32
|
+
- **Grouped props subtabs** when multiple categories exist in the JSON
|
|
33
|
+
- **Optional Docs link** when `meta.docsUrl` is present and `page-link="true"` is used
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
## Showcase
|
|
2
|
+
|
|
3
|
+
### JSON do Quasar Sem Refatoração
|
|
4
|
+
|
|
5
|
+
Este exemplo renderiza um arquivo JSON de API real do Quasar copiado para `public/quasar-api/`.
|
|
6
|
+
|
|
7
|
+
<d-block-api src="/quasar-api/QSeparator.json" />
|
|
8
|
+
|
|
9
|
+
### JSON de SDK Genérico Com o Mesmo Schema
|
|
10
|
+
|
|
11
|
+
Este exemplo usa o mesmo modelo de seções para um cliente HTTP não-Vue e também ativa o botão opcional de Docs.
|
|
12
|
+
|
|
13
|
+
<d-block-api src="/api/manual/http-client.json" title="HTTP Client API" page-link="true" />
|
|
14
|
+
|
|
15
|
+
## Sintaxe de Autoria
|
|
16
|
+
|
|
17
|
+
```html
|
|
18
|
+
<d-block-api src="/quasar-api/QSeparator.json" />
|
|
19
|
+
|
|
20
|
+
<d-block-api
|
|
21
|
+
src="/api/manual/http-client.json"
|
|
22
|
+
title="HTTP Client API"
|
|
23
|
+
page-link="true"
|
|
24
|
+
/>
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
## Recursos Visíveis Acima
|
|
28
|
+
|
|
29
|
+
- **Compatibilidade com JSON do Quasar** usando um arquivo real servido de `public/quasar-api/`
|
|
30
|
+
- **Suporte a APIs genéricas** sem introduzir um novo schema
|
|
31
|
+
- **Filtro local** por nomes e descrições dentro das seções carregadas
|
|
32
|
+
- **Subtabs agrupadas em props** quando múltiplas categorias existem no JSON
|
|
33
|
+
- **Link opcional para Docs** quando `meta.docsUrl` está presente e `page-link="true"` é usado
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
## Overview
|
|
2
|
+
|
|
3
|
+
Code example blocks render project Vue SFCs as live previews inside Markdown pages.
|
|
4
|
+
|
|
5
|
+
They are useful when documentation needs to show the real behavior of a component and still let readers inspect the exact source behind the preview.
|
|
6
|
+
|
|
7
|
+
The block is authored with the custom Markdown element `<d-block-code-example>`.
|
|
8
|
+
|
|
9
|
+
## Example Files
|
|
10
|
+
|
|
11
|
+
Place example components under `src/examples/**/*.vue` in the project using Docsector.
|
|
12
|
+
|
|
13
|
+
Docsector discovers those files at build time through Vite. The `src` value is normalized to kebab-case, so this block:
|
|
14
|
+
|
|
15
|
+
```html
|
|
16
|
+
<d-block-code-example src="manual/code-examples/basic-counter" title="Basic counter" />
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
resolves this file:
|
|
20
|
+
|
|
21
|
+
```text
|
|
22
|
+
src/examples/manual/code-examples/BasicCounter.vue
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
You can also use `file` instead of `src` when migrating examples from Quasar Docs patterns.
|
|
26
|
+
|
|
27
|
+
## Attributes
|
|
28
|
+
|
|
29
|
+
| Attribute | Purpose |
|
|
30
|
+
|-----------|---------|
|
|
31
|
+
| `src` | Example id under `src/examples/**/*.vue` |
|
|
32
|
+
| `file` | Alias for `src` |
|
|
33
|
+
| `title` | Header title shown above the preview |
|
|
34
|
+
| `expanded` | Opens the source panel by default when set to `true` |
|
|
35
|
+
| `codepen` | Shows the CodePen action unless set to `false` |
|
|
36
|
+
| `scrollable` | Gives the preview a fixed scrollable height |
|
|
37
|
+
| `overflow` | Allows both horizontal and vertical overflow in the preview |
|
|
38
|
+
| `height` | Sets a custom preview height, such as `360` or `420px` |
|
|
39
|
+
|
|
40
|
+
## Source Panel
|
|
41
|
+
|
|
42
|
+
The source button opens the Vue SFC split into Template, Script, Style, and All tabs when those sections are present.
|
|
43
|
+
|
|
44
|
+
The source panel reuses the standard Docsector code block renderer, so readers get syntax highlighting, copy support, and the same dark/light treatment as regular code blocks.
|
|
45
|
+
|
|
46
|
+
## GitHub Source Link
|
|
47
|
+
|
|
48
|
+
The GitHub button opens the example SFC in the project repository when Docsector can derive a repository URL from `github.editBaseUrl` or `links.github` in `docsector.config.js`.
|
|
49
|
+
|
|
50
|
+
## CodePen Export
|
|
51
|
+
|
|
52
|
+
The CodePen button is available when the source can be transformed safely for a browser-only demo.
|
|
53
|
+
|
|
54
|
+
The first implementation 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. Examples that use `<script setup>`, TypeScript scripts, or local imports still render in Docsector, but the CodePen action is disabled.
|
|
55
|
+
|
|
56
|
+
Set `codepen="false"` when an example is intentionally not meant to be exported.
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
## Visão geral
|
|
2
|
+
|
|
3
|
+
Blocos de exemplos de código renderizam SFCs Vue do projeto como previews ao vivo dentro das páginas Markdown.
|
|
4
|
+
|
|
5
|
+
Eles são úteis quando a documentação precisa mostrar o comportamento real de um componente e ainda permitir que leitores inspecionem o código fonte exato por trás do preview.
|
|
6
|
+
|
|
7
|
+
O bloco é escrito com o elemento Markdown customizado `<d-block-code-example>`.
|
|
8
|
+
|
|
9
|
+
## Arquivos de exemplo
|
|
10
|
+
|
|
11
|
+
Coloque os componentes de exemplo em `src/examples/**/*.vue` no projeto que usa o Docsector.
|
|
12
|
+
|
|
13
|
+
O Docsector descobre esses arquivos durante o build com Vite. O valor de `src` é normalizado para kebab-case, então este bloco:
|
|
14
|
+
|
|
15
|
+
```html
|
|
16
|
+
<d-block-code-example src="manual/code-examples/basic-counter" title="Basic counter" />
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
resolve este arquivo:
|
|
20
|
+
|
|
21
|
+
```text
|
|
22
|
+
src/examples/manual/code-examples/BasicCounter.vue
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
Também é possível usar `file` no lugar de `src` ao migrar exemplos inspirados nos padrões do Quasar Docs.
|
|
26
|
+
|
|
27
|
+
## Atributos
|
|
28
|
+
|
|
29
|
+
| Atributo | Finalidade |
|
|
30
|
+
|----------|------------|
|
|
31
|
+
| `src` | Id do exemplo dentro de `src/examples/**/*.vue` |
|
|
32
|
+
| `file` | Alias de `src` |
|
|
33
|
+
| `title` | Título exibido acima do preview |
|
|
34
|
+
| `expanded` | Abre o painel de fonte por padrão quando definido como `true` |
|
|
35
|
+
| `codepen` | Mostra a ação do CodePen, exceto quando definido como `false` |
|
|
36
|
+
| `scrollable` | Dá ao preview uma altura fixa com rolagem |
|
|
37
|
+
| `overflow` | Permite overflow horizontal e vertical no preview |
|
|
38
|
+
| `height` | Define uma altura customizada para o preview, como `360` ou `420px` |
|
|
39
|
+
|
|
40
|
+
## Painel de fonte
|
|
41
|
+
|
|
42
|
+
O botão de fonte abre o SFC Vue dividido em abas Template, Script, Style e All quando essas seções existem.
|
|
43
|
+
|
|
44
|
+
O painel reutiliza o renderizador padrão de blocos de código do Docsector, então leitores recebem syntax highlighting, suporte a cópia e o mesmo tratamento visual em temas claro e escuro.
|
|
45
|
+
|
|
46
|
+
## Link de fonte no GitHub
|
|
47
|
+
|
|
48
|
+
O botão do GitHub abre o SFC do exemplo no repositório do projeto quando o Docsector consegue derivar a URL a partir de `github.editBaseUrl` ou `links.github` em `docsector.config.js`.
|
|
49
|
+
|
|
50
|
+
## Exportação para CodePen
|
|
51
|
+
|
|
52
|
+
O botão do CodePen fica disponível quando o código pode ser transformado com segurança para uma demo somente no navegador.
|
|
53
|
+
|
|
54
|
+
A primeira implementação suporta SFCs Vue simples com template, style opcional e script Options API com `export default`. Imports nomeados de `vue` e `quasar` são convertidos para globais do navegador. Exemplos que usam `<script setup>`, scripts TypeScript ou imports locais continuam renderizando no Docsector, mas a ação do CodePen fica desativada.
|
|
55
|
+
|
|
56
|
+
Use `codepen="false"` quando um exemplo intencionalmente não deve ser exportado.
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
## Showcase
|
|
2
|
+
|
|
3
|
+
### Basic Counter
|
|
4
|
+
|
|
5
|
+
This example is rendered from a real Vue SFC under `src/examples/manual/code-examples/BasicCounter.vue`.
|
|
6
|
+
|
|
7
|
+
<d-block-code-example src="manual/code-examples/basic-counter" title="Basic counter">
|
|
8
|
+
Use the source button to inspect the SFC sections, or open the compatible demo in CodePen.
|
|
9
|
+
</d-block-code-example>
|
|
10
|
+
|
|
11
|
+
### Expanded Source by Default
|
|
12
|
+
|
|
13
|
+
Use `expanded="true"` when the source code is part of the lesson and should be visible as soon as the reader reaches the example.
|
|
14
|
+
|
|
15
|
+
<d-block-code-example src="manual/code-examples/inline-notice" title="Expanded source example" expanded="true">
|
|
16
|
+
This example intentionally starts with the source panel open.
|
|
17
|
+
</d-block-code-example>
|
|
18
|
+
|
|
19
|
+
## Authoring Syntax
|
|
20
|
+
|
|
21
|
+
```html
|
|
22
|
+
<d-block-code-example src="manual/code-examples/basic-counter" title="Basic counter">
|
|
23
|
+
Optional caption rendered as inline Markdown.
|
|
24
|
+
</d-block-code-example>
|
|
25
|
+
|
|
26
|
+
<d-block-code-example src="manual/code-examples/inline-notice" title="Expanded source example" expanded="true">
|
|
27
|
+
The source panel starts open.
|
|
28
|
+
</d-block-code-example>
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
## Features Visible Above
|
|
32
|
+
|
|
33
|
+
- **Live preview** rendered from the bundled Vue component
|
|
34
|
+
- **Source toggle** with Template, Script, Style, and All tabs
|
|
35
|
+
- **CodePen action** for compatible examples
|
|
36
|
+
- **GitHub action** pointing to the example SFC
|
|
37
|
+
- **Expanded source state** with `expanded="true"`
|
|
38
|
+
- **Inline Markdown caption** below the preview
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
## Showcase
|
|
2
|
+
|
|
3
|
+
### Contador básico
|
|
4
|
+
|
|
5
|
+
Este exemplo é renderizado a partir de um SFC Vue real em `src/examples/manual/code-examples/BasicCounter.vue`.
|
|
6
|
+
|
|
7
|
+
<d-block-code-example src="manual/code-examples/basic-counter" title="Basic counter">
|
|
8
|
+
Use o botão de fonte para inspecionar as seções do SFC, ou abra a demo compatível no CodePen.
|
|
9
|
+
</d-block-code-example>
|
|
10
|
+
|
|
11
|
+
### Fonte expandida por padrão
|
|
12
|
+
|
|
13
|
+
Use `expanded="true"` quando o código fonte faz parte da explicação e deve aparecer assim que o leitor chegar ao exemplo.
|
|
14
|
+
|
|
15
|
+
<d-block-code-example src="manual/code-examples/inline-notice" title="Expanded source example" expanded="true">
|
|
16
|
+
Este exemplo intencionalmente começa com o painel de fonte aberto.
|
|
17
|
+
</d-block-code-example>
|
|
18
|
+
|
|
19
|
+
## Sintaxe de autoria
|
|
20
|
+
|
|
21
|
+
```html
|
|
22
|
+
<d-block-code-example src="manual/code-examples/basic-counter" title="Basic counter">
|
|
23
|
+
Legenda opcional renderizada como Markdown inline.
|
|
24
|
+
</d-block-code-example>
|
|
25
|
+
|
|
26
|
+
<d-block-code-example src="manual/code-examples/inline-notice" title="Expanded source example" expanded="true">
|
|
27
|
+
O painel de fonte começa aberto.
|
|
28
|
+
</d-block-code-example>
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
## Recursos visíveis acima
|
|
32
|
+
|
|
33
|
+
- **Preview ao vivo** renderizado a partir do componente Vue empacotado
|
|
34
|
+
- **Alternância de fonte** com abas Template, Script, Style e All
|
|
35
|
+
- **Ação do CodePen** para exemplos compatíveis
|
|
36
|
+
- **Ação do GitHub** apontando para o SFC do exemplo
|
|
37
|
+
- **Estado de fonte expandida** com `expanded="true"`
|
|
38
|
+
- **Legenda em Markdown inline** abaixo do preview
|