feat(server): enhance frontmatter parsing for skill descriptions
Some checks failed
Deploy skills-market-server / deploy (push) Has been cancelled
Some checks failed
Deploy skills-market-server / deploy (push) Has been cancelled
- Integrated a new utility function `parseFrontmatterScalarKey` to streamline the extraction of the description from skill files. - Improved the logic for handling frontmatter, ensuring more robust parsing and trimming of description values.
This commit is contained in:
parent
33a59df4ae
commit
de65426d64
77
lib/frontmatter-scalar.js
Normal file
77
lib/frontmatter-scalar.js
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
/**
|
||||||
|
* 从 frontmatter 文本里读一个顶层标量(整块 metadata 已由调用方从 --- … --- 切好)。
|
||||||
|
* 多行块(description: > / |):从下一行起收到「下一个顶层键」或 metadata 结束为止。
|
||||||
|
*/
|
||||||
|
|
||||||
|
function escapeRegExp(s) {
|
||||||
|
return s.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 下一行若是顶层键 `foo:`(行首无缩进),则当前块结束。 */
|
||||||
|
function isTopLevelKeyLine(line) {
|
||||||
|
const t = line.trimStart()
|
||||||
|
if (!t || t.startsWith('#')) return false
|
||||||
|
return /^[A-Za-z_][\w-]*\s*:\s/.test(t)
|
||||||
|
}
|
||||||
|
|
||||||
|
function minIndentOfNonEmpty(lines) {
|
||||||
|
let min = Infinity
|
||||||
|
for (const l of lines) {
|
||||||
|
if (!l.trim()) continue
|
||||||
|
const n = l.match(/^(\s*)/)[1].length
|
||||||
|
if (n < min) min = n
|
||||||
|
}
|
||||||
|
return min === Infinity ? 0 : min
|
||||||
|
}
|
||||||
|
|
||||||
|
function dedent(lines) {
|
||||||
|
const min = minIndentOfNonEmpty(lines)
|
||||||
|
return lines.map((l) => (l.length === 0 ? '' : l.slice(min)))
|
||||||
|
}
|
||||||
|
|
||||||
|
function parseFrontmatterScalarKey(fmBlock, key) {
|
||||||
|
if (!fmBlock || !key) return null
|
||||||
|
const lines = fmBlock.split(/\r?\n/)
|
||||||
|
const keyRe = new RegExp(`^${escapeRegExp(key)}:\\s*(.*)$`)
|
||||||
|
|
||||||
|
for (let i = 0; i < lines.length; i++) {
|
||||||
|
const m = lines[i].match(keyRe)
|
||||||
|
if (!m) continue
|
||||||
|
|
||||||
|
let after = m[1].replace(/\s+$/, '')
|
||||||
|
const blockHead = after.match(/^([>|])([-+]?)\s*(.*)$/)
|
||||||
|
|
||||||
|
if (blockHead) {
|
||||||
|
const mode = blockHead[1]
|
||||||
|
const sameLine = (blockHead[3] || '').trimEnd()
|
||||||
|
const raw = []
|
||||||
|
if (sameLine) raw.push(sameLine)
|
||||||
|
|
||||||
|
for (let j = i + 1; j < lines.length; j++) {
|
||||||
|
const line = lines[j]
|
||||||
|
if (line.length > 0 && !/^\s/.test(line) && isTopLevelKeyLine(line)) break
|
||||||
|
raw.push(line)
|
||||||
|
}
|
||||||
|
|
||||||
|
const body = dedent(raw)
|
||||||
|
if (mode === '>') {
|
||||||
|
return body
|
||||||
|
.map((l) => l.trim())
|
||||||
|
.filter(Boolean)
|
||||||
|
.join(' ')
|
||||||
|
.trim()
|
||||||
|
}
|
||||||
|
return body.join('\n').trim()
|
||||||
|
}
|
||||||
|
|
||||||
|
const t = after.trim()
|
||||||
|
if ((t.startsWith('"') && t.endsWith('"')) || (t.startsWith("'") && t.endsWith("'"))) {
|
||||||
|
return t.slice(1, -1)
|
||||||
|
}
|
||||||
|
if (t) return t.replace(/^["']|["']$/g, '')
|
||||||
|
return ''
|
||||||
|
}
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = { parseFrontmatterScalarKey }
|
||||||
@ -3,6 +3,7 @@ const express = require('express')
|
|||||||
const cors = require('cors')
|
const cors = require('cors')
|
||||||
const path = require('path')
|
const path = require('path')
|
||||||
const { MongoClient, ObjectId } = require('mongodb')
|
const { MongoClient, ObjectId } = require('mongodb')
|
||||||
|
const { parseFrontmatterScalarKey } = require('./lib/frontmatter-scalar')
|
||||||
const { createAuthRoutes } = require('./routes/auth')
|
const { createAuthRoutes } = require('./routes/auth')
|
||||||
|
|
||||||
const app = express()
|
const app = express()
|
||||||
@ -200,9 +201,9 @@ function extractDescription(files) {
|
|||||||
const content = skillFile.content
|
const content = skillFile.content
|
||||||
const fmMatch = content.match(/^---\s*\r?\n([\s\S]*?)\r?\n---/)
|
const fmMatch = content.match(/^---\s*\r?\n([\s\S]*?)\r?\n---/)
|
||||||
if (fmMatch) {
|
if (fmMatch) {
|
||||||
const descMatch = fmMatch[1].match(/^description:\s*(.+)$/m)
|
const fromFm = parseFrontmatterScalarKey(fmMatch[1], 'description')
|
||||||
if (descMatch) {
|
if (fromFm != null && String(fromFm).trim() !== '') {
|
||||||
return descMatch[1].trim().replace(/^["']|["']$/g, '')
|
return String(fromFm).trim()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user