@docsector/docsector-reader 3.5.0 → 3.6.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 +1 -0
- package/bin/docsector.js +1 -1
- package/package.json +1 -1
- package/public/images/cards/getting-started-cover.svg +60 -0
- package/public/images/cards/quick-links-cover.svg +71 -0
- package/src/components/DBlockCard.vue +223 -0
- package/src/components/DPageTokens.vue +7 -0
- package/src/components/page-section-tokens.js +63 -1
- package/src/pages/manual/content/blocks/cards.overview.en-US.md +32 -0
- package/src/pages/manual/content/blocks/cards.overview.pt-BR.md +32 -0
- package/src/pages/manual/content/blocks/cards.showcase.en-US.md +39 -0
- package/src/pages/manual/content/blocks/cards.showcase.pt-BR.md +39 -0
- package/src/pages/manual.index.js +28 -0
package/README.md
CHANGED
|
@@ -75,6 +75,7 @@ Transform Markdown content into beautiful, navigable documentation sites — wit
|
|
|
75
75
|
- 📎 **File Attachment Blocks** — Use `<d-file src="/files/...">...</d-file>` in Markdown to render downloadable file cards with automatic local size detection and support for external URLs
|
|
76
76
|
- 🌐 **Embedded URL Blocks** — Use `<d-embedded-url url="https://...">...</d-embedded-url>` to render curated embeds for YouTube, Vimeo, Spotify, and CodePen with a safe link-card fallback for unsupported URLs
|
|
77
77
|
- 🧭 **Quick Links Custom Element** — Use `<d-quick-links>` and `<d-quick-link>` in Markdown to render rich home navigation cards
|
|
78
|
+
- 🗂️ **Cards Custom Element** — Use `<d-block-cards>` and `<d-block-card>` in Markdown to render linked content cards with optional cover images
|
|
78
79
|
- 🗂️ **API Catalog Well-Known** — Auto-generates `/.well-known/api-catalog` as Linkset JSON for machine-readable API discovery
|
|
79
80
|
- 🗃️ **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
81
|
- 🏷️ **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 }`
|
package/bin/docsector.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@docsector/docsector-reader",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.6.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,60 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1280 720" role="img" aria-labelledby="title desc">
|
|
2
|
+
<title id="title">Getting started cover</title>
|
|
3
|
+
<desc id="desc">Abstract cover with warm gradients and onboarding steps.</desc>
|
|
4
|
+
<defs>
|
|
5
|
+
<linearGradient id="bg" x1="0" y1="0" x2="1" y2="1">
|
|
6
|
+
<stop offset="0%" stop-color="#12141c"/>
|
|
7
|
+
<stop offset="48%" stop-color="#1b2230"/>
|
|
8
|
+
<stop offset="100%" stop-color="#27384d"/>
|
|
9
|
+
</linearGradient>
|
|
10
|
+
<linearGradient id="panel" x1="0" y1="0" x2="1" y2="1">
|
|
11
|
+
<stop offset="0%" stop-color="#f1d8a1" stop-opacity="0.95"/>
|
|
12
|
+
<stop offset="100%" stop-color="#b78f41" stop-opacity="0.85"/>
|
|
13
|
+
</linearGradient>
|
|
14
|
+
<linearGradient id="accent" x1="0" y1="0" x2="1" y2="0">
|
|
15
|
+
<stop offset="0%" stop-color="#69d8c3"/>
|
|
16
|
+
<stop offset="100%" stop-color="#8ab6ff"/>
|
|
17
|
+
</linearGradient>
|
|
18
|
+
<filter id="blur" x="-20%" y="-20%" width="140%" height="140%">
|
|
19
|
+
<feGaussianBlur stdDeviation="24"/>
|
|
20
|
+
</filter>
|
|
21
|
+
</defs>
|
|
22
|
+
|
|
23
|
+
<rect width="1280" height="720" fill="url(#bg)"/>
|
|
24
|
+
<circle cx="1120" cy="132" r="136" fill="#69d8c3" opacity="0.16" filter="url(#blur)"/>
|
|
25
|
+
<circle cx="180" cy="640" r="170" fill="#8ab6ff" opacity="0.18" filter="url(#blur)"/>
|
|
26
|
+
|
|
27
|
+
<rect x="90" y="96" width="470" height="528" rx="34" fill="#0f141c" opacity="0.92" stroke="#3a4c63"/>
|
|
28
|
+
<rect x="126" y="140" width="398" height="18" rx="9" fill="url(#accent)" opacity="0.9"/>
|
|
29
|
+
<rect x="126" y="188" width="182" height="28" rx="14" fill="#f5efe1" opacity="0.92"/>
|
|
30
|
+
<rect x="126" y="242" width="300" height="16" rx="8" fill="#8da6c7" opacity="0.7"/>
|
|
31
|
+
<rect x="126" y="272" width="260" height="16" rx="8" fill="#8da6c7" opacity="0.55"/>
|
|
32
|
+
|
|
33
|
+
<g transform="translate(126 344)">
|
|
34
|
+
<rect width="318" height="68" rx="18" fill="#17212d" stroke="#32465d"/>
|
|
35
|
+
<circle cx="36" cy="34" r="15" fill="#69d8c3"/>
|
|
36
|
+
<path d="M29 34l5 5 10-12" fill="none" stroke="#0d1722" stroke-width="6" stroke-linecap="round" stroke-linejoin="round"/>
|
|
37
|
+
<rect x="72" y="22" width="110" height="12" rx="6" fill="#f1f5f9"/>
|
|
38
|
+
<rect x="72" y="42" width="160" height="10" rx="5" fill="#8da6c7" opacity="0.75"/>
|
|
39
|
+
</g>
|
|
40
|
+
|
|
41
|
+
<g transform="translate(126 430)">
|
|
42
|
+
<rect width="356" height="68" rx="18" fill="#17212d" stroke="#32465d"/>
|
|
43
|
+
<circle cx="36" cy="34" r="15" fill="#69d8c3" opacity="0.82"/>
|
|
44
|
+
<path d="M29 34l5 5 10-12" fill="none" stroke="#0d1722" stroke-width="6" stroke-linecap="round" stroke-linejoin="round"/>
|
|
45
|
+
<rect x="72" y="22" width="132" height="12" rx="6" fill="#f1f5f9"/>
|
|
46
|
+
<rect x="72" y="42" width="200" height="10" rx="5" fill="#8da6c7" opacity="0.75"/>
|
|
47
|
+
</g>
|
|
48
|
+
|
|
49
|
+
<g transform="translate(640 88)">
|
|
50
|
+
<rect width="548" height="548" rx="44" fill="url(#panel)"/>
|
|
51
|
+
<rect x="78" y="84" width="392" height="244" rx="26" fill="#0f141c" opacity="0.92"/>
|
|
52
|
+
<path d="M128 282c42-72 86-108 132-108 35 0 69 15 103 44 31 27 58 40 80 40 39 0 73-21 104-64l29 20c-42 63-87 94-136 94-33 0-67-13-102-39-32-24-60-36-84-36-34 0-67 28-98 84z" fill="#69d8c3"/>
|
|
53
|
+
<circle cx="272" cy="206" r="46" fill="#8ab6ff" opacity="0.92"/>
|
|
54
|
+
<rect x="78" y="372" width="188" height="22" rx="11" fill="#0f141c" opacity="0.88"/>
|
|
55
|
+
<rect x="78" y="414" width="300" height="16" rx="8" fill="#243447" opacity="0.6"/>
|
|
56
|
+
<rect x="78" y="444" width="262" height="16" rx="8" fill="#243447" opacity="0.44"/>
|
|
57
|
+
<rect x="78" y="484" width="164" height="56" rx="18" fill="#0f141c" opacity="0.88"/>
|
|
58
|
+
<rect x="102" y="506" width="114" height="12" rx="6" fill="#f5efe1" opacity="0.88"/>
|
|
59
|
+
</g>
|
|
60
|
+
</svg>
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1280 720" role="img" aria-labelledby="title desc">
|
|
2
|
+
<title id="title">Quick links cover</title>
|
|
3
|
+
<desc id="desc">Abstract navigation cover with cards and directional accents.</desc>
|
|
4
|
+
<defs>
|
|
5
|
+
<linearGradient id="bg" x1="0" y1="0" x2="1" y2="1">
|
|
6
|
+
<stop offset="0%" stop-color="#10261f"/>
|
|
7
|
+
<stop offset="45%" stop-color="#16372d"/>
|
|
8
|
+
<stop offset="100%" stop-color="#1e4d3e"/>
|
|
9
|
+
</linearGradient>
|
|
10
|
+
<linearGradient id="card" x1="0" y1="0" x2="1" y2="1">
|
|
11
|
+
<stop offset="0%" stop-color="#f3f0e7"/>
|
|
12
|
+
<stop offset="100%" stop-color="#d5ddd1"/>
|
|
13
|
+
</linearGradient>
|
|
14
|
+
<linearGradient id="accent" x1="0" y1="0" x2="1" y2="0">
|
|
15
|
+
<stop offset="0%" stop-color="#69d8c3"/>
|
|
16
|
+
<stop offset="100%" stop-color="#d3b874"/>
|
|
17
|
+
</linearGradient>
|
|
18
|
+
<filter id="blur" x="-20%" y="-20%" width="140%" height="140%">
|
|
19
|
+
<feGaussianBlur stdDeviation="26"/>
|
|
20
|
+
</filter>
|
|
21
|
+
</defs>
|
|
22
|
+
|
|
23
|
+
<rect width="1280" height="720" fill="url(#bg)"/>
|
|
24
|
+
<circle cx="154" cy="138" r="126" fill="#69d8c3" opacity="0.18" filter="url(#blur)"/>
|
|
25
|
+
<circle cx="1090" cy="598" r="170" fill="#d3b874" opacity="0.16" filter="url(#blur)"/>
|
|
26
|
+
|
|
27
|
+
<g transform="translate(98 112)">
|
|
28
|
+
<rect width="452" height="480" rx="42" fill="#0f1714" opacity="0.94" stroke="#385247"/>
|
|
29
|
+
<rect x="44" y="48" width="162" height="18" rx="9" fill="url(#accent)"/>
|
|
30
|
+
<rect x="44" y="100" width="278" height="18" rx="9" fill="#f3f0e7" opacity="0.94"/>
|
|
31
|
+
<rect x="44" y="136" width="212" height="14" rx="7" fill="#9cb5ac" opacity="0.58"/>
|
|
32
|
+
|
|
33
|
+
<g transform="translate(44 204)">
|
|
34
|
+
<rect width="364" height="86" rx="24" fill="#17231e" stroke="#33493f"/>
|
|
35
|
+
<rect x="28" y="24" width="116" height="12" rx="6" fill="#f3f0e7"/>
|
|
36
|
+
<rect x="28" y="46" width="176" height="10" rx="5" fill="#8aa196" opacity="0.82"/>
|
|
37
|
+
<circle cx="320" cy="43" r="20" fill="#22362d"/>
|
|
38
|
+
<path d="M311 43h18M321 34l9 9-9 9" fill="none" stroke="#69d8c3" stroke-width="6" stroke-linecap="round" stroke-linejoin="round"/>
|
|
39
|
+
</g>
|
|
40
|
+
|
|
41
|
+
<g transform="translate(44 310)">
|
|
42
|
+
<rect width="330" height="86" rx="24" fill="#17231e" stroke="#33493f"/>
|
|
43
|
+
<rect x="28" y="24" width="96" height="12" rx="6" fill="#f3f0e7"/>
|
|
44
|
+
<rect x="28" y="46" width="156" height="10" rx="5" fill="#8aa196" opacity="0.82"/>
|
|
45
|
+
<circle cx="286" cy="43" r="20" fill="#22362d"/>
|
|
46
|
+
<path d="M277 43h18M287 34l9 9-9 9" fill="none" stroke="#69d8c3" stroke-width="6" stroke-linecap="round" stroke-linejoin="round"/>
|
|
47
|
+
</g>
|
|
48
|
+
</g>
|
|
49
|
+
|
|
50
|
+
<g transform="translate(646 100)">
|
|
51
|
+
<rect width="536" height="520" rx="44" fill="url(#card)" opacity="0.98"/>
|
|
52
|
+
<rect x="58" y="56" width="420" height="248" rx="28" fill="#0f1714" opacity="0.94"/>
|
|
53
|
+
<g transform="translate(110 114)">
|
|
54
|
+
<rect width="116" height="116" rx="28" fill="#69d8c3"/>
|
|
55
|
+
<path d="M40 58h36M58 40l18 18-18 18" fill="none" stroke="#0f1714" stroke-width="10" stroke-linecap="round" stroke-linejoin="round"/>
|
|
56
|
+
</g>
|
|
57
|
+
<g transform="translate(250 114)">
|
|
58
|
+
<rect width="116" height="116" rx="28" fill="#d3b874"/>
|
|
59
|
+
<path d="M40 58h36M58 40l18 18-18 18" fill="none" stroke="#0f1714" stroke-width="10" stroke-linecap="round" stroke-linejoin="round"/>
|
|
60
|
+
</g>
|
|
61
|
+
<g transform="translate(180 272)">
|
|
62
|
+
<rect width="116" height="116" rx="28" fill="#8ab6ff"/>
|
|
63
|
+
<path d="M40 58h36M58 40l18 18-18 18" fill="none" stroke="#0f1714" stroke-width="10" stroke-linecap="round" stroke-linejoin="round"/>
|
|
64
|
+
</g>
|
|
65
|
+
<rect x="58" y="360" width="204" height="18" rx="9" fill="#10261f" opacity="0.92"/>
|
|
66
|
+
<rect x="58" y="396" width="294" height="14" rx="7" fill="#425b52" opacity="0.6"/>
|
|
67
|
+
<rect x="58" y="424" width="248" height="14" rx="7" fill="#425b52" opacity="0.42"/>
|
|
68
|
+
<rect x="58" y="470" width="172" height="58" rx="18" fill="#10261f" opacity="0.92"/>
|
|
69
|
+
<rect x="84" y="493" width="120" height="12" rx="6" fill="#f3f0e7" opacity="0.92"/>
|
|
70
|
+
</g>
|
|
71
|
+
</svg>
|
|
@@ -0,0 +1,223 @@
|
|
|
1
|
+
<script setup>
|
|
2
|
+
const BASE_URL = import.meta.env.BASE_URL || '/'
|
|
3
|
+
|
|
4
|
+
defineOptions({
|
|
5
|
+
name: 'DBlockCard'
|
|
6
|
+
})
|
|
7
|
+
|
|
8
|
+
const props = defineProps({
|
|
9
|
+
items: {
|
|
10
|
+
type: Array,
|
|
11
|
+
default: () => []
|
|
12
|
+
},
|
|
13
|
+
title: {
|
|
14
|
+
type: String,
|
|
15
|
+
default: ''
|
|
16
|
+
}
|
|
17
|
+
})
|
|
18
|
+
|
|
19
|
+
const isExternal = (item) => {
|
|
20
|
+
const href = item?.href || ''
|
|
21
|
+
return /^https?:\/\//i.test(href)
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
const itemTag = (item) => {
|
|
25
|
+
if (item?.to) return 'router-link'
|
|
26
|
+
return 'a'
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const itemProps = (item) => {
|
|
30
|
+
if (item?.to) {
|
|
31
|
+
return {
|
|
32
|
+
to: item.to
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const href = item?.href || ''
|
|
37
|
+
return {
|
|
38
|
+
href,
|
|
39
|
+
target: isExternal(item) ? '_blank' : undefined,
|
|
40
|
+
rel: isExternal(item) ? 'noopener noreferrer' : undefined
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
const resolveAssetUrl = (raw = '') => {
|
|
45
|
+
const value = String(raw || '').trim()
|
|
46
|
+
|
|
47
|
+
if (!value) {
|
|
48
|
+
return ''
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
if (/^(?:[a-z]+:)?\/\//i.test(value) || /^(?:data:|blob:)/i.test(value)) {
|
|
52
|
+
return value
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
const trimmedBase = String(BASE_URL).replace(/\/$/, '')
|
|
56
|
+
|
|
57
|
+
if (value.startsWith('/')) {
|
|
58
|
+
return `${trimmedBase}${value}` || value
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
const normalized = value.replace(/^\.\//, '')
|
|
62
|
+
return `${trimmedBase}/${normalized}`.replace(/\/+/g, '/')
|
|
63
|
+
}
|
|
64
|
+
</script>
|
|
65
|
+
|
|
66
|
+
<template>
|
|
67
|
+
<div class="d-cards">
|
|
68
|
+
<h3 v-if="title" class="d-cards__title">{{ title }}</h3>
|
|
69
|
+
|
|
70
|
+
<div class="d-cards__grid">
|
|
71
|
+
<component
|
|
72
|
+
:is="itemTag(item)"
|
|
73
|
+
v-for="(item, index) in props.items"
|
|
74
|
+
:key="`${item.title}-${index}`"
|
|
75
|
+
class="d-cards__link"
|
|
76
|
+
v-bind="itemProps(item)"
|
|
77
|
+
>
|
|
78
|
+
<q-card flat bordered class="d-cards__card">
|
|
79
|
+
<q-img
|
|
80
|
+
v-if="item.image"
|
|
81
|
+
:src="resolveAssetUrl(item.image)"
|
|
82
|
+
:alt="item.title"
|
|
83
|
+
ratio="1.7778"
|
|
84
|
+
class="d-cards__image"
|
|
85
|
+
/>
|
|
86
|
+
|
|
87
|
+
<q-card-section v-else-if="item.icon" class="d-cards__icon-section">
|
|
88
|
+
<div class="d-cards__icon-surface">
|
|
89
|
+
<q-icon :name="item.icon" size="56px" color="primary" />
|
|
90
|
+
</div>
|
|
91
|
+
</q-card-section>
|
|
92
|
+
|
|
93
|
+
<q-card-section class="d-cards__body">
|
|
94
|
+
<div class="d-cards__heading-row">
|
|
95
|
+
<div class="d-cards__heading-group">
|
|
96
|
+
<q-icon
|
|
97
|
+
v-if="item.image && item.icon"
|
|
98
|
+
:name="item.icon"
|
|
99
|
+
size="18px"
|
|
100
|
+
color="primary"
|
|
101
|
+
/>
|
|
102
|
+
<div class="d-cards__label">{{ item.title }}</div>
|
|
103
|
+
</div>
|
|
104
|
+
|
|
105
|
+
<q-icon :name="isExternal(item) ? 'arrow_outward' : 'arrow_forward'" size="18px" />
|
|
106
|
+
</div>
|
|
107
|
+
|
|
108
|
+
<div class="d-cards__description">{{ item.description }}</div>
|
|
109
|
+
</q-card-section>
|
|
110
|
+
</q-card>
|
|
111
|
+
</component>
|
|
112
|
+
</div>
|
|
113
|
+
</div>
|
|
114
|
+
</template>
|
|
115
|
+
|
|
116
|
+
<style lang="sass">
|
|
117
|
+
body.body--light
|
|
118
|
+
--d-cards-card-bg: #fffdf8
|
|
119
|
+
--d-cards-card-border: rgba(123, 94, 45, 0.16)
|
|
120
|
+
--d-cards-card-shadow: rgba(94, 73, 37, 0.08)
|
|
121
|
+
--d-cards-card-shadow-hover: rgba(94, 73, 37, 0.16)
|
|
122
|
+
--d-cards-description: #4d5563
|
|
123
|
+
--d-cards-icon-surface: linear-gradient(180deg, rgba(210, 190, 145, 0.22), rgba(210, 190, 145, 0.08))
|
|
124
|
+
|
|
125
|
+
body.body--dark
|
|
126
|
+
--d-cards-card-bg: rgba(255, 248, 235, 0.035)
|
|
127
|
+
--d-cards-card-border: rgba(255, 235, 194, 0.12)
|
|
128
|
+
--d-cards-card-shadow: rgba(0, 0, 0, 0.25)
|
|
129
|
+
--d-cards-card-shadow-hover: rgba(0, 0, 0, 0.38)
|
|
130
|
+
--d-cards-description: rgba(255, 255, 255, 0.82)
|
|
131
|
+
--d-cards-icon-surface: linear-gradient(180deg, rgba(193, 166, 103, 0.18), rgba(193, 166, 103, 0.05))
|
|
132
|
+
|
|
133
|
+
.d-cards
|
|
134
|
+
margin: 0 auto
|
|
135
|
+
|
|
136
|
+
.d-cards__title
|
|
137
|
+
text-align: center
|
|
138
|
+
margin: 0 0 16px
|
|
139
|
+
|
|
140
|
+
.d-cards__grid
|
|
141
|
+
display: grid
|
|
142
|
+
grid-template-columns: repeat(auto-fit, minmax(240px, 1fr))
|
|
143
|
+
gap: 16px
|
|
144
|
+
|
|
145
|
+
.d-cards__link
|
|
146
|
+
display: block
|
|
147
|
+
color: inherit
|
|
148
|
+
text-decoration: none
|
|
149
|
+
border-bottom: 0 !important
|
|
150
|
+
background: transparent !important
|
|
151
|
+
|
|
152
|
+
.d-cards__link:hover,
|
|
153
|
+
.d-cards__link:focus-visible,
|
|
154
|
+
.d-cards__link:active,
|
|
155
|
+
.d-cards__link:visited
|
|
156
|
+
color: inherit !important
|
|
157
|
+
text-decoration: none
|
|
158
|
+
border-bottom: 0 !important
|
|
159
|
+
background: transparent !important
|
|
160
|
+
|
|
161
|
+
.d-cards__card
|
|
162
|
+
height: 100%
|
|
163
|
+
overflow: hidden
|
|
164
|
+
border-radius: 18px
|
|
165
|
+
background: var(--d-cards-card-bg)
|
|
166
|
+
border-color: var(--d-cards-card-border)
|
|
167
|
+
box-shadow: 0 12px 28px var(--d-cards-card-shadow)
|
|
168
|
+
transition: transform 180ms ease, box-shadow 180ms ease, border-color 180ms ease
|
|
169
|
+
|
|
170
|
+
.d-cards__link:hover .d-cards__card,
|
|
171
|
+
.d-cards__link:focus-visible .d-cards__card
|
|
172
|
+
transform: translateY(-2px)
|
|
173
|
+
box-shadow: 0 18px 36px var(--d-cards-card-shadow-hover)
|
|
174
|
+
|
|
175
|
+
.d-cards__link:focus-visible
|
|
176
|
+
outline: none
|
|
177
|
+
|
|
178
|
+
.d-cards__image
|
|
179
|
+
background: rgba(0, 0, 0, 0.05)
|
|
180
|
+
|
|
181
|
+
.d-cards__icon-section
|
|
182
|
+
display: flex
|
|
183
|
+
padding-bottom: 0
|
|
184
|
+
|
|
185
|
+
.d-cards__icon-surface
|
|
186
|
+
display: flex
|
|
187
|
+
align-items: center
|
|
188
|
+
justify-content: center
|
|
189
|
+
width: 100%
|
|
190
|
+
min-height: 156px
|
|
191
|
+
border-radius: 14px
|
|
192
|
+
background: var(--d-cards-icon-surface)
|
|
193
|
+
|
|
194
|
+
.d-cards__body
|
|
195
|
+
display: grid
|
|
196
|
+
gap: 10px
|
|
197
|
+
|
|
198
|
+
.d-cards__heading-row
|
|
199
|
+
display: flex
|
|
200
|
+
align-items: flex-start
|
|
201
|
+
justify-content: space-between
|
|
202
|
+
gap: 12px
|
|
203
|
+
|
|
204
|
+
.d-cards__heading-group
|
|
205
|
+
display: flex
|
|
206
|
+
align-items: center
|
|
207
|
+
gap: 8px
|
|
208
|
+
min-width: 0
|
|
209
|
+
|
|
210
|
+
.d-cards__label
|
|
211
|
+
font-size: 1rem
|
|
212
|
+
font-weight: 700
|
|
213
|
+
line-height: 1.35
|
|
214
|
+
|
|
215
|
+
.d-cards__description
|
|
216
|
+
color: var(--d-cards-description)
|
|
217
|
+
font-size: 0.97rem
|
|
218
|
+
line-height: 1.55
|
|
219
|
+
|
|
220
|
+
@media (max-width: 599px)
|
|
221
|
+
.d-cards__grid
|
|
222
|
+
grid-template-columns: 1fr
|
|
223
|
+
</style>
|
|
@@ -25,6 +25,7 @@ import DPageBlockquote from './DPageBlockquote.vue'
|
|
|
25
25
|
import DPageImage from './DPageImage.vue'
|
|
26
26
|
import DPageFile from './DPageFile.vue'
|
|
27
27
|
import DPageEmbeddedUrl from './DPageEmbeddedUrl.vue'
|
|
28
|
+
import DBlockCard from './DBlockCard.vue'
|
|
28
29
|
import DQuickLinks from './DQuickLinks.vue'
|
|
29
30
|
import DPageExpandable from './DPageExpandable.vue'
|
|
30
31
|
</script>
|
|
@@ -128,6 +129,12 @@ import DPageExpandable from './DPageExpandable.vue'
|
|
|
128
129
|
:content="token.content"
|
|
129
130
|
/>
|
|
130
131
|
|
|
132
|
+
<d-block-card
|
|
133
|
+
v-else-if="token.tag === 'cards'"
|
|
134
|
+
:title="token.title"
|
|
135
|
+
:items="token.items"
|
|
136
|
+
/>
|
|
137
|
+
|
|
131
138
|
<d-quick-links
|
|
132
139
|
v-else-if="token.tag === 'quick-links'"
|
|
133
140
|
:title="token.title"
|
|
@@ -13,6 +13,7 @@ const ALERT_MESSAGE_TYPES = new Set([
|
|
|
13
13
|
'caution'
|
|
14
14
|
])
|
|
15
15
|
|
|
16
|
+
const CARDS_MARKER_PREFIX = '@@DOCSECTOR_CARDS_'
|
|
16
17
|
const QUICK_LINKS_MARKER_PREFIX = '@@DOCSECTOR_QUICK_LINKS_'
|
|
17
18
|
const EXPANDABLE_MARKER_PREFIX = '@@DOCSECTOR_EXPANDABLE_'
|
|
18
19
|
const FILE_MARKER_PREFIX = '@@DOCSECTOR_FILE_'
|
|
@@ -190,6 +191,55 @@ const extractQuickLinksBlocks = (source = '') => {
|
|
|
190
191
|
}
|
|
191
192
|
}
|
|
192
193
|
|
|
194
|
+
const extractCardsBlocks = (source = '') => {
|
|
195
|
+
const map = new Map()
|
|
196
|
+
let index = 0
|
|
197
|
+
|
|
198
|
+
const blockPattern = /<d-(?:block-)?cards\b([^>]*)>([\s\S]*?)<\/d-(?:block-)?cards>/gi
|
|
199
|
+
const replaced = String(source).replace(blockPattern, (_, blockAttrsRaw, inner) => {
|
|
200
|
+
const blockAttrs = parseCustomTagAttributes(blockAttrsRaw)
|
|
201
|
+
const items = []
|
|
202
|
+
const itemPattern = /<d-(?:block-)?card\b([^>]*)\/?\s*>/gi
|
|
203
|
+
|
|
204
|
+
let itemMatch = itemPattern.exec(inner)
|
|
205
|
+
while (itemMatch !== null) {
|
|
206
|
+
const itemAttrs = parseCustomTagAttributes(itemMatch[1])
|
|
207
|
+
const title = itemAttrs.title || ''
|
|
208
|
+
const description = itemAttrs.description || ''
|
|
209
|
+
const to = itemAttrs.to || ''
|
|
210
|
+
const href = itemAttrs.href || ''
|
|
211
|
+
|
|
212
|
+
if (title && description && (to || href)) {
|
|
213
|
+
items.push({
|
|
214
|
+
title,
|
|
215
|
+
description,
|
|
216
|
+
to,
|
|
217
|
+
href,
|
|
218
|
+
image: itemAttrs.image || '',
|
|
219
|
+
icon: itemAttrs.icon || ''
|
|
220
|
+
})
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
itemMatch = itemPattern.exec(inner)
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
const marker = `${CARDS_MARKER_PREFIX}${index}@@`
|
|
227
|
+
index++
|
|
228
|
+
|
|
229
|
+
map.set(marker, {
|
|
230
|
+
title: blockAttrs.title || '',
|
|
231
|
+
items
|
|
232
|
+
})
|
|
233
|
+
|
|
234
|
+
return `\n${marker}\n`
|
|
235
|
+
})
|
|
236
|
+
|
|
237
|
+
return {
|
|
238
|
+
source: replaced,
|
|
239
|
+
cardsMap: map
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
|
|
193
243
|
const parseExpandableOpenState = (raw = '') => {
|
|
194
244
|
return ['1', 'true', 'yes', 'on'].includes(String(raw).trim().toLowerCase())
|
|
195
245
|
}
|
|
@@ -601,7 +651,8 @@ export const tokenizePageSectionSource = (source = '', options = {}) => {
|
|
|
601
651
|
})
|
|
602
652
|
})
|
|
603
653
|
|
|
604
|
-
const { source:
|
|
654
|
+
const { source: sourceWithCards, cardsMap } = extractCardsBlocks(sourceWithExpandables)
|
|
655
|
+
const { source: sourceWithQuickLinks, quickLinksMap } = extractQuickLinksBlocks(sourceWithCards)
|
|
605
656
|
const { source: sourceWithFiles, fileMap } = extractFileBlocks(sourceWithQuickLinks)
|
|
606
657
|
const { source: sourceWithEmbeddedUrls, embeddedUrlMap } = extractEmbeddedUrlBlocks(sourceWithFiles)
|
|
607
658
|
|
|
@@ -779,6 +830,17 @@ export const tokenizePageSectionSource = (source = '', options = {}) => {
|
|
|
779
830
|
break
|
|
780
831
|
}
|
|
781
832
|
|
|
833
|
+
if (cardsMap.has(element.content.trim())) {
|
|
834
|
+
const data = cardsMap.get(element.content.trim())
|
|
835
|
+
|
|
836
|
+
tokens.push({
|
|
837
|
+
tag: 'cards',
|
|
838
|
+
title: data.title,
|
|
839
|
+
items: data.items
|
|
840
|
+
})
|
|
841
|
+
break
|
|
842
|
+
}
|
|
843
|
+
|
|
782
844
|
if (quickLinksMap.has(element.content.trim())) {
|
|
783
845
|
const data = quickLinksMap.get(element.content.trim())
|
|
784
846
|
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
## Overview
|
|
2
|
+
|
|
3
|
+
Cards render a responsive grid of linked content blocks directly inside Markdown.
|
|
4
|
+
|
|
5
|
+
They are useful for landing sections, curated resource lists, and any place where a plain list of links feels too flat.
|
|
6
|
+
|
|
7
|
+
## Markdown Syntax
|
|
8
|
+
|
|
9
|
+
```html
|
|
10
|
+
<d-block-cards title="Explore more">
|
|
11
|
+
<d-block-card
|
|
12
|
+
title="Install"
|
|
13
|
+
description="Set up the project"
|
|
14
|
+
to="/guide/getting-started"
|
|
15
|
+
image="/images/cards/getting-started-cover.svg"
|
|
16
|
+
/>
|
|
17
|
+
<d-block-card
|
|
18
|
+
title="GitHub"
|
|
19
|
+
description="Open the repository"
|
|
20
|
+
href="https://github.com/docsector/docsector-reader"
|
|
21
|
+
icon="launch"
|
|
22
|
+
/>
|
|
23
|
+
</d-block-cards>
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
## Notes
|
|
27
|
+
|
|
28
|
+
- Use `to` for internal navigation and `href` for external URLs.
|
|
29
|
+
- Add `image` when the card should feel more like a landing-page tile.
|
|
30
|
+
- Add `icon` when the card has no image but still needs a stronger visual cue.
|
|
31
|
+
- Short descriptions scan better than paragraph-sized copy.
|
|
32
|
+
- Cover images look best in a wide format such as 16:9.
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
## Visão geral
|
|
2
|
+
|
|
3
|
+
Cards renderizam uma grade responsiva de blocos com link diretamente dentro do Markdown.
|
|
4
|
+
|
|
5
|
+
Eles são úteis para seções de entrada, listas curadas de recursos e qualquer lugar em que uma lista simples de links fique visualmente pobre.
|
|
6
|
+
|
|
7
|
+
## Sintaxe Markdown
|
|
8
|
+
|
|
9
|
+
```html
|
|
10
|
+
<d-block-cards title="Explore mais">
|
|
11
|
+
<d-block-card
|
|
12
|
+
title="Instalação"
|
|
13
|
+
description="Configure o projeto"
|
|
14
|
+
to="/guide/getting-started"
|
|
15
|
+
image="/images/cards/getting-started-cover.svg"
|
|
16
|
+
/>
|
|
17
|
+
<d-block-card
|
|
18
|
+
title="GitHub"
|
|
19
|
+
description="Abra o repositório"
|
|
20
|
+
href="https://github.com/docsector/docsector-reader"
|
|
21
|
+
icon="launch"
|
|
22
|
+
/>
|
|
23
|
+
</d-block-cards>
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
## Notas
|
|
27
|
+
|
|
28
|
+
- Use `to` para navegação interna e `href` para URLs externas.
|
|
29
|
+
- Adicione `image` quando o card precisar se comportar mais como um bloco de landing page.
|
|
30
|
+
- Adicione `icon` quando o card não tiver imagem, mas ainda precisar de uma pista visual mais forte.
|
|
31
|
+
- Descrições curtas funcionam melhor do que textos longos.
|
|
32
|
+
- Imagens de capa ficam melhores em formatos largos, como 16:9.
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
## Showcase
|
|
2
|
+
|
|
3
|
+
<d-block-cards title="Start here">
|
|
4
|
+
<d-block-card
|
|
5
|
+
title="Getting Started"
|
|
6
|
+
description="Install and run the project"
|
|
7
|
+
to="/guide/getting-started"
|
|
8
|
+
image="/images/cards/getting-started-cover.svg"
|
|
9
|
+
/>
|
|
10
|
+
<d-block-card
|
|
11
|
+
title="Quick Links"
|
|
12
|
+
description="Open another navigation-focused block"
|
|
13
|
+
to="/manual/content/blocks/quick-links"
|
|
14
|
+
image="/images/cards/quick-links-cover.svg"
|
|
15
|
+
/>
|
|
16
|
+
<d-block-card
|
|
17
|
+
title="GitHub"
|
|
18
|
+
description="Open the repository"
|
|
19
|
+
href="https://github.com/docsector/docsector-reader"
|
|
20
|
+
icon="launch"
|
|
21
|
+
/>
|
|
22
|
+
</d-block-cards>
|
|
23
|
+
|
|
24
|
+
## Without Cover Images
|
|
25
|
+
|
|
26
|
+
<d-block-cards title="Continue reading">
|
|
27
|
+
<d-block-card
|
|
28
|
+
title="Expandable"
|
|
29
|
+
description="Read the collapsible content block overview"
|
|
30
|
+
to="/manual/content/blocks/expandable"
|
|
31
|
+
icon="unfold_more"
|
|
32
|
+
/>
|
|
33
|
+
<d-block-card
|
|
34
|
+
title="Page structure"
|
|
35
|
+
description="Review the main page container structure"
|
|
36
|
+
to="/manual/content/structures/page"
|
|
37
|
+
icon="view_quilt"
|
|
38
|
+
/>
|
|
39
|
+
</d-block-cards>
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
## Showcase
|
|
2
|
+
|
|
3
|
+
<d-block-cards title="Comece por aqui">
|
|
4
|
+
<d-block-card
|
|
5
|
+
title="Primeiros passos"
|
|
6
|
+
description="Instale e execute o projeto"
|
|
7
|
+
to="/guide/getting-started"
|
|
8
|
+
image="/images/cards/getting-started-cover.svg"
|
|
9
|
+
/>
|
|
10
|
+
<d-block-card
|
|
11
|
+
title="Quick Links"
|
|
12
|
+
description="Abra outro block focado em navegação"
|
|
13
|
+
to="/manual/content/blocks/quick-links"
|
|
14
|
+
image="/images/cards/quick-links-cover.svg"
|
|
15
|
+
/>
|
|
16
|
+
<d-block-card
|
|
17
|
+
title="GitHub"
|
|
18
|
+
description="Abra o repositório"
|
|
19
|
+
href="https://github.com/docsector/docsector-reader"
|
|
20
|
+
icon="launch"
|
|
21
|
+
/>
|
|
22
|
+
</d-block-cards>
|
|
23
|
+
|
|
24
|
+
## Sem imagens de capa
|
|
25
|
+
|
|
26
|
+
<d-block-cards title="Continue lendo">
|
|
27
|
+
<d-block-card
|
|
28
|
+
title="Expandable"
|
|
29
|
+
description="Leia a visão geral do block colapsável"
|
|
30
|
+
to="/manual/content/blocks/expandable"
|
|
31
|
+
icon="unfold_more"
|
|
32
|
+
/>
|
|
33
|
+
<d-block-card
|
|
34
|
+
title="Estrutura de página"
|
|
35
|
+
description="Revise a estrutura principal do container de página"
|
|
36
|
+
to="/manual/content/structures/page"
|
|
37
|
+
icon="view_quilt"
|
|
38
|
+
/>
|
|
39
|
+
</d-block-cards>
|
|
@@ -767,6 +767,34 @@ export default {
|
|
|
767
767
|
}
|
|
768
768
|
},
|
|
769
769
|
|
|
770
|
+
'/content/blocks/cards': {
|
|
771
|
+
config: {
|
|
772
|
+
icon: 'view_module',
|
|
773
|
+
status: 'done',
|
|
774
|
+
meta: {
|
|
775
|
+
description: {
|
|
776
|
+
'en-US': 'Cards — Documentation of Docsector Reader',
|
|
777
|
+
'pt-BR': 'Cartões — Documentacao do Docsector Reader'
|
|
778
|
+
}
|
|
779
|
+
},
|
|
780
|
+
book: 'manual',
|
|
781
|
+
menu: {},
|
|
782
|
+
subpages: {
|
|
783
|
+
showcase: true
|
|
784
|
+
}
|
|
785
|
+
},
|
|
786
|
+
data: {
|
|
787
|
+
'en-US': { title: 'Cards' },
|
|
788
|
+
'pt-BR': { title: 'Cartões' }
|
|
789
|
+
},
|
|
790
|
+
metadata: {
|
|
791
|
+
tags: {
|
|
792
|
+
'en-US': 'cards grid cover image navigation content links layout',
|
|
793
|
+
'pt-BR': 'cartões grade imagem capa navegação conteúdo links layout'
|
|
794
|
+
}
|
|
795
|
+
}
|
|
796
|
+
},
|
|
797
|
+
|
|
770
798
|
'/content/structures': {
|
|
771
799
|
config: null,
|
|
772
800
|
data: {
|