@docsector/docsector-reader 0.5.9 → 0.7.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 +17 -0
- package/bin/docsector.js +2 -2
- package/package.json +1 -1
- package/src/components/DPageBar.vue +135 -0
- package/src/components/DPageBlockquote.vue +46 -4
- package/src/components/DPageSection.vue +147 -2
- package/src/components/DSubpage.vue +3 -0
- package/src/css/app.sass +102 -7
- package/src/i18n/languages/en-US.hjson +7 -1
- package/src/i18n/languages/pt-BR.hjson +7 -1
- package/src/i18n/tags.hjson +2 -0
- package/src/pages/guide/alerts-and-blockquotes.overview.en-US.md +65 -0
- package/src/pages/guide/alerts-and-blockquotes.overview.pt-BR.md +65 -0
- package/src/pages/guide/i18n-and-markdown.overview.en-US.md +14 -0
- package/src/pages/guide/i18n-and-markdown.overview.pt-BR.md +14 -0
- package/src/pages/index.js +22 -0
- package/src/pages/manual/components/d-page-blockquote.overview.en-US.md +31 -9
- package/src/pages/manual/components/d-page-blockquote.overview.pt-BR.md +31 -9
- package/src/pages/manual/components/d-page-blockquote.showcase.en-US.md +19 -12
- package/src/pages/manual/components/d-page-blockquote.showcase.pt-BR.md +19 -12
- package/src/quasar.factory.js +192 -1
package/README.md
CHANGED
|
@@ -22,6 +22,9 @@ Transform Markdown content into beautiful, navigable documentation sites — wit
|
|
|
22
22
|
|
|
23
23
|
- 📝 **Markdown Rendering** — Write docs in Markdown, rendered with syntax highlighting (Prism.js)
|
|
24
24
|
- 🧩 **Mermaid Diagrams** — Native support for fenced ` ```mermaid ` blocks, with automatic dark/light theme switching
|
|
25
|
+
- 🚨 **GitHub-Style Alerts** — Native support for `[!NOTE]`, `[!TIP]`, `[!IMPORTANT]`, `[!WARNING]`, and `[!CAUTION]`
|
|
26
|
+
- 🤖 **AI-Friendly** — "Copy page" button copies raw Markdown for LLMs; "View as Markdown" opens any page as plain text via `.md` URL suffix
|
|
27
|
+
- 📅 **Last Updated Date** — Automatic per-page "last updated" date from git commit history, locale-formatted
|
|
25
28
|
- 🌍 **Internationalization (i18n)** — Multi-language support with HJSON locale files and per-page translations
|
|
26
29
|
- 🌗 **Dark/Light Mode** — Automatic theme switching with Quasar Dark Plugin
|
|
27
30
|
- 🔗 **Anchor Navigation** — Right-side Table of Contents tree with scroll tracking
|
|
@@ -284,6 +287,20 @@ src/pages/manual/my-section/my-page.overview.en-US.md
|
|
|
284
287
|
src/pages/manual/my-section/my-page.overview.pt-BR.md
|
|
285
288
|
```
|
|
286
289
|
|
|
290
|
+
### GitHub-Style Alert Example
|
|
291
|
+
|
|
292
|
+
```markdown
|
|
293
|
+
> [!CAUTION]
|
|
294
|
+
> NOTICE OF BREAKING CHANGE.
|
|
295
|
+
>
|
|
296
|
+
> As of 7.0.0, multiple breaking changes were introduced into the library.
|
|
297
|
+
>
|
|
298
|
+
> Please review the migration guide before updating.
|
|
299
|
+
```
|
|
300
|
+
|
|
301
|
+
Supported alert types: `NOTE`, `TIP`, `IMPORTANT`, `WARNING`, `CAUTION`.
|
|
302
|
+
Regular blockquotes without `[!TYPE]` continue to work normally.
|
|
303
|
+
|
|
287
304
|
---
|
|
288
305
|
|
|
289
306
|
## 🖥️ CLI Commands
|
package/bin/docsector.js
CHANGED
|
@@ -23,7 +23,7 @@ const packageRoot = resolve(__dirname, '..')
|
|
|
23
23
|
const args = process.argv.slice(2)
|
|
24
24
|
const command = args[0]
|
|
25
25
|
|
|
26
|
-
const VERSION = '0.
|
|
26
|
+
const VERSION = '0.6.0'
|
|
27
27
|
|
|
28
28
|
const HELP = `
|
|
29
29
|
Docsector Reader v${VERSION}
|
|
@@ -71,7 +71,7 @@ function getTemplatePackageJson (name) {
|
|
|
71
71
|
serve: 'docsector serve'
|
|
72
72
|
},
|
|
73
73
|
dependencies: {
|
|
74
|
-
'@docsector/docsector-reader': '^0.
|
|
74
|
+
'@docsector/docsector-reader': '^0.6.0',
|
|
75
75
|
'@quasar/extras': '^1.16.12',
|
|
76
76
|
'quasar': '^2.16.6',
|
|
77
77
|
'vue': '^3.5.13',
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@docsector/docsector-reader",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.7.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,135 @@
|
|
|
1
|
+
<script setup>
|
|
2
|
+
import { ref, computed } from 'vue'
|
|
3
|
+
import { useRoute } from 'vue-router'
|
|
4
|
+
import { useStore } from 'vuex'
|
|
5
|
+
import { useI18n } from 'vue-i18n'
|
|
6
|
+
import { copyToClipboard, openURL } from 'quasar'
|
|
7
|
+
|
|
8
|
+
import gitDates from 'virtual:docsector-git-dates'
|
|
9
|
+
|
|
10
|
+
const store = useStore()
|
|
11
|
+
const route = useRoute()
|
|
12
|
+
const { t, locale } = useI18n()
|
|
13
|
+
|
|
14
|
+
const copied = ref(false)
|
|
15
|
+
|
|
16
|
+
const subpage = computed(() => {
|
|
17
|
+
const rel = store.state.page.relative
|
|
18
|
+
return rel ? rel.replace(/^\//, '') : 'overview'
|
|
19
|
+
})
|
|
20
|
+
|
|
21
|
+
const fileKey = computed(() => {
|
|
22
|
+
const base = store.state.page.base
|
|
23
|
+
if (!base) return ''
|
|
24
|
+
return `${base}.${subpage.value}.${locale.value}.md`
|
|
25
|
+
})
|
|
26
|
+
|
|
27
|
+
const formattedDate = computed(() => {
|
|
28
|
+
const iso = gitDates[fileKey.value]
|
|
29
|
+
if (!iso) return ''
|
|
30
|
+
|
|
31
|
+
const date = new Date(iso)
|
|
32
|
+
if (isNaN(date.getTime())) return ''
|
|
33
|
+
|
|
34
|
+
return new Intl.DateTimeFormat(locale.value, {
|
|
35
|
+
year: 'numeric',
|
|
36
|
+
month: 'long',
|
|
37
|
+
day: 'numeric'
|
|
38
|
+
}).format(date)
|
|
39
|
+
})
|
|
40
|
+
|
|
41
|
+
const rawMarkdown = computed(() => {
|
|
42
|
+
const absolute = store.state.i18n.absolute
|
|
43
|
+
if (!absolute) return ''
|
|
44
|
+
|
|
45
|
+
const source = t(`_.${absolute}.source`)
|
|
46
|
+
if (!source) return ''
|
|
47
|
+
|
|
48
|
+
return String(source)
|
|
49
|
+
.replace(/{/g, '{')
|
|
50
|
+
.replace(/}/g, '}')
|
|
51
|
+
.replace(/\{'([^']+)'\}/g, '$1')
|
|
52
|
+
.replace(/&/g, '&')
|
|
53
|
+
})
|
|
54
|
+
|
|
55
|
+
const markdownURL = computed(() => {
|
|
56
|
+
return `${route.path}.md`
|
|
57
|
+
})
|
|
58
|
+
|
|
59
|
+
const copyPage = () => {
|
|
60
|
+
if (!rawMarkdown.value) return
|
|
61
|
+
|
|
62
|
+
copyToClipboard(rawMarkdown.value).then(() => {
|
|
63
|
+
copied.value = true
|
|
64
|
+
setTimeout(() => { copied.value = false }, 2000)
|
|
65
|
+
})
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
const viewAsMarkdown = () => {
|
|
69
|
+
openURL(markdownURL.value)
|
|
70
|
+
}
|
|
71
|
+
</script>
|
|
72
|
+
|
|
73
|
+
<template>
|
|
74
|
+
<div class="d-page-bar">
|
|
75
|
+
<span v-if="formattedDate" class="d-page-bar__date">
|
|
76
|
+
{{ t('page.lastUpdated') }}: {{ formattedDate }}
|
|
77
|
+
</span>
|
|
78
|
+
<span v-else class="d-page-bar__date"></span>
|
|
79
|
+
|
|
80
|
+
<q-btn-dropdown
|
|
81
|
+
class="d-page-bar__actions"
|
|
82
|
+
split
|
|
83
|
+
no-caps
|
|
84
|
+
:icon="copied ? 'check' : 'content_copy'"
|
|
85
|
+
:label="copied ? t('page.copied') : t('page.copyPage')"
|
|
86
|
+
:color="copied ? 'positive' : 'grey-7'"
|
|
87
|
+
size="sm"
|
|
88
|
+
@click="copyPage"
|
|
89
|
+
>
|
|
90
|
+
<q-list style="min-width: 240px">
|
|
91
|
+
<q-item clickable v-close-popup @click="copyPage" class="q-py-sm">
|
|
92
|
+
<q-item-section avatar>
|
|
93
|
+
<q-icon name="content_copy" />
|
|
94
|
+
</q-item-section>
|
|
95
|
+
<q-item-section>
|
|
96
|
+
<q-item-label>{{ t('page.copyPage') }}</q-item-label>
|
|
97
|
+
<q-item-label caption>{{ t('page.copyPageCaption') }}</q-item-label>
|
|
98
|
+
</q-item-section>
|
|
99
|
+
</q-item>
|
|
100
|
+
|
|
101
|
+
<q-item clickable v-close-popup @click="viewAsMarkdown" class="q-py-sm">
|
|
102
|
+
<q-item-section avatar>
|
|
103
|
+
<q-icon name="description" />
|
|
104
|
+
</q-item-section>
|
|
105
|
+
<q-item-section>
|
|
106
|
+
<q-item-label>{{ t('page.viewAsMarkdown') }}</q-item-label>
|
|
107
|
+
<q-item-label caption>{{ t('page.viewAsMarkdownCaption') }}</q-item-label>
|
|
108
|
+
</q-item-section>
|
|
109
|
+
<q-item-section side>
|
|
110
|
+
<q-icon name="open_in_new" size="xs" />
|
|
111
|
+
</q-item-section>
|
|
112
|
+
</q-item>
|
|
113
|
+
</q-list>
|
|
114
|
+
</q-btn-dropdown>
|
|
115
|
+
</div>
|
|
116
|
+
</template>
|
|
117
|
+
|
|
118
|
+
<style lang="sass">
|
|
119
|
+
.d-page-bar
|
|
120
|
+
display: flex
|
|
121
|
+
justify-content: space-between
|
|
122
|
+
align-items: center
|
|
123
|
+
margin-bottom: 4px
|
|
124
|
+
|
|
125
|
+
&__date
|
|
126
|
+
font-size: 0.8rem
|
|
127
|
+
opacity: 0.6
|
|
128
|
+
|
|
129
|
+
&__actions
|
|
130
|
+
font-size: 0.75rem
|
|
131
|
+
|
|
132
|
+
body.body--dark
|
|
133
|
+
.d-page-bar__date
|
|
134
|
+
color: rgba(255, 255, 255, 0.7)
|
|
135
|
+
</style>
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
<script setup>
|
|
2
2
|
// defineProps is a compiler macro in <script setup>, no import needed
|
|
3
|
+
import { computed } from 'vue'
|
|
3
4
|
|
|
4
5
|
const props = defineProps({
|
|
5
6
|
message: {
|
|
@@ -7,13 +8,54 @@ const props = defineProps({
|
|
|
7
8
|
default: ''
|
|
8
9
|
}
|
|
9
10
|
})
|
|
11
|
+
|
|
12
|
+
const alertTypes = {
|
|
13
|
+
note: {
|
|
14
|
+
label: 'Note',
|
|
15
|
+
icon: 'info'
|
|
16
|
+
},
|
|
17
|
+
tip: {
|
|
18
|
+
label: 'Tip',
|
|
19
|
+
icon: 'lightbulb'
|
|
20
|
+
},
|
|
21
|
+
important: {
|
|
22
|
+
label: 'Important',
|
|
23
|
+
icon: 'priority_high'
|
|
24
|
+
},
|
|
25
|
+
warning: {
|
|
26
|
+
label: 'Warning',
|
|
27
|
+
icon: 'warning'
|
|
28
|
+
},
|
|
29
|
+
caution: {
|
|
30
|
+
label: 'Caution',
|
|
31
|
+
icon: 'error'
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const normalizedMessage = computed(() => {
|
|
36
|
+
const value = String(props.message || '').toLowerCase()
|
|
37
|
+
return alertTypes[value] ? value : ''
|
|
38
|
+
})
|
|
39
|
+
|
|
40
|
+
const alertLabel = computed(() => {
|
|
41
|
+
return normalizedMessage.value
|
|
42
|
+
? alertTypes[normalizedMessage.value].label
|
|
43
|
+
: ''
|
|
44
|
+
})
|
|
45
|
+
|
|
46
|
+
const alertIcon = computed(() => {
|
|
47
|
+
return normalizedMessage.value
|
|
48
|
+
? alertTypes[normalizedMessage.value].icon
|
|
49
|
+
: ''
|
|
50
|
+
})
|
|
10
51
|
</script>
|
|
11
52
|
|
|
12
53
|
<template>
|
|
13
|
-
<blockquote>
|
|
14
|
-
<
|
|
15
|
-
|
|
16
|
-
|
|
54
|
+
<blockquote :class="['d-page-blockquote', normalizedMessage ? `d-page-blockquote--${normalizedMessage}` : null]">
|
|
55
|
+
<p v-if="alertLabel" class="d-page-blockquote__heading">
|
|
56
|
+
<q-icon :name="alertIcon" size="18px" />
|
|
57
|
+
<strong>{{ alertLabel }}</strong>
|
|
58
|
+
</p>
|
|
17
59
|
<slot />
|
|
18
60
|
</blockquote>
|
|
19
61
|
</template>
|
|
@@ -12,6 +12,7 @@ import DH5 from './DH5.vue'
|
|
|
12
12
|
import DH6 from './DH6.vue'
|
|
13
13
|
import DPageSourceCode from './DPageSourceCode.vue'
|
|
14
14
|
import DMermaidDiagram from './DMermaidDiagram.vue'
|
|
15
|
+
import DPageBlockquote from './DPageBlockquote.vue'
|
|
15
16
|
|
|
16
17
|
const props = defineProps({
|
|
17
18
|
id: {
|
|
@@ -23,6 +24,31 @@ const props = defineProps({
|
|
|
23
24
|
const store = useStore()
|
|
24
25
|
const { t } = useI18n()
|
|
25
26
|
|
|
27
|
+
const ALERT_MESSAGE_TYPES = new Set([
|
|
28
|
+
'note',
|
|
29
|
+
'tip',
|
|
30
|
+
'important',
|
|
31
|
+
'warning',
|
|
32
|
+
'caution'
|
|
33
|
+
])
|
|
34
|
+
|
|
35
|
+
const parseAlertMarker = (rawContent = '') => {
|
|
36
|
+
const match = String(rawContent).trim().match(/^\[!\s*([A-Za-z]+)\s*\]\s*(.*)$/s)
|
|
37
|
+
if (!match) {
|
|
38
|
+
return null
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
const type = match[1].toLowerCase()
|
|
42
|
+
if (!ALERT_MESSAGE_TYPES.has(type)) {
|
|
43
|
+
return null
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
return {
|
|
47
|
+
type,
|
|
48
|
+
content: (match[2] || '').trim()
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
26
52
|
const tokenized = computed(() => {
|
|
27
53
|
const absolute = store.state.i18n.absolute
|
|
28
54
|
|
|
@@ -43,14 +69,126 @@ const tokenized = computed(() => {
|
|
|
43
69
|
allowedAttributes: ['filename']
|
|
44
70
|
})
|
|
45
71
|
|
|
46
|
-
|
|
72
|
+
// Use a plain inline renderer to avoid markdown-it-attrs edge cases
|
|
73
|
+
// when rendering isolated inline fragments.
|
|
74
|
+
const MarkdownInline = new MarkdownIt()
|
|
75
|
+
|
|
76
|
+
const markdownEnv = {}
|
|
77
|
+
|
|
78
|
+
const parsed = Markdown.parse(normalizedSource, markdownEnv)
|
|
47
79
|
|
|
48
80
|
// @ map
|
|
49
81
|
const tokens = []
|
|
50
82
|
let level = 0
|
|
51
83
|
let tag = ''
|
|
52
84
|
const children = []
|
|
85
|
+
|
|
86
|
+
const blockquote = {
|
|
87
|
+
depth: 0,
|
|
88
|
+
content: '',
|
|
89
|
+
alertType: '',
|
|
90
|
+
firstInline: true
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
const resetBlockquote = () => {
|
|
94
|
+
blockquote.content = ''
|
|
95
|
+
blockquote.alertType = ''
|
|
96
|
+
blockquote.firstInline = true
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
const flushBlockquote = () => {
|
|
100
|
+
const content = blockquote.content
|
|
101
|
+
.replace(/<p>\s*<\/p>/g, '')
|
|
102
|
+
.trim()
|
|
103
|
+
|
|
104
|
+
tokens.push({
|
|
105
|
+
tag: 'blockquote',
|
|
106
|
+
content,
|
|
107
|
+
alertType: blockquote.alertType
|
|
108
|
+
})
|
|
109
|
+
|
|
110
|
+
resetBlockquote()
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
const appendBlockquoteTag = (element, open) => {
|
|
114
|
+
if (!element.tag || element.tag === 'blockquote') {
|
|
115
|
+
return
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
blockquote.content += open
|
|
119
|
+
? `<${element.tag}>`
|
|
120
|
+
: `</${element.tag}>`
|
|
121
|
+
}
|
|
122
|
+
|
|
53
123
|
parsed.forEach((element) => {
|
|
124
|
+
if (element.type === 'blockquote_open') {
|
|
125
|
+
if (blockquote.depth === 0) {
|
|
126
|
+
resetBlockquote()
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
blockquote.depth++
|
|
130
|
+
return
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
if (element.type === 'blockquote_close' && blockquote.depth > 0) {
|
|
134
|
+
blockquote.depth--
|
|
135
|
+
|
|
136
|
+
if (blockquote.depth === 0) {
|
|
137
|
+
flushBlockquote()
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
return
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
if (blockquote.depth > 0) {
|
|
144
|
+
if (element.type === 'inline') {
|
|
145
|
+
const rawInline = element.content
|
|
146
|
+
|
|
147
|
+
if (blockquote.firstInline) {
|
|
148
|
+
blockquote.firstInline = false
|
|
149
|
+
|
|
150
|
+
const alert = parseAlertMarker(rawInline)
|
|
151
|
+
if (alert !== null) {
|
|
152
|
+
blockquote.alertType = alert.type
|
|
153
|
+
|
|
154
|
+
if (alert.content !== '') {
|
|
155
|
+
blockquote.content += MarkdownInline.renderInline(alert.content, markdownEnv)
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
return
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
blockquote.content += MarkdownInline.renderInline(rawInline, markdownEnv)
|
|
163
|
+
return
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
if (element.type === 'fence') {
|
|
167
|
+
const info = String(element.info || '').split(' ')
|
|
168
|
+
const language = info[0] || ''
|
|
169
|
+
const escaped = String(element.content)
|
|
170
|
+
.replace(/&/g, '&')
|
|
171
|
+
.replace(/</g, '<')
|
|
172
|
+
.replace(/>/g, '>')
|
|
173
|
+
|
|
174
|
+
const languageClass = language ? ` class="language-${language}"` : ''
|
|
175
|
+
blockquote.content += `<pre><code${languageClass}>${escaped}</code></pre>`
|
|
176
|
+
return
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
if (element.type.endsWith('_open')) {
|
|
180
|
+
appendBlockquoteTag(element, true)
|
|
181
|
+
return
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
if (element.type.endsWith('_close')) {
|
|
185
|
+
appendBlockquoteTag(element, false)
|
|
186
|
+
return
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
return
|
|
190
|
+
}
|
|
191
|
+
|
|
54
192
|
switch (element.type) {
|
|
55
193
|
case 'bullet_list_open':
|
|
56
194
|
case 'ordered_list_open':
|
|
@@ -60,7 +198,7 @@ const tokenized = computed(() => {
|
|
|
60
198
|
|
|
61
199
|
// Render
|
|
62
200
|
if (element.type === 'inline') {
|
|
63
|
-
element.content =
|
|
201
|
+
element.content = MarkdownInline.renderInline(element.content, markdownEnv)
|
|
64
202
|
}
|
|
65
203
|
|
|
66
204
|
if (level === 0) {
|
|
@@ -236,6 +374,13 @@ const tokenized = computed(() => {
|
|
|
236
374
|
v-html="token.content"
|
|
237
375
|
></p>
|
|
238
376
|
|
|
377
|
+
<d-page-blockquote
|
|
378
|
+
v-else-if="token.tag === 'blockquote'"
|
|
379
|
+
:message="token.alertType"
|
|
380
|
+
>
|
|
381
|
+
<div v-html="token.content"></div>
|
|
382
|
+
</d-page-blockquote>
|
|
383
|
+
|
|
239
384
|
<d-page-source-code
|
|
240
385
|
v-else-if="token.tag === 'code'"
|
|
241
386
|
:index="id + index"
|
|
@@ -3,6 +3,7 @@ import { computed } from 'vue'
|
|
|
3
3
|
import { useRoute } from 'vue-router'
|
|
4
4
|
// components
|
|
5
5
|
import DPage from "./DPage.vue";
|
|
6
|
+
import DPageBar from "./DPageBar.vue";
|
|
6
7
|
import DH1 from "./DH1.vue";
|
|
7
8
|
import DPageSection from "./DPageSection.vue";
|
|
8
9
|
|
|
@@ -23,6 +24,8 @@ const id = computed(() => {
|
|
|
23
24
|
<template>
|
|
24
25
|
<d-page>
|
|
25
26
|
<header>
|
|
27
|
+
<d-page-bar />
|
|
28
|
+
<hr />
|
|
26
29
|
<d-h1 :id="0" />
|
|
27
30
|
</header>
|
|
28
31
|
|
package/src/css/app.sass
CHANGED
|
@@ -81,7 +81,48 @@ body.body--dark
|
|
|
81
81
|
color: #3da6f3
|
|
82
82
|
border-bottom: 1px dotted #1b4a6c
|
|
83
83
|
|
|
84
|
-
&.overview
|
|
84
|
+
&.overview,
|
|
85
|
+
&.showcase
|
|
86
|
+
blockquote
|
|
87
|
+
border-left-color: #3d444d
|
|
88
|
+
background-color: #161b22 !important
|
|
89
|
+
|
|
90
|
+
.d-page-blockquote
|
|
91
|
+
&--note
|
|
92
|
+
border-left-color: #58a6ff
|
|
93
|
+
background-color: rgba(56, 139, 253, 0.18) !important
|
|
94
|
+
|
|
95
|
+
.d-page-blockquote__heading
|
|
96
|
+
color: #58a6ff
|
|
97
|
+
|
|
98
|
+
&--tip
|
|
99
|
+
border-left-color: #3fb950
|
|
100
|
+
background-color: rgba(63, 185, 80, 0.18) !important
|
|
101
|
+
|
|
102
|
+
.d-page-blockquote__heading
|
|
103
|
+
color: #3fb950
|
|
104
|
+
|
|
105
|
+
&--important
|
|
106
|
+
border-left-color: #bc8cff
|
|
107
|
+
background-color: rgba(188, 140, 255, 0.2) !important
|
|
108
|
+
|
|
109
|
+
.d-page-blockquote__heading
|
|
110
|
+
color: #bc8cff
|
|
111
|
+
|
|
112
|
+
&--warning
|
|
113
|
+
border-left-color: #d29922
|
|
114
|
+
background-color: rgba(210, 153, 34, 0.2) !important
|
|
115
|
+
|
|
116
|
+
.d-page-blockquote__heading
|
|
117
|
+
color: #d29922
|
|
118
|
+
|
|
119
|
+
&--caution
|
|
120
|
+
border-left-color: #ff7b72
|
|
121
|
+
background-color: rgba(248, 81, 73, 0.2) !important
|
|
122
|
+
|
|
123
|
+
.d-page-blockquote__heading
|
|
124
|
+
color: #ff7b72
|
|
125
|
+
|
|
85
126
|
table
|
|
86
127
|
border-color: #3f3f3f
|
|
87
128
|
box-shadow: 1px 2px 2px 1px rgba(0, 0, 0, 0.45)
|
|
@@ -154,14 +195,68 @@ body.body--dark
|
|
|
154
195
|
padding: 0 2px
|
|
155
196
|
transition: all 0.3s ease
|
|
156
197
|
|
|
157
|
-
&.overview
|
|
198
|
+
&.overview,
|
|
199
|
+
&.showcase
|
|
158
200
|
blockquote
|
|
159
|
-
margin:
|
|
160
|
-
padding: 0
|
|
201
|
+
margin: 1.5em 0
|
|
202
|
+
padding: 0.85em 1.1em
|
|
203
|
+
border-left: 4px solid #d0d7de
|
|
204
|
+
border-radius: 0 6px 6px 0
|
|
205
|
+
background-color: #f6f8fa !important
|
|
161
206
|
p
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
207
|
+
margin: 0.65em 0
|
|
208
|
+
letter-spacing: normal
|
|
209
|
+
|
|
210
|
+
p:first-child
|
|
211
|
+
margin-top: 0
|
|
212
|
+
|
|
213
|
+
p:last-child
|
|
214
|
+
margin-bottom: 0
|
|
215
|
+
|
|
216
|
+
.d-page-blockquote
|
|
217
|
+
&__heading
|
|
218
|
+
display: flex
|
|
219
|
+
align-items: center
|
|
220
|
+
gap: 0.35rem
|
|
221
|
+
margin: 0 0 0.6rem 0
|
|
222
|
+
|
|
223
|
+
strong
|
|
224
|
+
font-weight: 700
|
|
225
|
+
|
|
226
|
+
&--note
|
|
227
|
+
border-left-color: #0969da
|
|
228
|
+
background-color: rgba(9, 105, 218, 0.12) !important
|
|
229
|
+
|
|
230
|
+
.d-page-blockquote__heading
|
|
231
|
+
color: #0969da
|
|
232
|
+
|
|
233
|
+
&--tip
|
|
234
|
+
border-left-color: #1a7f37
|
|
235
|
+
background-color: rgba(26, 127, 55, 0.12) !important
|
|
236
|
+
|
|
237
|
+
.d-page-blockquote__heading
|
|
238
|
+
color: #1a7f37
|
|
239
|
+
|
|
240
|
+
&--important
|
|
241
|
+
border-left-color: #8250df
|
|
242
|
+
background-color: rgba(130, 80, 223, 0.12) !important
|
|
243
|
+
|
|
244
|
+
.d-page-blockquote__heading
|
|
245
|
+
color: #8250df
|
|
246
|
+
|
|
247
|
+
&--warning
|
|
248
|
+
border-left-color: #9a6700
|
|
249
|
+
background-color: rgba(154, 103, 0, 0.14) !important
|
|
250
|
+
|
|
251
|
+
.d-page-blockquote__heading
|
|
252
|
+
color: #9a6700
|
|
253
|
+
|
|
254
|
+
&--caution
|
|
255
|
+
border-left-color: #cf222e
|
|
256
|
+
background-color: rgba(207, 34, 46, 0.14) !important
|
|
257
|
+
|
|
258
|
+
.d-page-blockquote__heading
|
|
259
|
+
color: #cf222e
|
|
165
260
|
img
|
|
166
261
|
border: 0
|
|
167
262
|
max-width: 100%
|
|
@@ -30,7 +30,13 @@
|
|
|
30
30
|
nav: {
|
|
31
31
|
prev: 'Previous page',
|
|
32
32
|
next: 'Next page'
|
|
33
|
-
}
|
|
33
|
+
},
|
|
34
|
+
lastUpdated: 'Last updated',
|
|
35
|
+
copyPage: 'Copy page',
|
|
36
|
+
copyPageCaption: 'Copy page as Markdown for LLMs',
|
|
37
|
+
copied: 'Copied!',
|
|
38
|
+
viewAsMarkdown: 'View as Markdown',
|
|
39
|
+
viewAsMarkdownCaption: 'View this page as plain text'
|
|
34
40
|
},
|
|
35
41
|
|
|
36
42
|
menu: {
|
|
@@ -29,7 +29,13 @@
|
|
|
29
29
|
nav: {
|
|
30
30
|
prev: 'Página anterior',
|
|
31
31
|
next: 'Próxima página'
|
|
32
|
-
}
|
|
32
|
+
},
|
|
33
|
+
lastUpdated: 'Última atualização',
|
|
34
|
+
copyPage: 'Copiar página',
|
|
35
|
+
copyPageCaption: 'Copiar página como Markdown para LLMs',
|
|
36
|
+
copied: 'Copiado!',
|
|
37
|
+
viewAsMarkdown: 'Ver como Markdown',
|
|
38
|
+
viewAsMarkdownCaption: 'Ver esta página como texto simples'
|
|
33
39
|
},
|
|
34
40
|
|
|
35
41
|
menu: {
|
package/src/i18n/tags.hjson
CHANGED
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
"/guide/configuration": "config branding logo name version language links github docsector.config.js",
|
|
5
5
|
"/guide/pages-and-routing": "pages routes routing registry menu navigation path type status subpages",
|
|
6
6
|
"/guide/i18n-and-markdown": "i18n internationalization language locale hjson markdown content translation",
|
|
7
|
+
"/guide/alerts-and-blockquotes": "alerts blockquotes github note tip important warning caution markdown quote admonition",
|
|
7
8
|
"/guide/theming": "theme dark light mode color css sass variables styling",
|
|
8
9
|
"/guide/deployment": "deploy hosting production build static nginx netlify vercel github pages",
|
|
9
10
|
"/guide/plugins": "plugins extensions addons customize",
|
|
@@ -25,6 +26,7 @@
|
|
|
25
26
|
"/guide/configuration": "config branding logo nome versão idioma links github docsector.config.js",
|
|
26
27
|
"/guide/pages-and-routing": "páginas rotas roteamento registro menu navegação caminho tipo status subpages",
|
|
27
28
|
"/guide/i18n-and-markdown": "i18n internacionalização idioma locale hjson markdown conteúdo tradução",
|
|
29
|
+
"/guide/alerts-and-blockquotes": "alertas blockquotes github note tip important warning caution markdown citação admonition",
|
|
28
30
|
"/guide/theming": "tema escuro claro modo cor css sass variáveis estilização",
|
|
29
31
|
"/guide/deployment": "deploy hospedagem produção build estático nginx netlify vercel github pages",
|
|
30
32
|
"/guide/plugins": "plugins extensões complementos customizar",
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
# Alerts and Blockquotes
|
|
2
|
+
|
|
3
|
+
Docsector supports GitHub-style alert blockquotes and regular blockquotes.
|
|
4
|
+
|
|
5
|
+
## GitHub alert syntax
|
|
6
|
+
|
|
7
|
+
Use this syntax in Markdown:
|
|
8
|
+
|
|
9
|
+
```markdown
|
|
10
|
+
> [!CAUTION]
|
|
11
|
+
> NOTICE OF BREAKING CHANGE.
|
|
12
|
+
>
|
|
13
|
+
> As of 7.0.0, multiple breaking changes were introduced.
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
Supported alert types:
|
|
17
|
+
|
|
18
|
+
- `NOTE`
|
|
19
|
+
- `TIP`
|
|
20
|
+
- `IMPORTANT`
|
|
21
|
+
- `WARNING`
|
|
22
|
+
- `CAUTION`
|
|
23
|
+
|
|
24
|
+
## Alert examples
|
|
25
|
+
|
|
26
|
+
### Note
|
|
27
|
+
|
|
28
|
+
> [!NOTE]
|
|
29
|
+
> This is extra context that helps readers understand the current section.
|
|
30
|
+
|
|
31
|
+
### Tip
|
|
32
|
+
|
|
33
|
+
> [!TIP]
|
|
34
|
+
> You can keep your examples short and focused to improve readability.
|
|
35
|
+
|
|
36
|
+
### Important
|
|
37
|
+
|
|
38
|
+
> [!IMPORTANT]
|
|
39
|
+
> This migration changes defaults and must be reviewed before deployment.
|
|
40
|
+
|
|
41
|
+
### Warning
|
|
42
|
+
|
|
43
|
+
> [!WARNING]
|
|
44
|
+
> This action may interrupt running workers in production.
|
|
45
|
+
|
|
46
|
+
### Caution
|
|
47
|
+
|
|
48
|
+
> [!CAUTION]
|
|
49
|
+
> Back up your environment before applying this update.
|
|
50
|
+
>
|
|
51
|
+
> See `docs/migration.md` for the complete checklist.
|
|
52
|
+
|
|
53
|
+
## Regular blockquote
|
|
54
|
+
|
|
55
|
+
If no `[!TYPE]` marker is present, blockquotes render as regular notes:
|
|
56
|
+
|
|
57
|
+
> This is a regular blockquote.
|
|
58
|
+
>
|
|
59
|
+
> It still supports **bold text**, [links](https://github.com/docsector/docsector-reader), and `inline code`.
|
|
60
|
+
|
|
61
|
+
## Notes
|
|
62
|
+
|
|
63
|
+
- Alert markers are case-insensitive (`[!note]` also works).
|
|
64
|
+
- Unknown markers are treated as regular blockquotes.
|
|
65
|
+
- Alert and regular blockquotes both work in light and dark mode.
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
# Alertas e Blockquotes
|
|
2
|
+
|
|
3
|
+
O Docsector suporta blockquotes no estilo de alertas do GitHub e blockquotes comuns.
|
|
4
|
+
|
|
5
|
+
## Sintaxe de alerta do GitHub
|
|
6
|
+
|
|
7
|
+
Use esta sintaxe no Markdown:
|
|
8
|
+
|
|
9
|
+
```markdown
|
|
10
|
+
> [!CAUTION]
|
|
11
|
+
> AVISO DE MUDANCA QUEBRANDO COMPATIBILIDADE.
|
|
12
|
+
>
|
|
13
|
+
> A partir da versao 7.0.0, varias breaking changes foram introduzidas.
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
Tipos de alerta suportados:
|
|
17
|
+
|
|
18
|
+
- `NOTE`
|
|
19
|
+
- `TIP`
|
|
20
|
+
- `IMPORTANT`
|
|
21
|
+
- `WARNING`
|
|
22
|
+
- `CAUTION`
|
|
23
|
+
|
|
24
|
+
## Exemplos de alerta
|
|
25
|
+
|
|
26
|
+
### Note
|
|
27
|
+
|
|
28
|
+
> [!NOTE]
|
|
29
|
+
> Este e um contexto adicional que ajuda o leitor a entender a secao atual.
|
|
30
|
+
|
|
31
|
+
### Tip
|
|
32
|
+
|
|
33
|
+
> [!TIP]
|
|
34
|
+
> Voce pode manter os exemplos curtos e focados para melhorar a legibilidade.
|
|
35
|
+
|
|
36
|
+
### Important
|
|
37
|
+
|
|
38
|
+
> [!IMPORTANT]
|
|
39
|
+
> Esta migracao altera defaults e deve ser revisada antes do deploy.
|
|
40
|
+
|
|
41
|
+
### Warning
|
|
42
|
+
|
|
43
|
+
> [!WARNING]
|
|
44
|
+
> Esta acao pode interromper workers em execucao em producao.
|
|
45
|
+
|
|
46
|
+
### Caution
|
|
47
|
+
|
|
48
|
+
> [!CAUTION]
|
|
49
|
+
> Faça backup do ambiente antes de aplicar esta atualizacao.
|
|
50
|
+
>
|
|
51
|
+
> Veja `docs/migration.md` para o checklist completo.
|
|
52
|
+
|
|
53
|
+
## Blockquote comum
|
|
54
|
+
|
|
55
|
+
Se nao houver marcador `[!TYPE]`, o blockquote sera renderizado como blockquote comum:
|
|
56
|
+
|
|
57
|
+
> Este e um blockquote comum.
|
|
58
|
+
>
|
|
59
|
+
> Ele continua suportando **texto em negrito**, [links](https://github.com/docsector/docsector-reader) e `inline code`.
|
|
60
|
+
|
|
61
|
+
## Observacoes
|
|
62
|
+
|
|
63
|
+
- Marcadores de alerta sao case-insensitive (`[!note]` tambem funciona).
|
|
64
|
+
- Marcadores desconhecidos sao tratados como blockquote comum.
|
|
65
|
+
- Alertas e blockquotes comuns funcionam no modo claro e escuro.
|
|
@@ -61,6 +61,20 @@ You can render Mermaid diagrams using fenced blocks with the `mermaid` language
|
|
|
61
61
|
```
|
|
62
62
|
```mermaid
|
|
63
63
|
flowchart TD
|
|
64
|
+
|
|
65
|
+
### GitHub Alerts
|
|
66
|
+
|
|
67
|
+
Docsector also supports GitHub-style alert blockquotes:
|
|
68
|
+
|
|
69
|
+
```markdown
|
|
70
|
+
> [!IMPORTANT]
|
|
71
|
+
> The original repository was archived.
|
|
72
|
+
>
|
|
73
|
+
> Continue development in the maintained repository.
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
Supported types are `NOTE`, `TIP`, `IMPORTANT`, `WARNING`, and `CAUTION`.
|
|
77
|
+
Regular blockquotes (without `[!TYPE]`) continue to work as normal.
|
|
64
78
|
A[Start] --> B[End]
|
|
65
79
|
```
|
|
66
80
|
```
|
|
@@ -65,6 +65,20 @@ flowchart TD
|
|
|
65
65
|
```
|
|
66
66
|
```
|
|
67
67
|
|
|
68
|
+
### Alertas do GitHub
|
|
69
|
+
|
|
70
|
+
O Docsector tambem suporta blockquotes de alerta no estilo do GitHub:
|
|
71
|
+
|
|
72
|
+
```markdown
|
|
73
|
+
> [!IMPORTANT]
|
|
74
|
+
> O repositorio original foi arquivado.
|
|
75
|
+
>
|
|
76
|
+
> Continue o desenvolvimento no repositorio mantido.
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
Os tipos suportados sao `NOTE`, `TIP`, `IMPORTANT`, `WARNING` e `CAUTION`.
|
|
80
|
+
Blockquotes comuns (sem `[!TYPE]`) continuam funcionando normalmente.
|
|
81
|
+
|
|
68
82
|
### Atributos Customizados
|
|
69
83
|
|
|
70
84
|
O plugin `markdown-it-attrs` permite atributos customizados usando sintaxe `:attr;`:
|
package/src/pages/index.js
CHANGED
|
@@ -114,6 +114,28 @@ export default {
|
|
|
114
114
|
}
|
|
115
115
|
},
|
|
116
116
|
|
|
117
|
+
'/alerts-and-blockquotes': {
|
|
118
|
+
config: {
|
|
119
|
+
icon: 'notification_important',
|
|
120
|
+
status: 'done',
|
|
121
|
+
meta: {
|
|
122
|
+
description: {
|
|
123
|
+
'en-US': 'Alerts & Blockquotes — Documentation of Docsector Reader',
|
|
124
|
+
'pt-BR': 'Alertas & Blockquotes — Documentacao do Docsector Reader'
|
|
125
|
+
}
|
|
126
|
+
},
|
|
127
|
+
type: 'guide',
|
|
128
|
+
menu: {},
|
|
129
|
+
subpages: {
|
|
130
|
+
showcase: false
|
|
131
|
+
}
|
|
132
|
+
},
|
|
133
|
+
data: {
|
|
134
|
+
'en-US': { title: 'Alerts & Blockquotes' },
|
|
135
|
+
'pt-BR': { title: 'Alertas & Blockquotes' }
|
|
136
|
+
}
|
|
137
|
+
},
|
|
138
|
+
|
|
117
139
|
'/theming': {
|
|
118
140
|
config: {
|
|
119
141
|
icon: 'palette',
|
|
@@ -1,12 +1,15 @@
|
|
|
1
1
|
## Overview
|
|
2
2
|
|
|
3
|
-
`DPageBlockquote` renders **styled blockquotes** with semantic categorization. It
|
|
3
|
+
`DPageBlockquote` renders **styled blockquotes** with semantic categorization. It now powers both:
|
|
4
|
+
|
|
5
|
+
- GitHub-style alert blockquotes from Markdown (`> [!TYPE]`)
|
|
6
|
+
- Regular blockquotes (`> ...`) without an alert marker
|
|
4
7
|
|
|
5
8
|
## Props
|
|
6
9
|
|
|
7
10
|
| Prop | Type | Default | Description |
|
|
8
11
|
|------|------|---------|-------------|
|
|
9
|
-
| `message` | `String` | `''` | Type of
|
|
12
|
+
| `message` | `String` | `''` | Type of alert: `'note'`, `'tip'`, `'important'`, `'warning'`, or `'caution'` |
|
|
10
13
|
|
|
11
14
|
## Slot
|
|
12
15
|
|
|
@@ -16,29 +19,48 @@ The default slot receives the blockquote content.
|
|
|
16
19
|
|
|
17
20
|
| Type | Label | Purpose |
|
|
18
21
|
|------|-------|---------|
|
|
22
|
+
| `note` | **Note** | Additional context and references |
|
|
23
|
+
| `tip` | **Tip** | Practical recommendation or best practice |
|
|
19
24
|
| `important` | **Important** | Critical information the reader must know |
|
|
20
25
|
| `warning` | **Warning** | Potential pitfalls or breaking changes |
|
|
21
|
-
| `
|
|
26
|
+
| `caution` | **Caution** | High-risk action that deserves extra care |
|
|
22
27
|
| (empty) | *(none)* | Generic blockquote with no label |
|
|
23
28
|
|
|
24
29
|
## Usage
|
|
25
30
|
|
|
26
|
-
|
|
31
|
+
GitHub alert syntax in Markdown:
|
|
32
|
+
|
|
33
|
+
```markdown
|
|
34
|
+
> [!WARNING]
|
|
35
|
+
> This operation may interrupt workers.
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
Regular blockquote syntax in Markdown:
|
|
39
|
+
|
|
40
|
+
```markdown
|
|
41
|
+
> This is a regular blockquote.
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
You can also use the component directly:
|
|
27
45
|
|
|
28
46
|
```html
|
|
29
|
-
<d-page-blockquote message="
|
|
30
|
-
<p>This is
|
|
47
|
+
<d-page-blockquote message="note">
|
|
48
|
+
<p>This is additional context.</p>
|
|
49
|
+
</d-page-blockquote>
|
|
50
|
+
|
|
51
|
+
<d-page-blockquote message="tip">
|
|
52
|
+
<p>This is a practical recommendation.</p>
|
|
31
53
|
</d-page-blockquote>
|
|
32
54
|
|
|
33
55
|
<d-page-blockquote message="warning">
|
|
34
56
|
<p>Be careful with this operation!</p>
|
|
35
57
|
</d-page-blockquote>
|
|
36
58
|
|
|
37
|
-
<d-page-blockquote message="
|
|
38
|
-
<p>This is
|
|
59
|
+
<d-page-blockquote message="caution">
|
|
60
|
+
<p>This is a high-risk warning.</p>
|
|
39
61
|
</d-page-blockquote>
|
|
40
62
|
```
|
|
41
63
|
|
|
42
64
|
## Styling
|
|
43
65
|
|
|
44
|
-
The component renders a standard `<blockquote>` element
|
|
66
|
+
The component renders a standard `<blockquote>` element with alert-specific classes when a `message` is provided. Appearance is controlled in global `app.sass`, including dark/light mode variants for each alert type.
|
|
@@ -1,12 +1,15 @@
|
|
|
1
1
|
## Visão Geral
|
|
2
2
|
|
|
3
|
-
`DPageBlockquote` renderiza **blockquotes estilizados** com categorização semântica.
|
|
3
|
+
`DPageBlockquote` renderiza **blockquotes estilizados** com categorização semântica. Agora ele atende tanto:
|
|
4
|
+
|
|
5
|
+
- Alertas no estilo GitHub vindos do Markdown (`> [!TYPE]`)
|
|
6
|
+
- Blockquotes comuns (`> ...`) sem marcador de alerta
|
|
4
7
|
|
|
5
8
|
## Props
|
|
6
9
|
|
|
7
10
|
| Prop | Tipo | Padrão | Descrição |
|
|
8
11
|
|------|------|--------|-----------|
|
|
9
|
-
| `message` | `String` | `''` | Tipo de
|
|
12
|
+
| `message` | `String` | `''` | Tipo de alerta: `'note'`, `'tip'`, `'important'`, `'warning'` ou `'caution'` |
|
|
10
13
|
|
|
11
14
|
## Slot
|
|
12
15
|
|
|
@@ -16,29 +19,48 @@ O slot padrão recebe o conteúdo do blockquote.
|
|
|
16
19
|
|
|
17
20
|
| Tipo | Label | Propósito |
|
|
18
21
|
|------|-------|-----------|
|
|
22
|
+
| `note` | **Note** | Contexto adicional e referências |
|
|
23
|
+
| `tip` | **Tip** | Recomendação prática ou boa prática |
|
|
19
24
|
| `important` | **Important** | Informação crítica que o leitor precisa saber |
|
|
20
25
|
| `warning` | **Warning** | Armadilhas potenciais ou breaking changes |
|
|
21
|
-
| `
|
|
26
|
+
| `caution` | **Caution** | Ação de alto risco que exige cuidado extra |
|
|
22
27
|
| (vazio) | *(nenhum)* | Blockquote genérico sem label |
|
|
23
28
|
|
|
24
29
|
## Uso
|
|
25
30
|
|
|
26
|
-
|
|
31
|
+
Sintaxe de alerta GitHub no Markdown:
|
|
32
|
+
|
|
33
|
+
```markdown
|
|
34
|
+
> [!WARNING]
|
|
35
|
+
> Esta operação pode interromper workers.
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
Sintaxe de blockquote comum no Markdown:
|
|
39
|
+
|
|
40
|
+
```markdown
|
|
41
|
+
> Este é um blockquote comum.
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
Você também pode usar o componente diretamente:
|
|
27
45
|
|
|
28
46
|
```html
|
|
29
|
-
<d-page-blockquote message="
|
|
30
|
-
<p>
|
|
47
|
+
<d-page-blockquote message="note">
|
|
48
|
+
<p>Este é um contexto adicional.</p>
|
|
49
|
+
</d-page-blockquote>
|
|
50
|
+
|
|
51
|
+
<d-page-blockquote message="tip">
|
|
52
|
+
<p>Esta é uma recomendação prática.</p>
|
|
31
53
|
</d-page-blockquote>
|
|
32
54
|
|
|
33
55
|
<d-page-blockquote message="warning">
|
|
34
56
|
<p>Tenha cuidado com esta operação!</p>
|
|
35
57
|
</d-page-blockquote>
|
|
36
58
|
|
|
37
|
-
<d-page-blockquote message="
|
|
38
|
-
<p>
|
|
59
|
+
<d-page-blockquote message="caution">
|
|
60
|
+
<p>Este é um aviso de alto risco.</p>
|
|
39
61
|
</d-page-blockquote>
|
|
40
62
|
```
|
|
41
63
|
|
|
42
64
|
## Estilização
|
|
43
65
|
|
|
44
|
-
O componente renderiza um elemento `<blockquote>` padrão
|
|
66
|
+
O componente renderiza um elemento `<blockquote>` padrão com classes específicas quando `message` é informado. A aparência é controlada no `app.sass` global, incluindo variações para modo claro/escuro por tipo de alerta.
|
|
@@ -1,27 +1,34 @@
|
|
|
1
1
|
## Showcase
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Examples using GitHub alert syntax:
|
|
4
4
|
|
|
5
|
-
##
|
|
5
|
+
## Note
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
> [!NOTE]
|
|
8
|
+
> You can provide additional context and references in this block.
|
|
8
9
|
|
|
9
|
-
|
|
10
|
+
## Tip
|
|
10
11
|
|
|
11
|
-
|
|
12
|
+
> [!TIP]
|
|
13
|
+
> Keep examples short and focused so readers can execute them quickly.
|
|
12
14
|
|
|
13
|
-
|
|
15
|
+
## Important
|
|
14
16
|
|
|
15
|
-
>
|
|
17
|
+
> [!IMPORTANT]
|
|
18
|
+
> This migration changes defaults and should be validated before deploy.
|
|
16
19
|
|
|
17
|
-
##
|
|
20
|
+
## Warning
|
|
21
|
+
|
|
22
|
+
> [!WARNING]
|
|
23
|
+
> This action can interrupt running workers.
|
|
18
24
|
|
|
19
|
-
|
|
25
|
+
## Caution
|
|
20
26
|
|
|
21
|
-
>
|
|
27
|
+
> [!CAUTION]
|
|
28
|
+
> Back up your environment before changing low-level server settings.
|
|
22
29
|
|
|
23
30
|
## Generic
|
|
24
31
|
|
|
25
|
-
|
|
32
|
+
Regular blockquote without alert marker:
|
|
26
33
|
|
|
27
|
-
> This is a standard blockquote with no
|
|
34
|
+
> This is a standard blockquote with no alert marker.
|
|
@@ -1,27 +1,34 @@
|
|
|
1
1
|
## Demonstração
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Exemplos usando sintaxe de alerta do GitHub:
|
|
4
4
|
|
|
5
|
-
##
|
|
5
|
+
## Note
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
> [!NOTE]
|
|
8
|
+
> Voce pode adicionar contexto adicional e referencias neste bloco.
|
|
8
9
|
|
|
9
|
-
|
|
10
|
+
## Tip
|
|
10
11
|
|
|
11
|
-
|
|
12
|
+
> [!TIP]
|
|
13
|
+
> Mantenha exemplos curtos e focados para facilitar a execucao.
|
|
12
14
|
|
|
13
|
-
|
|
15
|
+
## Important
|
|
14
16
|
|
|
15
|
-
>
|
|
17
|
+
> [!IMPORTANT]
|
|
18
|
+
> Esta migracao altera defaults e deve ser validada antes do deploy.
|
|
16
19
|
|
|
17
|
-
##
|
|
20
|
+
## Warning
|
|
21
|
+
|
|
22
|
+
> [!WARNING]
|
|
23
|
+
> Esta acao pode interromper workers em execucao.
|
|
18
24
|
|
|
19
|
-
|
|
25
|
+
## Caution
|
|
20
26
|
|
|
21
|
-
>
|
|
27
|
+
> [!CAUTION]
|
|
28
|
+
> Faça backup do ambiente antes de alterar configuracoes de baixo nivel do servidor.
|
|
22
29
|
|
|
23
30
|
## Genérico
|
|
24
31
|
|
|
25
|
-
|
|
32
|
+
Blockquote comum sem marcador de alerta:
|
|
26
33
|
|
|
27
|
-
> Este
|
|
34
|
+
> Este e um blockquote padrao sem marcador de alerta.
|
package/src/quasar.factory.js
CHANGED
|
@@ -23,7 +23,8 @@
|
|
|
23
23
|
* @param {Function} [options.extendViteConf] - Additional Vite config extension
|
|
24
24
|
*/
|
|
25
25
|
|
|
26
|
-
import { readFileSync, existsSync, rmSync, mkdirSync, writeFileSync } from 'fs'
|
|
26
|
+
import { readFileSync, existsSync, rmSync, mkdirSync, writeFileSync, readdirSync } from 'fs'
|
|
27
|
+
import { execSync } from 'child_process'
|
|
27
28
|
import { createHash } from 'crypto'
|
|
28
29
|
import { resolve } from 'path'
|
|
29
30
|
import { pathToFileURL } from 'url'
|
|
@@ -231,6 +232,193 @@ function createPrerenderMetaPlugin (projectRoot) {
|
|
|
231
232
|
}
|
|
232
233
|
}
|
|
233
234
|
|
|
235
|
+
/**
|
|
236
|
+
* Create a Vite plugin that collects git last-commit dates for all Markdown
|
|
237
|
+
* files under src/pages/ and exposes them as a virtual module.
|
|
238
|
+
*
|
|
239
|
+
* Consuming components can `import gitDates from 'virtual:docsector-git-dates'`
|
|
240
|
+
* to get an object mapping relative page keys to ISO date strings.
|
|
241
|
+
*
|
|
242
|
+
* Keys use the pattern: `<type>/<path>.<subpage>.<locale>.md`
|
|
243
|
+
* e.g. `manual/Bootgly/about/what.overview.en-US.md`
|
|
244
|
+
*/
|
|
245
|
+
function createGitDatesPlugin (projectRoot) {
|
|
246
|
+
const virtualId = 'virtual:docsector-git-dates'
|
|
247
|
+
const resolvedId = '\0' + virtualId
|
|
248
|
+
let dates = {}
|
|
249
|
+
|
|
250
|
+
function collectDates () {
|
|
251
|
+
dates = {}
|
|
252
|
+
const pagesDir = resolve(projectRoot, 'src', 'pages')
|
|
253
|
+
if (!existsSync(pagesDir)) return
|
|
254
|
+
|
|
255
|
+
const walkDir = (dir) => {
|
|
256
|
+
const entries = readdirSync(dir, { withFileTypes: true })
|
|
257
|
+
for (const entry of entries) {
|
|
258
|
+
const fullPath = resolve(dir, entry.name)
|
|
259
|
+
if (entry.isDirectory()) {
|
|
260
|
+
walkDir(fullPath)
|
|
261
|
+
} else if (entry.name.endsWith('.md')) {
|
|
262
|
+
try {
|
|
263
|
+
const date = execSync(
|
|
264
|
+
`git log -1 --format=%cI -- "${fullPath}"`,
|
|
265
|
+
{ cwd: projectRoot, encoding: 'utf-8', stdio: ['pipe', 'pipe', 'pipe'] }
|
|
266
|
+
).trim()
|
|
267
|
+
if (date) {
|
|
268
|
+
// Key relative to src/pages/, e.g. "manual/Bootgly/about/what.overview.en-US.md"
|
|
269
|
+
const relKey = fullPath.slice(pagesDir.length + 1)
|
|
270
|
+
dates[relKey] = date
|
|
271
|
+
}
|
|
272
|
+
} catch {
|
|
273
|
+
// git not available or file untracked — skip
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
walkDir(pagesDir)
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
return {
|
|
283
|
+
name: 'docsector-git-dates',
|
|
284
|
+
buildStart () {
|
|
285
|
+
collectDates()
|
|
286
|
+
},
|
|
287
|
+
resolveId (id) {
|
|
288
|
+
if (id === virtualId) return resolvedId
|
|
289
|
+
},
|
|
290
|
+
load (id) {
|
|
291
|
+
if (id === resolvedId) {
|
|
292
|
+
return `export default ${JSON.stringify(dates)}`
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
/**
|
|
299
|
+
* Create a Vite plugin that serves raw Markdown content for `.md` suffixed URLs.
|
|
300
|
+
*
|
|
301
|
+
* In **dev mode**, intercepts requests like `/manual/Bootgly/about/what/overview.md`
|
|
302
|
+
* and serves the corresponding `src/pages/manual/Bootgly/about/what.overview.<lang>.md`
|
|
303
|
+
* file as `text/plain; charset=utf-8`.
|
|
304
|
+
*
|
|
305
|
+
* In **production build** (`closeBundle`), generates static `.md` files in `dist/spa/`
|
|
306
|
+
* for each page/subpage so that the `.md` URLs resolve to actual files on any static host.
|
|
307
|
+
*
|
|
308
|
+
* The language served is determined by the `?lang=` query parameter, falling back to the
|
|
309
|
+
* `defaultLanguage` from `docsector.config.js`.
|
|
310
|
+
*/
|
|
311
|
+
function createMarkdownEndpointPlugin (projectRoot) {
|
|
312
|
+
const pagesDir = resolve(projectRoot, 'src', 'pages')
|
|
313
|
+
|
|
314
|
+
function resolveMarkdownFile (urlPath, lang) {
|
|
315
|
+
// URL: /manual/Bootgly/about/what/overview.md
|
|
316
|
+
// Strip leading slash and trailing .md
|
|
317
|
+
const clean = urlPath.replace(/^\//, '').replace(/\.md$/, '')
|
|
318
|
+
// Split into segments: ['manual', 'Bootgly', 'about', 'what', 'overview']
|
|
319
|
+
const segments = clean.split('/')
|
|
320
|
+
if (segments.length < 2) return null
|
|
321
|
+
|
|
322
|
+
// Last segment is the subpage (overview, showcase, vs)
|
|
323
|
+
const subpage = segments.pop()
|
|
324
|
+
// Remaining segments form the type + path: 'manual/Bootgly/about/what'
|
|
325
|
+
const basePath = segments.join('/')
|
|
326
|
+
|
|
327
|
+
// File: src/pages/manual/Bootgly/about/what.overview.en-US.md
|
|
328
|
+
const filePath = resolve(pagesDir, `${basePath}.${subpage}.${lang}.md`)
|
|
329
|
+
if (existsSync(filePath)) return filePath
|
|
330
|
+
|
|
331
|
+
return null
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
return {
|
|
335
|
+
name: 'docsector-markdown-endpoint',
|
|
336
|
+
|
|
337
|
+
configureServer (server) {
|
|
338
|
+
// Read default language from config
|
|
339
|
+
let defaultLang = 'en-US'
|
|
340
|
+
try {
|
|
341
|
+
const configPath = resolve(projectRoot, 'docsector.config.js')
|
|
342
|
+
if (existsSync(configPath)) {
|
|
343
|
+
// Dynamic import in dev — we read it synchronously via a simple approach
|
|
344
|
+
const configContent = readFileSync(configPath, 'utf-8')
|
|
345
|
+
const match = configContent.match(/defaultLanguage\s*:\s*['"]([^'"]+)['"]/)
|
|
346
|
+
if (match) defaultLang = match[1]
|
|
347
|
+
}
|
|
348
|
+
} catch { /* use fallback */ }
|
|
349
|
+
|
|
350
|
+
server.middlewares.use((req, res, next) => {
|
|
351
|
+
const url = new URL(req.url, 'http://localhost')
|
|
352
|
+
if (!url.pathname.endsWith('.md')) return next()
|
|
353
|
+
|
|
354
|
+
const lang = url.searchParams.get('lang') || defaultLang
|
|
355
|
+
const file = resolveMarkdownFile(url.pathname, lang)
|
|
356
|
+
if (!file) return next()
|
|
357
|
+
|
|
358
|
+
const content = readFileSync(file, 'utf-8')
|
|
359
|
+
res.setHeader('Content-Type', 'text/plain; charset=utf-8')
|
|
360
|
+
res.end(content)
|
|
361
|
+
})
|
|
362
|
+
},
|
|
363
|
+
|
|
364
|
+
apply: 'serve'
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
/**
|
|
369
|
+
* Create a Vite plugin that generates static `.md` files at build time.
|
|
370
|
+
*
|
|
371
|
+
* Runs in the `closeBundle` hook alongside the prerender-meta plugin.
|
|
372
|
+
* For each page/subpage, copies the raw Markdown source into
|
|
373
|
+
* `dist/spa/<routePath>.md` so that `.md` URLs work on static hosts.
|
|
374
|
+
*/
|
|
375
|
+
function createMarkdownBuildPlugin (projectRoot) {
|
|
376
|
+
return {
|
|
377
|
+
name: 'docsector-markdown-build',
|
|
378
|
+
apply: 'build',
|
|
379
|
+
async closeBundle () {
|
|
380
|
+
const distDir = resolve(projectRoot, 'dist', 'spa')
|
|
381
|
+
if (!existsSync(distDir)) return
|
|
382
|
+
|
|
383
|
+
const pagesDir = resolve(projectRoot, 'src', 'pages')
|
|
384
|
+
const configUrl = pathToFileURL(resolve(projectRoot, 'docsector.config.js')).href
|
|
385
|
+
const pagesUrl = pathToFileURL(resolve(projectRoot, 'src', 'pages', 'index.js')).href
|
|
386
|
+
|
|
387
|
+
const { default: config } = await import(configUrl)
|
|
388
|
+
const { default: pages } = await import(pagesUrl)
|
|
389
|
+
|
|
390
|
+
const defaultLang = config.defaultLanguage || config.languages?.[0]?.value || 'en-US'
|
|
391
|
+
let count = 0
|
|
392
|
+
|
|
393
|
+
for (const [pagePath, page] of Object.entries(pages)) {
|
|
394
|
+
if (page.config === null) continue
|
|
395
|
+
if (page.config.status === 'empty') continue
|
|
396
|
+
|
|
397
|
+
const type = page.config.type ?? 'manual'
|
|
398
|
+
|
|
399
|
+
const subpages = ['overview']
|
|
400
|
+
if (page.config.subpages?.showcase) subpages.push('showcase')
|
|
401
|
+
if (page.config.subpages?.vs) subpages.push('vs')
|
|
402
|
+
|
|
403
|
+
for (const subpage of subpages) {
|
|
404
|
+
const srcFile = resolve(pagesDir, `${type}${pagePath}.${subpage}.${defaultLang}.md`)
|
|
405
|
+
if (!existsSync(srcFile)) continue
|
|
406
|
+
|
|
407
|
+
const routePath = `${type}${pagePath}/${subpage}`
|
|
408
|
+
const destFile = resolve(distDir, `${routePath}.md`)
|
|
409
|
+
const destDir = resolve(destFile, '..')
|
|
410
|
+
|
|
411
|
+
mkdirSync(destDir, { recursive: true })
|
|
412
|
+
writeFileSync(destFile, readFileSync(srcFile, 'utf-8'))
|
|
413
|
+
count++
|
|
414
|
+
}
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
console.log(`\x1b[36m[docsector]\x1b[0m Generated ${count} static .md files`)
|
|
418
|
+
}
|
|
419
|
+
}
|
|
420
|
+
}
|
|
421
|
+
|
|
234
422
|
/**
|
|
235
423
|
* Create a complete Quasar configuration for a docsector-reader consumer project.
|
|
236
424
|
*
|
|
@@ -301,6 +489,9 @@ export function createQuasarConfig (options = {}) {
|
|
|
301
489
|
|
|
302
490
|
vitePlugins: [
|
|
303
491
|
createHjsonPlugin(),
|
|
492
|
+
createGitDatesPlugin(projectRoot),
|
|
493
|
+
createMarkdownEndpointPlugin(projectRoot),
|
|
494
|
+
createMarkdownBuildPlugin(projectRoot),
|
|
304
495
|
createPagesWatchPlugin(projectRoot),
|
|
305
496
|
createPrerenderMetaPlugin(projectRoot),
|
|
306
497
|
...vitePlugins
|