Files
docs/scripts/prepare-static-index.ts
S.Gromov 9a962f37b5
All checks were successful
CI/CD Pipeline / build (push) Successful in 43s
CI/CD Pipeline / docker (push) Successful in 1m18s
CI/CD Pipeline / deploy (push) Successful in 6s
feat: добавить skill для SLM Design
- добавлена сборка self-contained skill для Claude Code и opencode

- добавлен install-ready архив skill в public/slm-design/skill

- обновлена карточка SLM Design с меню действий открыть/скачать

- добавлен static fallback главной страницы из общего конфига

- подключены Mantine Menu и Phosphor Icons для действий карточки
2026-05-22 23:23:14 +03:00

136 lines
4.3 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import fs from 'node:fs'
import path from 'node:path'
import { docs, type DocAction, type DocActionCollection, type DocActionGroup } from '../src/config/docs.config'
const rootDir = path.resolve(import.meta.dirname, '..')
const indexPath = path.join(rootDir, 'index.html')
const startMarker = '<!-- STATIC_DOCS_START -->'
const endMarker = '<!-- STATIC_DOCS_END -->'
function escapeHtml(value: string) {
return value
.replaceAll('&', '&amp;')
.replaceAll('<', '&lt;')
.replaceAll('>', '&gt;')
.replaceAll('"', '&quot;')
}
function isActionGroup(action: DocAction | DocActionGroup): action is DocActionGroup {
return 'actions' in action
}
function splitActionCollection(collection: DocActionCollection | undefined) {
if (!collection?.length) return { actions: [], groups: [] }
if (isActionGroup(collection[0])) {
const groups = collection as DocActionGroup[]
return {
actions: [],
groups: groups.filter((group) => group.actions.length > 0),
}
}
return {
actions: collection as DocAction[],
groups: [],
}
}
function renderLink(action: DocAction, type: 'download' | 'open') {
const attrs = [
`href="${escapeHtml(action.href)}"`,
type === 'open' ? 'target="_blank"' : '',
type === 'open' ? 'rel="noopener noreferrer"' : '',
type === 'download' ? 'download' : '',
].filter(Boolean).join(' ')
return `<li><a ${attrs}>${escapeHtml(action.label)}</a></li>`
}
function renderActionList(actions: DocAction[], type: 'download' | 'open') {
return `<ul class="static-action-list">${actions.map((action) => renderLink(action, type)).join('')}</ul>`
}
function renderActionCollection(collection: DocActionCollection | undefined, title: string, type: 'download' | 'open') {
const { actions, groups } = splitActionCollection(collection)
if (actions.length === 0 && groups.length === 0) return ''
const content = groups.length > 0
? groups.map((group) => `
<li>
<span class="static-action-group-title">${escapeHtml(group.title)}</span>
${renderActionList(group.actions, type)}
</li>`).join('')
: actions.map((action) => renderLink(action, type)).join('')
return `
<li>
<span class="static-action-title">${title}</span>
<ul class="static-action-list static-action-list-nested">${content}
</ul>
</li>`
}
function renderDocLinks(title: string, links: DocAction[]) {
if (links.length === 0) return ''
return `
<li>
<span class="static-action-title">AI</span>
${renderActionList(links, 'open')}
</li>`
}
function renderDoc(doc: typeof docs[number]) {
const title = escapeHtml(doc.title)
const heading = doc.href ? `<a href="${escapeHtml(doc.href)}">${title}</a>` : title
const actionGroups = doc.actionGroups
const actions = [
renderActionCollection(actionGroups?.open, 'Открыть', 'open'),
renderActionCollection(actionGroups?.download, 'Скачать', 'download'),
doc.actionGroups ? '' : renderDocLinks(doc.title, doc.links),
].filter(Boolean).join('')
const actionBlock = actions ? `
<ul class="static-actions-list">${actions}
</ul>` : ''
return `
<li class="static-card">
<article>
<div class="static-meta">${escapeHtml(doc.label)} · ${escapeHtml(doc.status)}</div>
<h2>${heading}</h2>
<p>${escapeHtml(doc.description)}</p>${actionBlock}
</article>
</li>`
}
function renderStaticDocs() {
return `<section aria-labelledby="static-docs-title">
<h2 id="static-docs-title">Список документаций</h2>
<ul class="static-docs">${docs.map(renderDoc).join('')}
</ul>
</section>`
}
const indexHtml = fs.readFileSync(indexPath, 'utf8')
const startIndex = indexHtml.indexOf(startMarker)
const endIndex = indexHtml.indexOf(endMarker)
if (startIndex === -1 || endIndex === -1 || endIndex < startIndex) {
throw new Error(`Не найдены маркеры ${startMarker} / ${endMarker} в index.html`)
}
const nextIndexHtml = [
indexHtml.slice(0, startIndex + startMarker.length),
'\n ',
renderStaticDocs().replaceAll('\n', '\n '),
'\n ',
indexHtml.slice(endIndex),
].join('')
fs.writeFileSync(indexPath, nextIndexHtml, 'utf8')
console.log('Подготовлен static fallback в index.html')