@docsector/docsector-reader 0.10.4 → 0.11.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/bin/docsector.js +1 -1
- package/package.json +1 -1
- package/src/components/DPage.vue +5 -0
- package/src/quasar.factory.js +133 -7
package/bin/docsector.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@docsector/docsector-reader",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.11.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",
|
package/src/components/DPage.vue
CHANGED
|
@@ -238,6 +238,10 @@ onBeforeUnmount(() => {
|
|
|
238
238
|
.content > div.scroll
|
|
239
239
|
min-height: calc(100vh - 86px)
|
|
240
240
|
|
|
241
|
+
.content > div.scroll > div.q-scrollarea__content
|
|
242
|
+
max-width: 100%
|
|
243
|
+
box-sizing: border-box
|
|
244
|
+
|
|
241
245
|
.content:not(.no-padding) > div.scroll > div.q-scrollarea__content
|
|
242
246
|
padding: 15px
|
|
243
247
|
|
|
@@ -245,6 +249,7 @@ onBeforeUnmount(() => {
|
|
|
245
249
|
min-height: calc(100vh - 86px) !important
|
|
246
250
|
|
|
247
251
|
#scroll-container
|
|
252
|
+
width: 100%
|
|
248
253
|
max-width: 1200px
|
|
249
254
|
margin: auto
|
|
250
255
|
|
package/src/quasar.factory.js
CHANGED
|
@@ -247,11 +247,115 @@ function createGitDatesPlugin (projectRoot) {
|
|
|
247
247
|
const resolvedId = '\0' + virtualId
|
|
248
248
|
let dates = {}
|
|
249
249
|
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
250
|
+
/**
|
|
251
|
+
* Try to unshallow the repository so `git log` returns real commit dates
|
|
252
|
+
* instead of the single clone-time date that shallow CI clones produce.
|
|
253
|
+
*/
|
|
254
|
+
function tryUnshallow () {
|
|
255
|
+
try {
|
|
256
|
+
const isShallow = execSync(
|
|
257
|
+
'git rev-parse --is-shallow-repository',
|
|
258
|
+
{ cwd: projectRoot, encoding: 'utf-8', stdio: ['pipe', 'pipe', 'pipe'] }
|
|
259
|
+
).trim()
|
|
260
|
+
|
|
261
|
+
if (isShallow === 'true') {
|
|
262
|
+
console.log('[docsector] Shallow repository detected — fetching full history…')
|
|
263
|
+
execSync('git fetch --unshallow', {
|
|
264
|
+
cwd: projectRoot,
|
|
265
|
+
encoding: 'utf-8',
|
|
266
|
+
stdio: ['pipe', 'pipe', 'pipe'],
|
|
267
|
+
timeout: 60_000
|
|
268
|
+
})
|
|
269
|
+
console.log('[docsector] Repository unshallowed successfully.')
|
|
270
|
+
return true
|
|
271
|
+
}
|
|
272
|
+
} catch {
|
|
273
|
+
console.warn('[docsector] Could not unshallow repository — will try GitHub API fallback.')
|
|
274
|
+
return false
|
|
275
|
+
}
|
|
276
|
+
return true // not shallow, full history available
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
/**
|
|
280
|
+
* Extract the GitHub `owner/repo` slug from the consumer's docsector.config.js.
|
|
281
|
+
* Looks for `github.editBaseUrl` (e.g. "https://github.com/bootgly/bootgly_docs/edit/…")
|
|
282
|
+
* or an explicit `github.repo` field (e.g. "bootgly/bootgly_docs").
|
|
283
|
+
*/
|
|
284
|
+
function getGitHubRepo () {
|
|
285
|
+
try {
|
|
286
|
+
const configPath = resolve(projectRoot, 'docsector.config.js')
|
|
287
|
+
if (!existsSync(configPath)) return null
|
|
288
|
+
|
|
289
|
+
const src = readFileSync(configPath, 'utf-8')
|
|
290
|
+
|
|
291
|
+
// Explicit repo field: repo: 'owner/repo'
|
|
292
|
+
const repoMatch = src.match(/repo\s*:\s*['"]([^'"]+)['"]/)
|
|
293
|
+
if (repoMatch) return repoMatch[1]
|
|
294
|
+
|
|
295
|
+
// Derive from editBaseUrl: https://github.com/<owner>/<repo>/edit/…
|
|
296
|
+
const urlMatch = src.match(/editBaseUrl\s*:\s*['"]https:\/\/github\.com\/([^/]+\/[^/]+)\//)
|
|
297
|
+
if (urlMatch) return urlMatch[1]
|
|
298
|
+
} catch { /* ignore */ }
|
|
299
|
+
return null
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
/**
|
|
303
|
+
* Fetch last-commit dates from the GitHub API for all .md files under src/pages/.
|
|
304
|
+
* Uses the unauthenticated commits endpoint (60 req/hr) or authenticated if
|
|
305
|
+
* GITHUB_TOKEN is set (5 000 req/hr).
|
|
306
|
+
*/
|
|
307
|
+
async function collectDatesFromGitHub (pagesDir, repo) {
|
|
308
|
+
console.log(`[docsector] Fetching file dates from GitHub API (${repo})…`)
|
|
309
|
+
|
|
310
|
+
const headers = { 'User-Agent': 'docsector-reader', Accept: 'application/vnd.github+json' }
|
|
311
|
+
const token = process.env.GITHUB_TOKEN
|
|
312
|
+
if (token) headers.Authorization = `Bearer ${token}`
|
|
313
|
+
|
|
314
|
+
const walkDir = (dir) => {
|
|
315
|
+
const entries = readdirSync(dir, { withFileTypes: true })
|
|
316
|
+
let files = []
|
|
317
|
+
for (const entry of entries) {
|
|
318
|
+
const fullPath = resolve(dir, entry.name)
|
|
319
|
+
if (entry.isDirectory()) {
|
|
320
|
+
files = files.concat(walkDir(fullPath))
|
|
321
|
+
} else if (entry.name.endsWith('.md')) {
|
|
322
|
+
files.push(fullPath)
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
return files
|
|
326
|
+
}
|
|
254
327
|
|
|
328
|
+
const files = walkDir(pagesDir)
|
|
329
|
+
let fetched = 0
|
|
330
|
+
|
|
331
|
+
for (const fullPath of files) {
|
|
332
|
+
const relKey = fullPath.slice(pagesDir.length + 1)
|
|
333
|
+
const apiPath = `src/pages/${relKey}`
|
|
334
|
+
const url = `https://api.github.com/repos/${repo}/commits?path=${encodeURIComponent(apiPath)}&per_page=1`
|
|
335
|
+
|
|
336
|
+
try {
|
|
337
|
+
const res = await fetch(url, { headers })
|
|
338
|
+
if (!res.ok) {
|
|
339
|
+
if (res.status === 403 || res.status === 429) {
|
|
340
|
+
console.warn('[docsector] GitHub API rate limit reached — stopping.')
|
|
341
|
+
break
|
|
342
|
+
}
|
|
343
|
+
continue
|
|
344
|
+
}
|
|
345
|
+
const commits = await res.json()
|
|
346
|
+
if (commits.length > 0 && commits[0].commit) {
|
|
347
|
+
dates[relKey] = commits[0].commit.committer.date
|
|
348
|
+
fetched++
|
|
349
|
+
}
|
|
350
|
+
} catch {
|
|
351
|
+
// Network error — skip this file
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
console.log(`[docsector] Fetched dates for ${fetched}/${files.length} files from GitHub API.`)
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
function collectDatesFromGit (pagesDir) {
|
|
255
359
|
const walkDir = (dir) => {
|
|
256
360
|
const entries = readdirSync(dir, { withFileTypes: true })
|
|
257
361
|
for (const entry of entries) {
|
|
@@ -265,7 +369,6 @@ function createGitDatesPlugin (projectRoot) {
|
|
|
265
369
|
{ cwd: projectRoot, encoding: 'utf-8', stdio: ['pipe', 'pipe', 'pipe'] }
|
|
266
370
|
).trim()
|
|
267
371
|
if (date) {
|
|
268
|
-
// Key relative to src/pages/, e.g. "manual/Bootgly/about/what.overview.en-US.md"
|
|
269
372
|
const relKey = fullPath.slice(pagesDir.length + 1)
|
|
270
373
|
dates[relKey] = date
|
|
271
374
|
}
|
|
@@ -279,10 +382,33 @@ function createGitDatesPlugin (projectRoot) {
|
|
|
279
382
|
walkDir(pagesDir)
|
|
280
383
|
}
|
|
281
384
|
|
|
385
|
+
async function collectDates () {
|
|
386
|
+
dates = {}
|
|
387
|
+
const pagesDir = resolve(projectRoot, 'src', 'pages')
|
|
388
|
+
if (!existsSync(pagesDir)) return
|
|
389
|
+
|
|
390
|
+
// 1. Try to unshallow so git log returns real dates
|
|
391
|
+
const hasFullHistory = tryUnshallow()
|
|
392
|
+
|
|
393
|
+
// 2. Collect dates from local git
|
|
394
|
+
collectDatesFromGit(pagesDir)
|
|
395
|
+
|
|
396
|
+
// 3. Check if all dates are the same (sign of shallow clone with no unshallow)
|
|
397
|
+
const uniqueDates = new Set(Object.values(dates))
|
|
398
|
+
if (uniqueDates.size <= 1 && Object.keys(dates).length > 1 && !hasFullHistory) {
|
|
399
|
+
// All files share the same date — likely shallow clone fallback
|
|
400
|
+
const repo = getGitHubRepo()
|
|
401
|
+
if (repo) {
|
|
402
|
+
dates = {}
|
|
403
|
+
await collectDatesFromGitHub(pagesDir, repo)
|
|
404
|
+
}
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
|
|
282
408
|
return {
|
|
283
409
|
name: 'docsector-git-dates',
|
|
284
|
-
buildStart () {
|
|
285
|
-
collectDates()
|
|
410
|
+
async buildStart () {
|
|
411
|
+
await collectDates()
|
|
286
412
|
},
|
|
287
413
|
resolveId (id) {
|
|
288
414
|
if (id === virtualId) return resolvedId
|