@docsector/docsector-reader 4.4.5 → 4.4.6
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/bin/docsector.js
CHANGED
|
@@ -24,7 +24,7 @@ const packageRoot = resolve(__dirname, '..')
|
|
|
24
24
|
const args = process.argv.slice(2)
|
|
25
25
|
const command = args[0]
|
|
26
26
|
|
|
27
|
-
const VERSION = '4.4.
|
|
27
|
+
const VERSION = '4.4.6'
|
|
28
28
|
const AUTHORING_SKILL_NAME = 'docsector-documentation-authoring'
|
|
29
29
|
const AUTHORING_SKILL_DESCRIPTION = 'Author Docsector documentation with Markdown, custom blocks, MCP, and WebMCP.'
|
|
30
30
|
const AUTHORING_SKILL_PUBLIC_PATH = `/.well-known/agent-skills/${AUTHORING_SKILL_NAME}/SKILL.md`
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@docsector/docsector-reader",
|
|
3
|
-
"version": "4.4.
|
|
3
|
+
"version": "4.4.6",
|
|
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",
|
|
@@ -1,10 +1,16 @@
|
|
|
1
1
|
<script setup>
|
|
2
|
-
import { ref, computed, watch } from 'vue'
|
|
2
|
+
import { ref, computed, watch, nextTick } from 'vue'
|
|
3
|
+
import { useRoute, useRouter } from 'vue-router'
|
|
3
4
|
import { useQuasar } from 'quasar'
|
|
4
|
-
import { useStore } from 'vuex'
|
|
5
5
|
import Prism from './code-block-highlighting'
|
|
6
|
+
import {
|
|
7
|
+
buildSourceCodeLineAnchorId,
|
|
8
|
+
resolveSourceCodeLineHref,
|
|
9
|
+
shouldHandleSourceCodeLineActivation
|
|
10
|
+
} from './source-code-anchor'
|
|
6
11
|
import { countRenderedCodeLines } from './source-code-lines'
|
|
7
12
|
import { looksLikeFileName, resolveFileIconUrl } from '../composables/useFileIcon'
|
|
13
|
+
import useNavigator from '../composables/useNavigator'
|
|
8
14
|
|
|
9
15
|
defineOptions({
|
|
10
16
|
name: 'DBlockSourceCode'
|
|
@@ -38,15 +44,17 @@ const props = defineProps({
|
|
|
38
44
|
})
|
|
39
45
|
|
|
40
46
|
const $q = useQuasar()
|
|
41
|
-
const
|
|
47
|
+
const route = useRoute()
|
|
48
|
+
const router = useRouter()
|
|
49
|
+
const { anchor: scrollToAnchor } = useNavigator()
|
|
42
50
|
|
|
43
51
|
const copyBtnDisabled = ref(false)
|
|
44
52
|
const copyBtnColor = ref(null)
|
|
45
53
|
const copyBtnIcon = ref('content_copy')
|
|
46
54
|
const codeRef = ref(null)
|
|
47
55
|
const activeTab = ref(0)
|
|
56
|
+
const lineAnchorTopOffset = 34
|
|
48
57
|
|
|
49
|
-
const href = computed(() => `${store.state.page.absolute}#${anchor.value}`)
|
|
50
58
|
const coloring = computed(() => $q.dark.isActive ? 'dark' : 'white')
|
|
51
59
|
const anchor = computed(() => printToLetter(props.index + 1))
|
|
52
60
|
|
|
@@ -155,6 +163,38 @@ function copyCode() {
|
|
|
155
163
|
}
|
|
156
164
|
}
|
|
157
165
|
|
|
166
|
+
function buildLineAnchorId(line) {
|
|
167
|
+
return buildSourceCodeLineAnchorId(anchor.value, line)
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
function buildLineHref(line) {
|
|
171
|
+
return resolveSourceCodeLineHref(router, route.path, route.query, buildLineAnchorId(line))
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
async function navigateToLineAnchor(event, line) {
|
|
175
|
+
if (!shouldHandleSourceCodeLineActivation(event)) {
|
|
176
|
+
return
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
const hash = `#${buildLineAnchorId(line)}`
|
|
180
|
+
|
|
181
|
+
event.preventDefault()
|
|
182
|
+
|
|
183
|
+
if (route.hash === hash) {
|
|
184
|
+
scrollToAnchor(hash, false)
|
|
185
|
+
return
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
await router.push({
|
|
189
|
+
path: route.path,
|
|
190
|
+
query: route.query,
|
|
191
|
+
hash
|
|
192
|
+
})
|
|
193
|
+
|
|
194
|
+
await nextTick()
|
|
195
|
+
scrollToAnchor(hash, false)
|
|
196
|
+
}
|
|
197
|
+
|
|
158
198
|
function printToLetter(number) {
|
|
159
199
|
const alphabet = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
|
|
160
200
|
let result = ''
|
|
@@ -245,9 +285,9 @@ function printToLetter(number) {
|
|
|
245
285
|
<div class="code" :class="coloring">
|
|
246
286
|
<div class="lines" v-if="lines && lines > 1">
|
|
247
287
|
<template v-for="(line, index) in lines" :key="index">
|
|
248
|
-
<a class="line" :href="
|
|
288
|
+
<a class="line" :href="buildLineHref(line)" @click="navigateToLineAnchor($event, line)">
|
|
249
289
|
<i class="fa fa-link" aria-hidden="true" data-hidden="true"></i>
|
|
250
|
-
<span :id="
|
|
290
|
+
<span :id="buildLineAnchorId(line)" :data-anchor-offset-top="lineAnchorTopOffset">{{ line }}</span>
|
|
251
291
|
</a>
|
|
252
292
|
</template>
|
|
253
293
|
</div>
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export function buildSourceCodeLineAnchorId(anchorPrefix, line) {
|
|
2
|
+
return `${anchorPrefix}${line}`
|
|
3
|
+
}
|
|
4
|
+
|
|
5
|
+
export function resolveSourceCodeLineHref(router, routePath, routeQuery, anchorId) {
|
|
6
|
+
return router.resolve({
|
|
7
|
+
path: routePath,
|
|
8
|
+
query: routeQuery,
|
|
9
|
+
hash: `#${anchorId}`
|
|
10
|
+
}).href
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export function shouldHandleSourceCodeLineActivation(event) {
|
|
14
|
+
return !(event.defaultPrevented || event.button !== 0 || event.altKey || event.ctrlKey || event.metaKey || event.shiftKey)
|
|
15
|
+
}
|
|
@@ -11,6 +11,62 @@ export default function useNavigator() {
|
|
|
11
11
|
const route = useRoute()
|
|
12
12
|
const selected = ref(null)
|
|
13
13
|
|
|
14
|
+
const normalizeScrollTarget = (target) => {
|
|
15
|
+
if (target === document.body || target === document.documentElement) {
|
|
16
|
+
return window
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
return target
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const getScrollTargetTop = (target) => {
|
|
23
|
+
if (target === window) {
|
|
24
|
+
return window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop || 0
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
return target?.scrollTop || 0
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
const getScrollTargetRectTop = (target) => {
|
|
31
|
+
if (target === window) {
|
|
32
|
+
return 0
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
return target?.getBoundingClientRect?.().top || 0
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
const getAnchorTopOffset = (anchorEl) => {
|
|
39
|
+
if (!(anchorEl instanceof HTMLElement)) {
|
|
40
|
+
return 0
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
const explicitOffset = Number.parseFloat(anchorEl.dataset.anchorOffsetTop || '')
|
|
44
|
+
|
|
45
|
+
if (Number.isFinite(explicitOffset)) {
|
|
46
|
+
return Math.max(0, explicitOffset)
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
return 0
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
const resolveAnchorScrollState = (anchorEl) => {
|
|
53
|
+
if (!(anchorEl instanceof HTMLElement)) {
|
|
54
|
+
return null
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
const pageScrollContainer = anchorEl.closest('.q-scrollarea__container')
|
|
58
|
+
const scrollTarget = normalizeScrollTarget(pageScrollContainer || scroll.getScrollTarget(anchorEl))
|
|
59
|
+
const anchorRect = anchorEl.getBoundingClientRect()
|
|
60
|
+
const scrollTop = getScrollTargetTop(scrollTarget)
|
|
61
|
+
const targetRectTop = getScrollTargetRectTop(scrollTarget)
|
|
62
|
+
const anchorTopOffset = getAnchorTopOffset(anchorEl)
|
|
63
|
+
|
|
64
|
+
return {
|
|
65
|
+
scrollTarget,
|
|
66
|
+
offsetTop: Math.max(0, ((anchorRect.top - targetRectTop) + scrollTop) - anchorTopOffset)
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
14
70
|
const normalizeDomAnchorId = (id) => {
|
|
15
71
|
if (id === null || id === undefined || id === false) {
|
|
16
72
|
return ''
|
|
@@ -62,10 +118,11 @@ export default function useNavigator() {
|
|
|
62
118
|
const Anchor = document.getElementById(anchorId)
|
|
63
119
|
|
|
64
120
|
if (Anchor !== null && typeof Anchor === 'object') {
|
|
65
|
-
const
|
|
66
|
-
const AnchorOffsetTop = Anchor.offsetTop
|
|
121
|
+
const scrollState = resolveAnchorScrollState(Anchor)
|
|
67
122
|
|
|
68
|
-
|
|
123
|
+
if (scrollState !== null) {
|
|
124
|
+
scroll.setVerticalScrollPosition(scrollState.scrollTarget, scrollState.offsetTop, 300)
|
|
125
|
+
}
|
|
69
126
|
|
|
70
127
|
setTimeout(() => {
|
|
71
128
|
store.commit('page/setScrolling', true)
|
|
@@ -98,7 +155,7 @@ export default function useNavigator() {
|
|
|
98
155
|
const Anchor = document.getElementById(domAnchorId)
|
|
99
156
|
|
|
100
157
|
if (Anchor !== null && typeof Anchor === 'object') {
|
|
101
|
-
return Anchor
|
|
158
|
+
return resolveAnchorScrollState(Anchor)?.offsetTop
|
|
102
159
|
}
|
|
103
160
|
|
|
104
161
|
return undefined
|