Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions docs/.vuepress/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { registerComponentsPlugin } from '@vuepress/plugin-register-components';
import { getDirname, path } from '@vuepress/utils';
import { balancerTheme } from '../../theme/';
import { navbar, sidebar } from './configs/index.js';
import { llmsTxtPlugin } from './plugins/llmsTxtPlugin.js';

const isProd = process.env.NODE_ENV === 'production';

Expand Down Expand Up @@ -72,6 +73,7 @@ export default defineUserConfig({

// use plugins
plugins: [
llmsTxtPlugin(),
registerComponentsPlugin({
componentsDir: path.resolve(__dirname, './components'),
}),
Expand Down
107 changes: 107 additions & 0 deletions docs/.vuepress/plugins/llmsTxtPlugin.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
import type { Plugin } from '@vuepress/core'
import { fs, path } from '@vuepress/utils'
import { globby } from 'globby'
import { unified } from 'unified'
import remarkParse from 'remark-parse'
import remarkStringify from 'remark-stringify'
import remarkFrontmatter from 'remark-frontmatter'
import { visit } from 'unist-util-visit'
import { toMarkdown } from 'mdast-util-to-markdown'
import type { Heading } from 'mdast'
import { directiveToMarkdown } from 'mdast-util-directive'
import remarkDirective from 'remark-directive'
import { gfmToMarkdown } from 'mdast-util-gfm'

/**
* Generates the following files and serves them at the appropriate paths:
* - llms.txt
* - llms-full.txt
* - .md version of each docs page like https://docs.balancer.fi/concepts/core-concepts/introduction.md
*/
export const llmsTxtPlugin = (): Plugin => ({
name: 'llms-txt-generator',

onGenerated: async (app) => {

const outDir = app.dir.dest()
const docsDir = app.dir.source()

const glob = `${docsDir}/**/*.md`
const files = await globby(glob);

const content = [`# Balancer V3`, '', '> Learn, integrate, and build on a programmable AMM', '']
const llmsTxtContent = [...content, '## Docs', ''];
const llmsFullTxtContent = content;

for (const file of files) {
let pagePath = `${file.replace(docsDir, '').replace(/\.[^.]*$/, '')}.md`
if (!pagePath) continue


const contents = await fs.readFile(file, 'utf-8');
const parser = unified().use(remarkParse).use(remarkFrontmatter).use(remarkDirective).use(remarkStringify)

// Abstract syntax tree from the contents of all the markdown files
const ast = parser.parse(contents)

// For links to pages served at /llms.txt
visit(ast, { type: 'heading', depth: 1 }, (n, i) => {
const node = n.children[0]
if (node.type !== 'text') return

const value = node.value
const [, title, subTitle] = value.match(/^([^\[\]]+)(?: \[([^\[\]]+)\])?$/) ?? []

// Look for a description: either use subtitle or first paragraph after heading
let found = false
let description = subTitle
if (!description)
visit(ast, { type: 'paragraph' }, (n, j) => {
if (found) return
if (j && i && j <= i) return

found = true
description = toMarkdown(n, {extensions: [directiveToMarkdown(), gfmToMarkdown()]})

// Remove container directive syntax ( only for llms.txt )
description = description.replace(/^.*\\:::.*(?:\n|$)/gm, '').replace(/\n+$/, '');
})

llmsTxtContent.push(`- [${title}](https://docs.balancer.fi${pagePath})${description ? `: ${description}` : ''}`)
})

// Adjust depth of headings to make sense given site title is H1
visit(
ast,
(n) => n.type === 'heading',
(n) => {
const node = n as Heading
if (node.depth === 1 || node.depth === 2 || node.depth === 3 || node.depth === 4)
node.depth = (node.depth + 1) as 2 | 3 | 4 | 5
},
)

// remove front matter
visit(ast, { type: 'yaml' }, (_, i, p) => {
if (!p) return
if (typeof i !== 'number') return
p.children.splice(i, 1)
})

const llmFriendlyMarkdown = toMarkdown(ast, {extensions: [directiveToMarkdown(), gfmToMarkdown()]})

// Serve the .md version of each page alongside the .html
const mdOutputPath = path.join(outDir, pagePath)
fs.writeFileSync(mdOutputPath, llmFriendlyMarkdown)

llmsFullTxtContent.push( llmFriendlyMarkdown, '')
}

const llmsTxt = llmsTxtContent.join('\n')
const llmsFullTxt = llmsFullTxtContent.join('\n')

fs.ensureDirSync(outDir)
fs.writeFileSync(path.resolve(outDir, 'llms.txt'), llmsTxt)
fs.writeFileSync(path.resolve(outDir, 'llms-full.txt'), llmsFullTxt)
},
})
2 changes: 1 addition & 1 deletion docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,4 +39,4 @@ features:
details: All things data
link: /data-and-analytics/README.md


---
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Need valid frontmatter to parse the abstract syntax tree properly

2 changes: 2 additions & 0 deletions docs/developer-reference/contracts/error-signatures.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ order: 4

# Error signatures

Catalogue for decoding custom error signatures into their associated error names

Comment on lines +7 to +8
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Short descriptions at top of each page are helpful for llms.txt file

| Error Name | Parameters | Error Signature |
| ------------------------------------ | ------------------------------------------------------------ | --------------- |
| AfterAddLiquidityHookFailed | | `0x1f11c6e8` |
Expand Down
1 change: 1 addition & 0 deletions docs/partner-onboarding/balancer-v2/point-programs.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ order: 7
# Setting Up a Partner Points Program Category on the Balancer UI

This guide will walk you through the process of setting up a category for your partner points program in the Balancer protocol. By following these steps, you'll be able to tag sets of pools in the Balancer API and frontend, allowing users to earn points for providing liquidity to specific pools.

:::info
All information provided herein is referencing how to make changes to the [metadata repository ](https://github.com/balancer/metadata/) to register a points program on the Balancer Zen UI.
:::
Expand Down
Loading