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
1 change: 1 addition & 0 deletions packages/vitepress-plugin-moss/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ Never hard-code credentials in your config file.
# .env ← add to .gitignore, never commit
MOSS_PROJECT_ID=your_project_id
MOSS_PROJECT_KEY=your_api_key
MOSS_INDEX_NAME=my-docs
```

> **Note:** `projectKey` ends up embedded in the client-side JavaScript bundle. Treat it as you would an Algolia search-only API key — use a key scoped to read/query operations only.
Expand Down
1,185 changes: 559 additions & 626 deletions packages/vitepress-plugin-moss/Search.vue

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ export default defineConfig({
indexName: process.env.MOSS_INDEX_NAME || 'moss-sdk-docs',
} as any,
},
logo: '/moss-logo.png',

// https://vitepress.dev/reference/default-theme-config
nav: [
{ text: 'Moss Portal', link: 'https://usemoss.dev', target: '_blank', rel: 'noopener noreferrer' },
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
58 changes: 27 additions & 31 deletions packages/vitepress-plugin-moss/demo-site/scripts/index-docs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,13 @@ import path from 'node:path'
import fs from 'node:fs'
import { fileURLToPath } from 'node:url'

dotenv.config()

const __dirname = path.dirname(fileURLToPath(import.meta.url))

dotenv.config({ path: path.resolve(__dirname, '../../.env') })

const target = process.argv[2] ?? 'documentation'
const inspect = process.argv.includes('--inspect')
const root = path.resolve(__dirname, '..', target)
const tempFile = path.resolve(__dirname, '../.index-preview.json')

// Build all chunks from the markdown files
console.log(`Building index from: ${root}`)
Expand All @@ -38,31 +37,37 @@ const wordFiltered = allDocs.filter((doc: any) => {

// Filter out structural-only section headings that carry no semantic value
// (e.g. "Parameters", "Constructors", "Methods" are just navigation anchors)
// const STRUCTURAL_TITLES = new Set(['Parameters', 'Constructors', 'Methods', 'Properties', 'Type declaration'])
// const structuralFiltered = wordFiltered.filter((doc: any) => {
// const title: string = (doc.metadata?.title ?? '').trim().replace(/\u200b/g, '').trim()
// return !STRUCTURAL_TITLES.has(title)
// })
const STRUCTURAL_TITLES = new Set(['Parameters', 'Constructors', 'Methods', 'Properties', 'Type declaration'])
const structuralFiltered = wordFiltered.filter((doc: any) => {
const title: string = (doc.metadata?.title ?? '').trim().replace(/\u200b/g, '').trim()
return !STRUCTURAL_TITLES.has(title)
})

// Deduplicate: within the same page (groupId), keep only the first chunk per
// section title — repeated headings are redundant sub-sections of the same topic
// const seen = new Set<string>()
// const filtered = structuralFiltered.filter((doc: any) => {
// const key = `${doc.metadata?.groupId ?? ''}||${doc.metadata?.title ?? ''}`
// if (seen.has(key)) return false
// seen.add(key)
// return true
// })
const seen = new Set<string>()
const filtered = structuralFiltered.filter((doc: any) => {
const key = `${doc.metadata?.groupId ?? ''}||${doc.metadata?.title ?? ''}`
if (seen.has(key)) return false
seen.add(key)
return true
})

// console.log(`After filtering (>3 words): ${wordFiltered.length} chunks`)
// console.log(`After removing structural headings: ${structuralFiltered.length} chunks`)
// console.log(`After deduplicating by (page, section): ${filtered.length} chunks (removed ${allDocs.length - filtered.length} total)`)
console.log(`After filtering (>3 words): ${wordFiltered.length} chunks`)
console.log(`After removing structural headings: ${structuralFiltered.length} chunks`)
console.log(`After deduplicating by (page, section): ${filtered.length} chunks (removed ${allDocs.length - filtered.length} total)`)

const filtered = wordFiltered
console.log(`After filtering (>3 words): ${filtered.length} chunks (removed ${allDocs.length - filtered.length})`)
const projectId = process.env.MOSS_PROJECT_ID
const projectKey = process.env.MOSS_PROJECT_KEY
const indexName = process.env.MOSS_INDEX_NAME

if (!inspect && (!projectId || !projectKey || !indexName)) {
console.error('Missing env vars: MOSS_PROJECT_ID, MOSS_PROJECT_KEY, MOSS_INDEX_NAME')
process.exit(1)
}

// Write filtered chunks to temp file (used for inspect and upload)
fs.writeFileSync(tempFile, JSON.stringify(filtered, null, 2))
// fs.writeFileSync(tempFile, JSON.stringify(filtered, null, 2))

if (inspect) {
console.log('\nSample (first 3 chunks):')
Expand All @@ -71,17 +76,8 @@ if (inspect) {
process.exit(0)
}

const projectId = process.env.MOSS_PROJECT_ID
const projectKey = process.env.MOSS_PROJECT_KEY
const indexName = process.env.MOSS_INDEX_NAME

if (!projectId || !projectKey || !indexName) {
console.error('Missing env vars: MOSS_PROJECT_ID, MOSS_PROJECT_KEY, MOSS_INDEX_NAME')
process.exit(1)
}

console.log(`Uploading to index: ${indexName}`)
await createIndex(tempFile, { projectId, projectKey, indexName, modelName: 'moss-minilm' })
await createIndex(tempFile, { projectId, projectKey, indexName, modelName: 'moss-minilm', alpha: 0.2 })

// Clean up temp file
// fs.unlinkSync(tempFile)
Expand Down
36 changes: 30 additions & 6 deletions packages/vitepress-plugin-moss/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -79,8 +79,6 @@ export function mossIndexerPlugin(): Plugin {

// Only run for client build and only during production build
// NOTE: environment.name is used in newer Vite/VitePress
const environment = (this as any).environment

try {
debug('Starting Moss index sync...')

Expand All @@ -107,12 +105,38 @@ export function mossIndexerPlugin(): Plugin {
indexName
}

const { sync } = await import('@moss-tools/md-indexer')
await sync({
root: siteConfig.root, // VitePress root (where .vitepress/ lives); indexer reads srcDir from config
creds
const { buildJsonDocs, uploadDocuments } = await import('@moss-tools/md-indexer')

// Build chunks
const allDocs = await buildJsonDocs(siteConfig.root) as any[]
debug(`Built ${allDocs.length} chunks`)

// Filter: remove chunks with 3 or fewer words
const wordFiltered = allDocs.filter((doc: any) => {
const wordCount = doc.text?.trim().split(/\s+/).filter(Boolean).length ?? 0
return wordCount > 3
})

// Filter: remove structural-only section headings
const STRUCTURAL_TITLES = new Set(['Parameters', 'Constructors', 'Methods', 'Properties', 'Type declaration'])
const structuralFiltered = wordFiltered.filter((doc: any) => {
const title: string = (doc.metadata?.title ?? '').trim().replace(/\u200b/g, '').trim()
return !STRUCTURAL_TITLES.has(title)
})

// Deduplicate: keep only the first chunk per (groupId, title)
const seen = new Set<string>()
const filtered = structuralFiltered.filter((doc: any) => {
const key = `${doc.metadata?.groupId ?? ''}||${doc.metadata?.title ?? ''}`
if (seen.has(key)) return false
seen.add(key)
return true
})

debug(`After filtering: ${filtered.length} chunks (removed ${allDocs.length - filtered.length})`)

await uploadDocuments(filtered, { ...creds, modelName: 'moss-minilm' })

debug('✅ Moss index sync completed.')
} catch (error) {
const err = error as Error
Expand Down
3 changes: 3 additions & 0 deletions packages/vitepress-plugin-moss/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,9 @@
"dependencies": {
"@inferedge/moss": "^1.0.0-beta.7",
"@moss-tools/md-indexer": "^1.0.0-beta.3",
"@vueuse/core": "^14.2.1",
"@vueuse/integrations": "^14.2.1",
"focus-trap": "^8.0.1",
"obug": "^1.0.0"
},
"devDependencies": {
Expand Down
92 changes: 92 additions & 0 deletions packages/vitepress-plugin-moss/pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion packages/vitepress-plugin-moss/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
"skipLibCheck": true,
"jsx": "preserve",
"lib": ["ESNext", "DOM"],
"types": ["node"]
"types": ["node", "vite/client"]
},
"include": ["*.ts", "*.vue", "env.d.ts"]
}
Loading