Ворклог по задаче "Переосмыслить структуру сайта, доработать ее и пересобрать контент"

16 июл. 2026 г., 02:24:51

Добавил очень прикольную ИИ-функцию :-) - редактирование контента с внутренними кросс-ссылками. Главная фишка - передача агенту всего набора внутренних ссылок и он автоматически в контенте заменяет простой текст на ссылки. Но тут ИИ как обычно не совсем корректно отрабатывает и местами придумывает несуществующие ссылки. Но это лечится - просто добавил построцессинг контента и он чистит контент от битых внутренних ссылок (благо контент весь в маркдауне и это делается сильно проще, чем с чистым HTML).

import { unified } from 'unified'
import remarkParse from 'remark-parse'
import remarkMdx from 'remark-mdx'
import remarkStringify from 'remark-stringify'
import { visit } from 'unist-util-visit'
import type { Link, Text } from 'mdast'
import type { Parent } from 'unist'

export interface ConceptLink {
  uri: string
}

export interface InvalidLink {
  url: string
  position?: {
    start: { line: number; column: number }
    end: { line: number; column: number }
  }
}

export interface ValidateInternalLinksResult {
  invalidLinks: InvalidLink[]
}

function isInternalLink(url: string): boolean {
  return url.startsWith('/')
}

export function buildValidUrisSet(concepts: ConceptLink[]): Set<string> {
  return new Set(concepts.map((c) => c.uri))
}

export async function removeInvalidLinks(
  content: string,
  validUris: Set<string>,
): Promise<string> {
  const tree = unified().use(remarkParse).use(remarkMdx).parse(content)

  visit(tree, 'link', (node: Link, index, parent: Parent | undefined) => {
    if (!parent || index === undefined) {
      return
    }

    const url = node.url

    if (isInternalLink(url) && !validUris.has(url)) {
      if (process.env.NODE_ENV === 'development') {
        console.error('Invalid url', url)
      }

      const textNode: Text = {
        type: 'text',
        value: node.children
          .filter((child): child is Text => child.type === 'text')
          .map((child) => child.value)
          .join(''),
      }

      parent.children.splice(index, 1, textNode)
    }
  })

  const result = unified()
    .use(remarkStringify, {
      bullet: '-',
      emphasis: '_',
      strong: '*',
    })
    .stringify(tree)

  return result
}

Вот для примера обработанная статья: https://vietnamguru.ru/content/reference/aktualniy-spisok-provintsiy-vetnama

Она изначально была написана без единой внутренней ссылки. А ссылок там должно быть много, так как это список провинций (и местами еще города). Самому вручную ее редактировать довольно муторно (надо же не только ссылки найти у себя на сайте, надо еще проверить существует ли у нас такая провинция в каталоге). Кстати, тут попутный плюс - сразу получили список отсутствующих провинций - сразу понятно что надо добавить в каталог. А так получился вот такой контент: