feat(i18n): set up glossary (#2198)
This pull request introduces the initial glossary for the project to improve the translation quality. Implements #2148. ### TODOs - [x] Add the definition YAML - [x] Add a generator to produce Crowdin-compatible (TBX v3) format - [x] AGENTS.md - [ ] ~Workflow~ (Split to another PR) - [ ] ~Skills~ (Same as above)
This commit is contained in:
@@ -143,3 +143,7 @@ apps/stage-tamagotchi/electron.vite.config.*.mjs
|
||||
|
||||
docs/ai/context/verifications/
|
||||
.playwright-mcp/
|
||||
|
||||
# Generated from packages/i18n/glossary/terms.yaml at upload time. Never committed, so it
|
||||
# cannot drift from its source.
|
||||
packages/i18n/glossary/glossary.tbx
|
||||
|
||||
@@ -143,6 +143,37 @@ Concise but detailed reference for contributors working across the `moeru-ai/air
|
||||
|
||||
- Add/modify translations in `packages/i18n`; avoid scattering i18n across apps/packages.
|
||||
|
||||
### Glossary
|
||||
|
||||
`packages/i18n/glossary/terms.yaml` gives the approved English term for each product concept.
|
||||
`pnpm -F @proj-airi/i18n glossary:build` writes the TBX file that Crowdin imports. `schema.ts`
|
||||
documents each field.
|
||||
|
||||
- Read `terms.yaml` before you write or change a string that a user sees. Use the term it gives.
|
||||
- Do not edit `packages/i18n/glossary/translations/`. The next Crowdin download replaces it.
|
||||
- Take terms from the interface. Search the documentation to confirm a term, not to find one.
|
||||
|
||||
**Add a term when it prevents one of two failures:**
|
||||
|
||||
- A translator who reads only the source string chooses the wrong word.
|
||||
- Two translators choose different words, and both words are correct.
|
||||
|
||||
**Do not add a term when:**
|
||||
|
||||
- It is code. A translated control token, JSON key, file name, or package name breaks the
|
||||
application, and the application shows no error.
|
||||
- It is a common English word with its usual meaning, such as "Speed" or "Volume".
|
||||
- Its parts each have an entry and it says no more than its parts, such as "VRM model".
|
||||
- One feature uses it, and only two translators could disagree about it. But keep a rare term if a
|
||||
translator can get it wrong: `Tachie` occurs two times and is the strongest entry in the file.
|
||||
|
||||
`terms.yaml` holds no rationale, because each field must map to a TBX element. Give the reason in
|
||||
the pull request.
|
||||
|
||||
**Write a definition in one sentence.** Describe the thing, not the word, and put a negative rule in
|
||||
the `note`. Keep each sentence short and active: translators read them, and most do not read English
|
||||
as a first language.
|
||||
|
||||
## CSS/UNO
|
||||
|
||||
- Use/extend UnoCSS shortcuts in `uno.config.ts`.
|
||||
|
||||
@@ -52,6 +52,7 @@ words:
|
||||
- clippy
|
||||
- clustr
|
||||
- cmdorctrl
|
||||
- codenames
|
||||
- codesign
|
||||
- collectblock
|
||||
- colorjs
|
||||
@@ -189,6 +190,7 @@ words:
|
||||
- MeshToonMaterial
|
||||
- meteocons
|
||||
- micvad
|
||||
- MikuMikuDance
|
||||
- mineflayer
|
||||
- mingcute
|
||||
- minimizable
|
||||
|
||||
@@ -0,0 +1,284 @@
|
||||
import type { Concept } from './schema'
|
||||
|
||||
import { readdir, readFile } from 'node:fs/promises'
|
||||
import { dirname, join } from 'node:path'
|
||||
import { fileURLToPath } from 'node:url'
|
||||
|
||||
import { describe, expect, it } from 'vitest'
|
||||
import { parse } from 'yaml'
|
||||
|
||||
import { buildTbx } from './build-tbx'
|
||||
import { parseGlossary } from './schema'
|
||||
|
||||
const here = dirname(fileURLToPath(import.meta.url))
|
||||
|
||||
function concept(overrides: Partial<Concept> = {}): Concept {
|
||||
return {
|
||||
id: 'stage',
|
||||
subject: 'application',
|
||||
translatable: true,
|
||||
definition: 'The surface of the application that shows the character.',
|
||||
terms: [{ 'text': 'Stage', 'part-of-speech': 'noun', 'status': 'preferred' }],
|
||||
...overrides,
|
||||
}
|
||||
}
|
||||
|
||||
describe('buildTbx', () => {
|
||||
it('writes the document shape that a Crowdin export uses', () => {
|
||||
const xml = buildTbx([concept()], 'test')
|
||||
|
||||
expect(xml.startsWith('<?xml version="1.0" encoding="UTF-8"?>\n')).toBe(true)
|
||||
expect(xml).toContain('TBXcoreStructV03_TBX-Basic_integrated.rng')
|
||||
expect(xml).toContain('TBX-Basic_DCA.sch')
|
||||
expect(xml).toContain('xmlns="urn:iso:std:iso:30042:ed-2"')
|
||||
expect(xml).toContain('type="TBX-Basic"')
|
||||
expect(xml).toContain('style="dca"')
|
||||
expect(xml).toContain('<p>test</p>')
|
||||
expect(xml).toContain('<conceptEntry id="stage">')
|
||||
expect(xml).toContain('<langSec xml:lang="en">')
|
||||
// Crowdin's header carries a sourceDesc and nothing else.
|
||||
expect(xml).not.toContain('<titleStmt>')
|
||||
})
|
||||
|
||||
it('indents the elements the way a Crowdin export does', () => {
|
||||
const xml = buildTbx([concept()], 'test')
|
||||
|
||||
expect(xml).toContain('\n <tbxHeader>')
|
||||
expect(xml).toContain('\n <conceptEntry id="stage">')
|
||||
// Whitespace inside a definition is content, so it must not gain indentation.
|
||||
expect(xml).toContain('<descrip type="definition">The surface of the application that shows the character.</descrip>')
|
||||
})
|
||||
|
||||
it('puts langSec after the concept-level children', () => {
|
||||
const xml = buildTbx([concept()], 'test')
|
||||
|
||||
// TBX-Basic fixes this order. A langSec before a descrip is invalid, and a schema
|
||||
// validator rejects the file rather than importing it partly.
|
||||
expect(xml.indexOf('subjectField')).toBeLessThan(xml.indexOf('<langSec'))
|
||||
expect(xml.indexOf('type="definition"')).toBeLessThan(xml.indexOf('<langSec'))
|
||||
})
|
||||
|
||||
it('puts term before the termNote elements', () => {
|
||||
const xml = buildTbx([concept()], 'test')
|
||||
|
||||
expect(xml.indexOf('<term>')).toBeLessThan(xml.indexOf('partOfSpeech'))
|
||||
expect(xml.indexOf('partOfSpeech')).toBeLessThan(xml.indexOf('administrativeStatus'))
|
||||
})
|
||||
|
||||
it('writes the translatable flag that Crowdin reads', () => {
|
||||
// A Crowdin export carries the flag as a concept-level descrip, ahead of everything
|
||||
// else. TBX-Basic has no such data category, so this is a Crowdin extension.
|
||||
expect(buildTbx([concept({ translatable: false })], 'test'))
|
||||
.toContain('<descrip type="translatable">no</descrip>')
|
||||
expect(buildTbx([concept({ translatable: true })], 'test'))
|
||||
.toContain('<descrip type="translatable">yes</descrip>')
|
||||
})
|
||||
|
||||
it('puts the translatable flag before the other concept children', () => {
|
||||
const xml = buildTbx([concept()], 'test')
|
||||
|
||||
expect(xml.indexOf('type="translatable"')).toBeLessThan(xml.indexOf('type="subjectField"'))
|
||||
})
|
||||
|
||||
it('writes the context of each term that has one', () => {
|
||||
const xml = buildTbx([concept({
|
||||
terms: [
|
||||
{ 'text': 'Stage', 'part-of-speech': 'noun', 'status': 'preferred', 'context': 'Disable Stage Transitions' },
|
||||
{ 'text': 'Scene', 'part-of-speech': 'noun', 'status': 'deprecated', 'type': 'variant' },
|
||||
],
|
||||
})], 'test')
|
||||
|
||||
// TBX-Basic allows a context at term level only, so it belongs to the term whose
|
||||
// sentence it is rather than to the concept.
|
||||
expect(xml).toContain('<descrip type="context">Disable Stage Transitions</descrip>')
|
||||
expect(xml.match(/type="context"/g)).toHaveLength(1)
|
||||
})
|
||||
|
||||
it('puts the context and the note after the termNote elements', () => {
|
||||
const xml = buildTbx([concept({
|
||||
terms: [{ 'text': 'Stage', 'part-of-speech': 'noun', 'status': 'preferred', 'context': 'A sentence', 'note': 'A note' }],
|
||||
})], 'test')
|
||||
|
||||
expect(xml.indexOf('administrativeStatus')).toBeLessThan(xml.indexOf('type="context"'))
|
||||
expect(xml.indexOf('type="context"')).toBeLessThan(xml.indexOf('<note>A note</note>'))
|
||||
})
|
||||
|
||||
it('maps each status to the suffixed value that Crowdin writes', () => {
|
||||
const xml = buildTbx([concept({
|
||||
terms: [
|
||||
{ 'text': 'Character Card', 'part-of-speech': 'noun', 'status': 'preferred' },
|
||||
{ 'text': 'Card', 'part-of-speech': 'noun', 'status': 'admitted', 'type': 'shortForm' },
|
||||
{ 'text': 'Deck', 'part-of-speech': 'noun', 'status': 'deprecated', 'gender': 'feminine' },
|
||||
],
|
||||
})], 'test')
|
||||
|
||||
expect(xml).toContain('<termNote type="administrativeStatus">preferredTerm-admn-sts</termNote>')
|
||||
expect(xml).toContain('<termNote type="administrativeStatus">admittedTerm-admn-sts</termNote>')
|
||||
expect(xml).toContain('<termNote type="administrativeStatus">deprecatedTerm-admn-sts</termNote>')
|
||||
expect(xml).toContain('<termNote type="termType">shortForm</termNote>')
|
||||
expect(xml).toContain('<termNote type="grammaticalGender">feminine</termNote>')
|
||||
})
|
||||
|
||||
it('escapes the characters that would otherwise break the XML', () => {
|
||||
const xml = buildTbx([concept({ definition: 'A tag <b> & an "attribute".' })], 'test')
|
||||
|
||||
expect(xml).toContain('<b>')
|
||||
expect(xml).toContain('&')
|
||||
expect(xml).not.toContain('<b>')
|
||||
})
|
||||
|
||||
it('collapses the wrapping of a YAML folded block but keeps the paragraphs', () => {
|
||||
const note = parse('note: >\n One\n line.\n\n A second\n paragraph.\n').note as string
|
||||
const xml = buildTbx([concept({ note })], 'test')
|
||||
|
||||
expect(note).toBe('One line.\nA second paragraph.\n')
|
||||
expect(xml).toContain('One line.\n\nA second paragraph.')
|
||||
})
|
||||
})
|
||||
|
||||
describe('parseGlossary', () => {
|
||||
it('rejects two concepts that share an id', () => {
|
||||
expect(() => parseGlossary([concept(), concept()])).toThrow(/unique/)
|
||||
})
|
||||
|
||||
it('allows more than one preferred term, as Crowdin does', () => {
|
||||
// The export from project 816610 gives both `AIRI` and `Project AIRI` the preferred
|
||||
// status inside one concept, so nothing here may forbid it.
|
||||
const twoPreferred = concept({
|
||||
terms: [
|
||||
{ 'text': 'AIRI', 'part-of-speech': 'proper noun', 'status': 'preferred' },
|
||||
{ 'text': 'Project AIRI', 'part-of-speech': 'proper noun', 'status': 'preferred' },
|
||||
],
|
||||
})
|
||||
|
||||
expect(parseGlossary([twoPreferred])).toHaveLength(1)
|
||||
})
|
||||
|
||||
it('accepts the spelling of proper noun that Crowdin writes', () => {
|
||||
// ROOT CAUSE:
|
||||
//
|
||||
// An earlier version required `properNoun`, which is what the TBX-Basic specification
|
||||
// says, and rejected "proper noun" with a space. A glossary exported from project 816610
|
||||
// writes the spaced form on every proper noun, so the requirement was backwards: it
|
||||
// would have rejected the data Crowdin itself produces.
|
||||
const spaced = concept({ terms: [{ 'text': 'AIRI', 'part-of-speech': 'proper noun', 'status': 'preferred' }] })
|
||||
|
||||
expect(parseGlossary([spaced])).toHaveLength(1)
|
||||
expect(() => parseGlossary([concept({ terms: [{ 'text': 'AIRI', 'part-of-speech': 'properNoun', 'status': 'preferred' }] })])).toThrow()
|
||||
})
|
||||
|
||||
it('rejects an id that is not kebab case', () => {
|
||||
expect(() => parseGlossary([concept({ id: 'Stage Profile' })])).toThrow(/kebab/)
|
||||
})
|
||||
})
|
||||
|
||||
describe('terms.yaml', () => {
|
||||
async function loadConcepts(): Promise<Concept[]> {
|
||||
return parseGlossary(parse(await readFile(join(here, 'terms.yaml'), 'utf8')))
|
||||
}
|
||||
|
||||
/** Every scalar leaf of the English locale, which is what a user reads. */
|
||||
async function loadEnglishStrings(): Promise<string[]> {
|
||||
const root = join(here, '..', 'src', 'locales', 'en')
|
||||
const found: string[] = []
|
||||
|
||||
function walk(node: unknown): void {
|
||||
if (typeof node === 'string')
|
||||
found.push(node)
|
||||
else if (Array.isArray(node))
|
||||
node.forEach(walk)
|
||||
else if (node && typeof node === 'object')
|
||||
Object.values(node).forEach(walk)
|
||||
}
|
||||
|
||||
async function read(directory: string): Promise<void> {
|
||||
for (const entry of await readdir(directory, { withFileTypes: true })) {
|
||||
const path = join(directory, entry.name)
|
||||
if (entry.isDirectory())
|
||||
await read(path)
|
||||
else if (entry.name.endsWith('.yaml'))
|
||||
walk(parse(await readFile(path, 'utf8')))
|
||||
}
|
||||
}
|
||||
|
||||
await read(root)
|
||||
return found
|
||||
}
|
||||
|
||||
it('validates against the schema', async () => {
|
||||
const concepts = await loadConcepts()
|
||||
|
||||
expect(concepts.length).toBeGreaterThan(0)
|
||||
})
|
||||
|
||||
it('produces TBX for every concept', async () => {
|
||||
const concepts = await loadConcepts()
|
||||
const xml = buildTbx(concepts, 'test')
|
||||
|
||||
expect(xml.match(/<conceptEntry /g)).toHaveLength(concepts.length)
|
||||
})
|
||||
|
||||
it('holds no term that neither the interface nor the English documentation uses', async () => {
|
||||
const concepts = await loadConcepts()
|
||||
|
||||
// The glossary shares one Crowdin container with the documentation terminology, so a
|
||||
// term may live in prose rather than in a string. `Project AIRI` appears six times in
|
||||
// README.md and in no interface string, and `Neuro Sama` only under docs/content/en.
|
||||
//
|
||||
// The check still has teeth. A term that appears in none of these places can never match
|
||||
// in the editor, so it cannot help a translator. `Ayaka Neko` was such a term, and it is
|
||||
// the reason this check runs over the documentation rather than being deleted.
|
||||
const repository = join(here, '..', '..', '..')
|
||||
const prose = [await readFile(join(repository, 'README.md'), 'utf8')]
|
||||
|
||||
async function readDocs(directory: string): Promise<void> {
|
||||
for (const entry of await readdir(directory, { withFileTypes: true })) {
|
||||
const path = join(directory, entry.name)
|
||||
if (entry.isDirectory())
|
||||
await readDocs(path)
|
||||
else if (entry.name.endsWith('.md'))
|
||||
prose.push(await readFile(path, 'utf8'))
|
||||
}
|
||||
}
|
||||
await readDocs(join(repository, 'docs', 'content', 'en'))
|
||||
|
||||
const haystack = [...await loadEnglishStrings(), ...prose].join('\n').toLowerCase()
|
||||
|
||||
// The `documentation` concepts were adopted from the Crowdin glossary, and Crowdin is
|
||||
// where they are maintained. Repository text is not their source, so checking them
|
||||
// against it would delete data this file exists to preserve. `Ayaka Neko` is one: the
|
||||
// reversed name order, which no file here writes.
|
||||
const missing = concepts
|
||||
.filter(c => c.subject !== 'documentation')
|
||||
.flatMap(c => c.terms.filter(t => !haystack.includes(t.text.toLowerCase())).map(t => t.text))
|
||||
|
||||
expect(missing).toEqual([])
|
||||
})
|
||||
|
||||
it('gives every context the term it belongs to', async () => {
|
||||
const concepts = await loadConcepts()
|
||||
|
||||
// A context shows the term in use. Usually it is a real interface string, but for the
|
||||
// two codenames it cannot be: every interface string containing them is one this
|
||||
// glossary rules against. So the check is not "does the locale contain it" but "does it
|
||||
// mention its own term", which catches a sentence pasted onto the wrong entry.
|
||||
const unrelated = concepts.flatMap(c => c.terms
|
||||
.filter(t => t.context && !t.context.toLowerCase().includes(t.text.toLowerCase()))
|
||||
.map(t => `${c.id} / ${t.text}`))
|
||||
|
||||
expect(unrelated).toEqual([])
|
||||
})
|
||||
|
||||
it('holds no control token from the system prompt', async () => {
|
||||
const concepts = await loadConcepts()
|
||||
|
||||
// base.yaml carries the streaming control tokens to the translators. Those are code.
|
||||
// A translated token breaks stage playback with no error message, so a token must never
|
||||
// reach the glossary and become a term a translator is invited to work on.
|
||||
const code = concepts.flatMap(c => c.terms
|
||||
.filter(t => ['ACT', 'DELAY', 'CALL'].includes(t.text) || /[/{}<>]/.test(t.text))
|
||||
.map(t => t.text))
|
||||
|
||||
expect(code).toEqual([])
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,211 @@
|
||||
// cspell:words descrip
|
||||
import type { Element } from 'xast'
|
||||
|
||||
import type { Concept, Term } from './schema'
|
||||
|
||||
import process from 'node:process'
|
||||
|
||||
import { readFile, writeFile } from 'node:fs/promises'
|
||||
import { dirname, join } from 'node:path'
|
||||
import { fileURLToPath } from 'node:url'
|
||||
|
||||
import { toXml } from 'xast-util-to-xml'
|
||||
import { x } from 'xastscript'
|
||||
import { parse } from 'yaml'
|
||||
|
||||
import { parseGlossary } from './schema'
|
||||
|
||||
/**
|
||||
* The XML namespace of ISO 30042:2019, which the tooling calls TBX version 3. The `ed-2`
|
||||
* segment is the second edition of the ISO standard, not the second version of TBX.
|
||||
*/
|
||||
const TBX_NAMESPACE = 'urn:iso:std:iso:30042:ed-2'
|
||||
|
||||
/** The source language of the glossary. Crowdin owns every other language. */
|
||||
const SOURCE_LANGUAGE = 'en'
|
||||
|
||||
/**
|
||||
* The two schemas that Crowdin names in the exports it produces.
|
||||
*
|
||||
* They are processing instructions rather than elements, so an XML editor can validate the
|
||||
* file. Writing the same pair keeps a diff against a re-download small.
|
||||
*/
|
||||
const XML_MODELS = [
|
||||
'<?xml-model href="https://raw.githubusercontent.com/LTAC-Global/TBX-Basic_dialect/master/DCA/TBXcoreStructV03_TBX-Basic_integrated.rng" type="application/xml" schematypens="http://relaxng.org/ns/structure/1.0"?>',
|
||||
'<?xml-model href="https://raw.githubusercontent.com/LTAC-Global/TBX-Basic_dialect/master/DCA/TBX-Basic_DCA.sch" type="application/xml" schematypens="http://purl.oclc.org/dsdl/schematron"?>',
|
||||
]
|
||||
|
||||
/**
|
||||
* How Crowdin writes an acceptability rating.
|
||||
*
|
||||
* NOTICE:
|
||||
* The suffixed forms come from ISO 12620, and a Crowdin export writes them literally. Only
|
||||
* `preferredTerm-admn-sts` is confirmed by the export we have, because every term in it is
|
||||
* preferred. The other two follow the same pattern, and the first import should confirm
|
||||
* them.
|
||||
*/
|
||||
const ADMINISTRATIVE_STATUS: Record<Term['status'], string> = {
|
||||
preferred: 'preferredTerm-admn-sts',
|
||||
admitted: 'admittedTerm-admn-sts',
|
||||
deprecated: 'deprecatedTerm-admn-sts',
|
||||
}
|
||||
|
||||
/**
|
||||
* Turns the text of a YAML folded block into paragraphs.
|
||||
*
|
||||
* A folded block (`>`) joins each wrapped line with a space and turns a blank line into one
|
||||
* newline character. So a newline that survives parsing is always a paragraph break, and
|
||||
* the line width of the source file never reaches the output.
|
||||
*
|
||||
* NOTICE:
|
||||
* Splitting on two or more newlines looks correct and is wrong. YAML gives a blank line a
|
||||
* single newline, so that pattern matches nothing and every paragraph merges into one.
|
||||
*
|
||||
* Before:
|
||||
* - "One paragraph.\nA second paragraph."
|
||||
*
|
||||
* After:
|
||||
* - "One paragraph.\n\nA second paragraph."
|
||||
*/
|
||||
function collapse(text: string): string {
|
||||
return text.split(/\n+/).map(paragraph => paragraph.replace(/\s+/g, ' ').trim()).filter(Boolean).join('\n\n')
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds one `conceptEntry` element.
|
||||
*
|
||||
* TBX-Basic fixes the order inside each section, and the order below is not cosmetic:
|
||||
*
|
||||
* - inside `conceptEntry`, every `langSec` comes after the other children,
|
||||
* - inside `langSec`, every `termSec` comes after the other children,
|
||||
* - inside `termSec`, `term` comes first, then the `termNote` elements, then the rest.
|
||||
*
|
||||
*/
|
||||
function buildConceptEntry(concept: Concept): Element {
|
||||
const conceptChildren: Element[] = [
|
||||
// Crowdin's own export writes the flag first, as a concept-level descrip with the value
|
||||
// "yes" or "no". This is a Crowdin extension: TBX-Basic has no such data category.
|
||||
x('descrip', { type: 'translatable' }, concept.translatable ? 'yes' : 'no'),
|
||||
x('descrip', { type: 'subjectField' }, concept.subject),
|
||||
x('descrip', { type: 'definition' }, collapse(concept.definition)),
|
||||
]
|
||||
|
||||
if (concept.note)
|
||||
conceptChildren.push(x('note', collapse(concept.note)))
|
||||
|
||||
if (concept.url)
|
||||
conceptChildren.push(x('xref', { type: 'externalCrossReference', target: concept.url }, concept.url))
|
||||
|
||||
const termSections = concept.terms.map((term) => {
|
||||
const termChildren: Element[] = [
|
||||
x('term', term.text),
|
||||
x('termNote', { type: 'partOfSpeech' }, term['part-of-speech']),
|
||||
x('termNote', { type: 'administrativeStatus' }, ADMINISTRATIVE_STATUS[term.status]),
|
||||
]
|
||||
|
||||
if (term.type)
|
||||
termChildren.push(x('termNote', { type: 'termType' }, term.type))
|
||||
|
||||
if (term.gender)
|
||||
termChildren.push(x('termNote', { type: 'grammaticalGender' }, term.gender))
|
||||
|
||||
// TBX-Basic fixes the order inside a termSec: term, then every termNote, then the rest.
|
||||
if (term.context)
|
||||
termChildren.push(x('descrip', { type: 'context' }, term.context))
|
||||
|
||||
if (term.note)
|
||||
termChildren.push(x('note', collapse(term.note)))
|
||||
|
||||
return x('termSec', termChildren)
|
||||
})
|
||||
|
||||
conceptChildren.push(x('langSec', { 'xml:lang': SOURCE_LANGUAGE }, termSections))
|
||||
|
||||
return x('conceptEntry', { id: concept.id }, conceptChildren)
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders the glossary as a TBX-Basic document.
|
||||
*
|
||||
* The result is a complete XML document with the declaration, so a caller writes it to disk
|
||||
* unchanged. It carries the English terms only; Crowdin owns every other language, and
|
||||
* uploading target terms would overwrite the work of a translator.
|
||||
*
|
||||
* @param concepts Validated concepts, in the order they appear in `terms.yaml`.
|
||||
* @param source A description of where the data came from, recorded in the TBX header.
|
||||
*/
|
||||
export function buildTbx(concepts: Concept[], source: string): string {
|
||||
const tree = x(
|
||||
'tbx',
|
||||
// The root carries all four attributes that TBX-Basic requires. `style="dca"` selects
|
||||
// the data-category-as-attribute style, which is the one the schema values assume.
|
||||
{ 'type': 'TBX-Basic', 'style': 'dca', 'xml:lang': SOURCE_LANGUAGE, 'xmlns': TBX_NAMESPACE },
|
||||
[
|
||||
// The header carries a sourceDesc and nothing else, which is the shape Crowdin writes.
|
||||
x('tbxHeader', [x('fileDesc', [x('sourceDesc', [x('p', source)])])]),
|
||||
x('text', [x('body', concepts.map(buildConceptEntry))]),
|
||||
],
|
||||
)
|
||||
|
||||
indent(tree, 0)
|
||||
|
||||
return ['<?xml version="1.0" encoding="UTF-8"?>', ...XML_MODELS, toXml(tree), ''].join('\n')
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds whitespace between the children of an element, in place.
|
||||
*
|
||||
* Crowdin writes its exports with four-space indentation, and the serializer produces one
|
||||
* long line. Matching the layout keeps a diff against a re-download readable.
|
||||
*
|
||||
* An element whose children include text is left alone, because whitespace inside a
|
||||
* definition or a note is content, not layout.
|
||||
*/
|
||||
function indent(node: Element, depth: number): void {
|
||||
const children = node.children.filter(child => child.type === 'element')
|
||||
if (children.length !== node.children.length || children.length === 0)
|
||||
return
|
||||
|
||||
const inner = `\n${' '.repeat(depth + 1)}`
|
||||
const outer = `\n${' '.repeat(depth)}`
|
||||
|
||||
for (const child of children)
|
||||
indent(child, depth + 1)
|
||||
|
||||
node.children = [
|
||||
...children.flatMap(child => [{ type: 'text' as const, value: inner }, child]),
|
||||
{ type: 'text' as const, value: outer },
|
||||
]
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads `terms.yaml`, validates it, and writes the TBX file.
|
||||
*
|
||||
* Call stack:
|
||||
*
|
||||
* main
|
||||
* -> {@link parseGlossary}
|
||||
* -> {@link buildTbx}
|
||||
* -> buildConceptEntry
|
||||
* -> composeNote
|
||||
*/
|
||||
async function main(): Promise<void> {
|
||||
const here = dirname(fileURLToPath(import.meta.url))
|
||||
const input = join(here, 'terms.yaml')
|
||||
const output = process.argv[2] ?? join(here, 'glossary.tbx')
|
||||
|
||||
const concepts = parseGlossary(parse(await readFile(input, 'utf8')))
|
||||
await writeFile(output, buildTbx(concepts, 'packages/i18n/glossary/terms.yaml'), 'utf8')
|
||||
|
||||
const terms = concepts.reduce((total, concept) => total + concept.terms.length, 0)
|
||||
process.stdout.write(`wrote ${output}: ${concepts.length} concepts, ${terms} terms\n`)
|
||||
}
|
||||
|
||||
// Only run when this file is the entry point, so that the test can import buildTbx without
|
||||
// writing a file.
|
||||
if (process.argv[1] && import.meta.url === `file://${process.argv[1]}`) {
|
||||
main().catch((error: unknown) => {
|
||||
process.stderr.write(`${String(error)}\n`)
|
||||
process.exitCode = 1
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,119 @@
|
||||
import * as v from 'valibot'
|
||||
|
||||
/**
|
||||
* Part of speech, spelled the way Crowdin spells it.
|
||||
*
|
||||
* NOTICE:
|
||||
* TBX-Basic writes this value as `properNoun` (DC-0396), and Crowdin writes it as "proper
|
||||
* noun" with a space. Crowdin reads what we upload, so Crowdin wins. Confirmed against a
|
||||
* glossary exported from project 816610, where every proper noun reads "proper noun".
|
||||
*/
|
||||
const PartOfSpeechSchema = v.picklist([
|
||||
'adjective',
|
||||
'adposition',
|
||||
'adverb',
|
||||
'auxiliary',
|
||||
'coordinating conjunction',
|
||||
'determiner',
|
||||
'interjection',
|
||||
'noun',
|
||||
'numeral',
|
||||
'particle',
|
||||
'pronoun',
|
||||
'proper noun',
|
||||
'subordinating conjunction',
|
||||
'verb',
|
||||
'other',
|
||||
])
|
||||
|
||||
/** Term type. TBX-Basic allows these values and no others (DC-2677). */
|
||||
const TermTypeSchema = v.picklist(['fullForm', 'acronym', 'abbreviation', 'shortForm', 'variant', 'phrase'])
|
||||
|
||||
/**
|
||||
* How acceptable a term is (DC-0070). ISO 704:2022 calls it an acceptability rating.
|
||||
*
|
||||
* These are the readable forms. The generator maps them to the suffixed values Crowdin
|
||||
* writes, such as `preferredTerm-admn-sts`. Crowdin permits more than one preferred term in
|
||||
* a concept, so nothing here limits the count.
|
||||
*/
|
||||
const UsageStatusSchema = v.picklist(['preferred', 'admitted', 'deprecated'])
|
||||
|
||||
/** Grammatical gender (DC-0245). */
|
||||
const GenderSchema = v.picklist(['masculine', 'feminine', 'neuter', 'other'])
|
||||
|
||||
/**
|
||||
* One term of a concept.
|
||||
*
|
||||
* Every field maps to one TBX element, and the field names follow TBX rather than any name
|
||||
* of our own, so that the mapping stays obvious:
|
||||
*
|
||||
* text -> <term>
|
||||
* part-of-speech -> <termNote type="partOfSpeech">
|
||||
* status -> <termNote type="administrativeStatus">
|
||||
* type -> <termNote type="termType">
|
||||
* gender -> <termNote type="grammaticalGender">
|
||||
* context -> <descrip type="context">
|
||||
* note -> <note>
|
||||
*/
|
||||
const TermSchema = v.object({
|
||||
'text': v.pipe(v.string(), v.nonEmpty()),
|
||||
'part-of-speech': PartOfSpeechSchema,
|
||||
'status': UsageStatusSchema,
|
||||
'type': v.optional(TermTypeSchema),
|
||||
'gender': v.optional(GenderSchema),
|
||||
/** A sentence that shows the term in use. TBX allows a context at term level only. */
|
||||
'context': v.optional(v.string()),
|
||||
'note': v.optional(v.string()),
|
||||
})
|
||||
|
||||
/**
|
||||
* One concept, which is one entry of the glossary.
|
||||
*
|
||||
* As with a term, every field maps to one TBX element:
|
||||
*
|
||||
* id -> <conceptEntry id="...">
|
||||
* subject -> <descrip type="subjectField">
|
||||
* translatable -> <descrip type="translatable">, a Crowdin extension
|
||||
* definition -> <descrip type="definition">
|
||||
* note -> <note>
|
||||
* url -> <xref type="externalCrossReference">
|
||||
* terms -> <langSec xml:lang="en"> with one <termSec> for each term
|
||||
*/
|
||||
const ConceptSchema = v.object({
|
||||
/**
|
||||
* Stable identifier in kebab case. A change here creates a new concept in Crowdin rather
|
||||
* than updating the existing one, so it must survive a rename of the terms.
|
||||
*/
|
||||
id: v.pipe(v.string(), v.regex(/^[a-z0-9]+(?:-[a-z0-9]+)*$/, 'id must be kebab case')),
|
||||
subject: v.pipe(v.string(), v.nonEmpty()),
|
||||
translatable: v.boolean(),
|
||||
/** One sentence. Write two only when one cannot carry the meaning. */
|
||||
definition: v.pipe(v.string(), v.nonEmpty()),
|
||||
note: v.optional(v.string()),
|
||||
url: v.optional(v.pipe(v.string(), v.url())),
|
||||
terms: v.pipe(v.array(TermSchema), v.minLength(1)),
|
||||
})
|
||||
|
||||
export const GlossarySchema = v.pipe(
|
||||
v.array(ConceptSchema),
|
||||
v.minLength(1),
|
||||
v.check(
|
||||
concepts => new Set(concepts.map(c => c.id)).size === concepts.length,
|
||||
'every concept id must be unique',
|
||||
),
|
||||
)
|
||||
|
||||
export type Term = v.InferOutput<typeof TermSchema>
|
||||
export type Concept = v.InferOutput<typeof ConceptSchema>
|
||||
|
||||
/**
|
||||
* Parses and validates the contents of `terms.yaml`.
|
||||
*
|
||||
* Throws a `ValiError` naming the failing path when the data does not match, so a broken
|
||||
* entry fails the build rather than producing invalid TBX.
|
||||
*
|
||||
* @param data The result of parsing the YAML file.
|
||||
*/
|
||||
export function parseGlossary(data: unknown): Concept[] {
|
||||
return v.parse(GlossarySchema, data)
|
||||
}
|
||||
@@ -0,0 +1,476 @@
|
||||
# AIRI terminology glossary — English source of truth.
|
||||
#
|
||||
# A generator turns this file into TBX version 3 and sends it to the Crowdin glossary, where
|
||||
# the editor marks each term and offers the approved translation.
|
||||
#
|
||||
# Every field maps to one TBX element and carries the TBX name. schema.ts holds the mapping.
|
||||
# AGENTS.md, under "i18n / Glossary", says when a term belongs here and when it does not.
|
||||
#
|
||||
# This repository owns English. Crowdin owns the other 8 languages, and the translated terms
|
||||
# arrive in packages/i18n/glossary/translations/ through a pull request.
|
||||
|
||||
# ---------------------------------------------------------------------------------------
|
||||
# Names from the documentation
|
||||
#
|
||||
# These concepts were already in the Crowdin glossary, added by hand. They live here so that
|
||||
# this file describes the whole glossary and an upload cannot destroy them.
|
||||
# ---------------------------------------------------------------------------------------
|
||||
|
||||
- id: neuro-sama
|
||||
subject: documentation
|
||||
translatable: false
|
||||
definition: An AI VTuber made by another developer.
|
||||
note: The hyphenated form is the product's own spelling.
|
||||
terms:
|
||||
- text: Neuro-sama
|
||||
part-of-speech: proper noun
|
||||
status: preferred
|
||||
type: fullForm
|
||||
context: Neuro-sama uses 2D model driven by framework developed by Live2D Inc
|
||||
- text: Neuro Sama
|
||||
part-of-speech: proper noun
|
||||
status: admitted
|
||||
type: variant
|
||||
- text: Neuro
|
||||
part-of-speech: proper noun
|
||||
status: admitted
|
||||
type: shortForm
|
||||
|
||||
- id: neko-ayaka
|
||||
subject: documentation
|
||||
translatable: true
|
||||
definition: A maintainer of this project.
|
||||
note: Both name orders name one person.
|
||||
terms:
|
||||
- text: Neko Ayaka
|
||||
part-of-speech: proper noun
|
||||
status: preferred
|
||||
gender: feminine
|
||||
type: fullForm
|
||||
context: (from Neko Ayaka) Good morning! You are finally awake.
|
||||
- text: Ayaka Neko
|
||||
part-of-speech: proper noun
|
||||
status: admitted
|
||||
gender: feminine
|
||||
type: variant
|
||||
note: The reversed name order.
|
||||
- text: Neko
|
||||
part-of-speech: proper noun
|
||||
status: admitted
|
||||
gender: feminine
|
||||
type: shortForm
|
||||
note: 'The short form, as in "always call her Neko for simplicity".'
|
||||
|
||||
- id: devlog
|
||||
subject: documentation
|
||||
translatable: false
|
||||
definition: A development log that the project publishes on its documentation site.
|
||||
terms:
|
||||
- text: DevLog
|
||||
part-of-speech: noun
|
||||
status: preferred
|
||||
type: fullForm
|
||||
context: DevLog @ 2025.08.05
|
||||
- text: DevLogs
|
||||
part-of-speech: noun
|
||||
status: admitted
|
||||
type: variant
|
||||
note: The plural; TBX has no plural value, so it is recorded as a variant.
|
||||
|
||||
# ---------------------------------------------------------------------------------------
|
||||
# Product and editions
|
||||
# ---------------------------------------------------------------------------------------
|
||||
|
||||
- id: airi
|
||||
subject: product
|
||||
# TODO: open question. Should this concept be translatable? Interface strings in all 8
|
||||
# locales keep "AIRI". But the project uses the Japanese form アイリ in prose, and also in
|
||||
# the English README.
|
||||
translatable: false
|
||||
definition: The application that this project makes, an animated character that speaks, listens, and sees.
|
||||
note: >
|
||||
Keep the Latin letters in every language; only prose may write the Japanese form アイリ.
|
||||
terms:
|
||||
- text: AIRI
|
||||
part-of-speech: proper noun
|
||||
status: preferred
|
||||
context: Welcome to AIRI!
|
||||
- text: Project AIRI
|
||||
part-of-speech: proper noun
|
||||
status: preferred
|
||||
type: fullForm
|
||||
note: The full name, used on first mention.
|
||||
|
||||
- id: tamagotchi
|
||||
subject: product
|
||||
translatable: false
|
||||
definition: The internal codename of the desktop edition, whose package is stage-tamagotchi.
|
||||
note: >
|
||||
Keep the Latin letters, write "Desktop ver." in anything an end user reads, and never
|
||||
write "Stage Tamagotchi" with a space.
|
||||
terms:
|
||||
- text: Tamagotchi
|
||||
part-of-speech: proper noun
|
||||
status: preferred
|
||||
context: Desktop ver. (known as stage-tamagotchi internally)
|
||||
|
||||
- id: pocket
|
||||
subject: product
|
||||
translatable: false
|
||||
definition: The internal codename of the mobile edition, whose package is stage-pocket.
|
||||
note: >
|
||||
Keep the Latin letters, write "Mobile ver." in anything an end user reads, and never
|
||||
write "Stage Pocket" with a space.
|
||||
terms:
|
||||
- text: Pocket
|
||||
part-of-speech: proper noun
|
||||
status: preferred
|
||||
context: Mobile ver. (known as stage-pocket internally)
|
||||
note: Correct for a developer audience, wrong in the interface.
|
||||
- text: Stage Pocket
|
||||
part-of-speech: proper noun
|
||||
status: deprecated
|
||||
type: variant
|
||||
note: Neither the codename nor the name a user sees.
|
||||
|
||||
# ---------------------------------------------------------------------------------------
|
||||
# Payment
|
||||
# ---------------------------------------------------------------------------------------
|
||||
|
||||
- id: flux
|
||||
subject: payment
|
||||
translatable: false
|
||||
definition: The currency inside the application.
|
||||
terms:
|
||||
- text: Flux
|
||||
part-of-speech: proper noun
|
||||
status: preferred
|
||||
context: Payment successful! Your Flux has been topped up.
|
||||
|
||||
# ---------------------------------------------------------------------------------------
|
||||
# Rendering
|
||||
# ---------------------------------------------------------------------------------------
|
||||
|
||||
- id: live2d
|
||||
subject: rendering
|
||||
translatable: false
|
||||
definition: A system that animates 2D artwork of a character.
|
||||
terms:
|
||||
- text: Live2D
|
||||
part-of-speech: proper noun
|
||||
status: preferred
|
||||
context: Live2D Settings
|
||||
|
||||
- id: vrm
|
||||
subject: rendering
|
||||
translatable: false
|
||||
definition: A file format for a 3D avatar.
|
||||
terms:
|
||||
- text: VRM
|
||||
part-of-speech: proper noun
|
||||
status: preferred
|
||||
context: Enter VRM model URL
|
||||
|
||||
- id: mmd
|
||||
subject: rendering
|
||||
translatable: false
|
||||
definition: The MikuMikuDance file format.
|
||||
terms:
|
||||
- text: MMD
|
||||
part-of-speech: proper noun
|
||||
status: preferred
|
||||
context: Remove imported Live2D, VRM, Spine, and MMD models.
|
||||
|
||||
- id: spine
|
||||
subject: rendering
|
||||
translatable: false
|
||||
definition: A system for 2D skeletal animation.
|
||||
terms:
|
||||
- text: Spine
|
||||
part-of-speech: proper noun
|
||||
status: preferred
|
||||
context: Spine Settings
|
||||
|
||||
- id: tachie
|
||||
subject: rendering
|
||||
translatable: true
|
||||
definition: Artwork that shows a character standing.
|
||||
# TODO: open question. Confirm the Chinese wording with a native reviewer.
|
||||
note: Japanese uses 立ち絵; a language with no such word keeps "Tachie".
|
||||
terms:
|
||||
- text: Tachie
|
||||
part-of-speech: noun
|
||||
status: preferred
|
||||
context: Tachie models use .tachie.zip archives containing emotion-named images.
|
||||
|
||||
- id: avatar-model
|
||||
subject: rendering
|
||||
translatable: true
|
||||
definition: The file that holds the appearance of the character, such as a Live2D model or a VRM model.
|
||||
note: Not the LLM model.
|
||||
terms:
|
||||
- text: Model
|
||||
part-of-speech: noun
|
||||
status: preferred
|
||||
context: Remove imported Live2D, VRM, Spine, and MMD models.
|
||||
|
||||
- id: motion
|
||||
subject: rendering
|
||||
translatable: true
|
||||
definition: An animation clip that moves the character, such as a wave of the hand.
|
||||
note: A Motion moves the body and an Expression changes the face; use two different words.
|
||||
terms:
|
||||
- text: Motion
|
||||
part-of-speech: noun
|
||||
status: preferred
|
||||
context: Map Motions
|
||||
|
||||
- id: expression
|
||||
subject: rendering
|
||||
translatable: true
|
||||
definition: A change of the character's face, such as a smile.
|
||||
note: Use a different word from Motion, which moves the body.
|
||||
terms:
|
||||
- text: Expression
|
||||
part-of-speech: noun
|
||||
status: preferred
|
||||
context: Expressions
|
||||
|
||||
- id: motion-map
|
||||
subject: rendering
|
||||
translatable: true
|
||||
definition: The table that connects each emotion to a motion.
|
||||
terms:
|
||||
- text: Motion Map
|
||||
part-of-speech: noun
|
||||
status: preferred
|
||||
context: Edit motion map
|
||||
|
||||
# ---------------------------------------------------------------------------------------
|
||||
# The application
|
||||
# ---------------------------------------------------------------------------------------
|
||||
|
||||
- id: stage
|
||||
subject: application
|
||||
translatable: true
|
||||
definition: The surface of the application that shows the character and the widgets.
|
||||
note: This word does not refer to a step in a process.
|
||||
terms:
|
||||
- text: Stage
|
||||
part-of-speech: noun
|
||||
status: preferred
|
||||
context: Disable Stage Transitions
|
||||
|
||||
- id: controls-island
|
||||
subject: application
|
||||
translatable: true
|
||||
definition: The group of controls that floats above the stage.
|
||||
note: An invented name; describe the thing rather than translate the two words.
|
||||
terms:
|
||||
- text: Controls Island
|
||||
part-of-speech: noun
|
||||
status: preferred
|
||||
context: Controls Island Icon Size
|
||||
|
||||
- id: spotlight
|
||||
subject: application
|
||||
translatable: true
|
||||
definition: A window on the desktop edition that opens with a keyboard shortcut for quick commands.
|
||||
note: Not the macOS function of the same name, so do not copy the Apple translation.
|
||||
terms:
|
||||
- text: Spotlight
|
||||
part-of-speech: noun
|
||||
status: preferred
|
||||
context: Spotlight shortcut
|
||||
|
||||
# ---------------------------------------------------------------------------------------
|
||||
# Models and providers
|
||||
# ---------------------------------------------------------------------------------------
|
||||
|
||||
- id: provider
|
||||
subject: providers
|
||||
translatable: true
|
||||
definition: An external service that supplies a model, such as OpenAI, Ollama, or ElevenLabs.
|
||||
terms:
|
||||
- text: Provider
|
||||
part-of-speech: noun
|
||||
status: preferred
|
||||
context: No models were found for this provider
|
||||
|
||||
- id: model
|
||||
subject: providers
|
||||
translatable: true
|
||||
definition: A machine-learning model that a provider supplies.
|
||||
terms:
|
||||
- text: Model
|
||||
part-of-speech: noun
|
||||
status: preferred
|
||||
context: Select a model
|
||||
|
||||
# ---------------------------------------------------------------------------------------
|
||||
# The modules
|
||||
#
|
||||
# These five names are a family. Translate them as a group, so the result reads as one set
|
||||
# of capabilities and not as five unrelated words.
|
||||
# ---------------------------------------------------------------------------------------
|
||||
|
||||
- id: consciousness
|
||||
subject: modules
|
||||
translatable: true
|
||||
definition: The module that thinks for the character, using a large language model.
|
||||
note: An unusual word for a software feature; it means the module for the language model.
|
||||
terms:
|
||||
- text: Consciousness
|
||||
part-of-speech: noun
|
||||
status: preferred
|
||||
context: Select the suitable LLM provider for consciousness
|
||||
|
||||
- id: hearing
|
||||
subject: modules
|
||||
translatable: true
|
||||
definition: The module that changes the speech of the user to text.
|
||||
note: Opposite direction to Speech; not a word for the ear or a medical test.
|
||||
terms:
|
||||
- text: Hearing
|
||||
part-of-speech: noun
|
||||
status: preferred
|
||||
context: Hearing
|
||||
|
||||
- id: speech
|
||||
subject: modules
|
||||
translatable: true
|
||||
definition: The module that changes text to the voice of the character.
|
||||
note: Read the note on "Hearing".
|
||||
terms:
|
||||
- text: Speech
|
||||
part-of-speech: noun
|
||||
status: preferred
|
||||
context: Speech
|
||||
|
||||
- id: vision
|
||||
subject: modules
|
||||
translatable: true
|
||||
definition: The module that lets the character see images and the screen.
|
||||
note: This is eyesight, not a plan for the future.
|
||||
terms:
|
||||
- text: Vision
|
||||
part-of-speech: noun
|
||||
status: preferred
|
||||
context: Vision
|
||||
|
||||
- id: artistry
|
||||
subject: modules
|
||||
translatable: true
|
||||
definition: The module that makes images.
|
||||
note: Translate the definition, not the English word.
|
||||
terms:
|
||||
- text: Artistry
|
||||
part-of-speech: noun
|
||||
status: preferred
|
||||
context: Artistry Provider Configuration
|
||||
|
||||
# ---------------------------------------------------------------------------------------
|
||||
# Memory
|
||||
# ---------------------------------------------------------------------------------------
|
||||
|
||||
- id: memory
|
||||
subject: memory
|
||||
translatable: true
|
||||
definition: What the character keeps and can use again in a later conversation.
|
||||
note: >
|
||||
Not the computer's RAM, which the performance overlay means by the same word; use the
|
||||
word for what a person remembers.
|
||||
terms:
|
||||
- text: Memory
|
||||
part-of-speech: noun
|
||||
status: preferred
|
||||
context: Memory
|
||||
|
||||
- id: long-term-memory
|
||||
subject: memory
|
||||
translatable: true
|
||||
# TODO: confirm this definition. The module has a settings page and a route, but no
|
||||
# implementation that describes the behavior.
|
||||
definition: The module that holds what the character keeps across many conversations.
|
||||
terms:
|
||||
- text: Long-Term Memory
|
||||
part-of-speech: noun
|
||||
status: preferred
|
||||
context: Long-term memory specific settings and management
|
||||
|
||||
- id: short-term-memory
|
||||
subject: memory
|
||||
translatable: true
|
||||
# TODO: confirm this definition. Read the note on "long-term-memory".
|
||||
definition: The module that holds what the character keeps inside the current conversation.
|
||||
terms:
|
||||
- text: Short-Term Memory
|
||||
part-of-speech: noun
|
||||
status: preferred
|
||||
context: Short-term memory specific settings and management
|
||||
|
||||
# ---------------------------------------------------------------------------------------
|
||||
# The character
|
||||
# ---------------------------------------------------------------------------------------
|
||||
|
||||
- id: character
|
||||
subject: character
|
||||
translatable: true
|
||||
definition: >
|
||||
A character with everything this product stores for it: the persona, the avatar model,
|
||||
the background, the provider and model of each module, and the prompt of each agent.
|
||||
note: >
|
||||
A rename is in progress, so no term is preferred yet, and the interface still uses
|
||||
"Character" for a smaller thing: a tab inside the card.
|
||||
terms:
|
||||
- text: AIRI Card
|
||||
part-of-speech: noun
|
||||
status: admitted
|
||||
context: Paste this into your AIRI Card artistry config to override these nodes.
|
||||
note: The name in the interface today; translate "Card" and keep "AIRI".
|
||||
- text: Character
|
||||
part-of-speech: noun
|
||||
status: admitted
|
||||
note: The planned name, not yet used for this concept.
|
||||
- text: Profile
|
||||
part-of-speech: noun
|
||||
status: admitted
|
||||
type: variant
|
||||
note: >
|
||||
The stage switcher means this concept; the Account page means the user's own details.
|
||||
|
||||
- id: character-card
|
||||
subject: character
|
||||
translatable: true
|
||||
definition: The portable file format for a character, from the wider ecosystem.
|
||||
note: >
|
||||
A user imports it into a Character, which holds more; never shorten it to "Card".
|
||||
terms:
|
||||
- text: Character Card
|
||||
part-of-speech: noun
|
||||
status: preferred
|
||||
context: Configure modules for this character card.
|
||||
|
||||
- id: system-prompt
|
||||
subject: character
|
||||
translatable: true
|
||||
definition: The instructions the application sends to the model before the conversation starts.
|
||||
terms:
|
||||
- text: System Prompt
|
||||
part-of-speech: noun
|
||||
status: preferred
|
||||
context: 'Error: Please, provide a system prompt.'
|
||||
|
||||
# ---------------------------------------------------------------------------------------
|
||||
# Sound
|
||||
# ---------------------------------------------------------------------------------------
|
||||
|
||||
- id: voice-pack
|
||||
subject: sound
|
||||
translatable: true
|
||||
definition: A prepared voice the user selects for the active character.
|
||||
terms:
|
||||
- text: Voice Pack
|
||||
part-of-speech: noun
|
||||
status: preferred
|
||||
context: No Voice Packs available
|
||||
@@ -61,9 +61,16 @@
|
||||
"scripts": {
|
||||
"dev": "pnpm run build",
|
||||
"build": "tsdown",
|
||||
"glossary:build": "tsx glossary/build-tbx.ts",
|
||||
"test": "vitest run",
|
||||
"test:watch": "vitest",
|
||||
"typecheck": "tsc --noEmit"
|
||||
},
|
||||
"devDependencies": {
|
||||
"unplugin-yaml": "catalog:"
|
||||
"unplugin-yaml": "catalog:",
|
||||
"valibot": "catalog:",
|
||||
"xast-util-to-xml": "catalog:",
|
||||
"xastscript": "catalog:",
|
||||
"yaml": "catalog:"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
import { defineConfig } from 'vitest/config'
|
||||
|
||||
export default defineConfig({
|
||||
test: {
|
||||
include: ['glossary/**/*.test.ts'],
|
||||
},
|
||||
})
|
||||
Generated
+245
-23
@@ -2116,7 +2116,7 @@ importers:
|
||||
version: 3.0.2(electron@41.2.1)
|
||||
'@electron-toolkit/tsconfig':
|
||||
specifier: 'catalog:'
|
||||
version: 2.0.0(@types/node@25.6.0)
|
||||
version: 2.0.0(@types/node@24.12.2)
|
||||
'@electron-toolkit/utils':
|
||||
specifier: 'catalog:'
|
||||
version: 4.0.0(electron@41.2.1)
|
||||
@@ -2155,7 +2155,7 @@ importers:
|
||||
version: 3.1.0
|
||||
'@intlify/unplugin-vue-i18n':
|
||||
specifier: 'catalog:'
|
||||
version: 11.0.7(@vue/compiler-dom@3.5.32)(eslint@10.2.1(jiti@2.6.1))(rollup@4.60.1)(typescript@5.9.3)(vite@8.0.8(@types/node@25.6.0)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3))(vue-i18n@11.3.2(vue@3.5.32(typescript@5.9.3)))(vue@3.5.32(typescript@5.9.3))
|
||||
version: 11.0.7(@vue/compiler-dom@3.5.32)(eslint@10.2.1(jiti@2.6.1))(rollup@4.60.1)(typescript@5.9.3)(vite@8.0.8(@types/node@24.12.2)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3))(vue-i18n@11.3.2(vue@3.5.32(typescript@5.9.3)))(vue@3.5.32(typescript@5.9.3))
|
||||
'@modelcontextprotocol/sdk':
|
||||
specifier: 'catalog:'
|
||||
version: 1.29.0(@cfworker/json-schema@4.1.1)(zod@4.3.6)
|
||||
@@ -2191,10 +2191,10 @@ importers:
|
||||
version: link:../../packages/ui-transitions
|
||||
'@proj-airi/unplugin-fetch':
|
||||
specifier: 'catalog:'
|
||||
version: 0.2.3(vite@8.0.8(@types/node@25.6.0)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3))
|
||||
version: 0.2.3(vite@8.0.8(@types/node@24.12.2)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3))
|
||||
'@proj-airi/unplugin-live2d-sdk':
|
||||
specifier: 'catalog:'
|
||||
version: 0.1.7(@types/node@25.6.0)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3)
|
||||
version: 0.1.7(@types/node@24.12.2)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3)
|
||||
'@types/audioworklet':
|
||||
specifier: 'catalog:'
|
||||
version: 0.0.97
|
||||
@@ -2221,7 +2221,7 @@ importers:
|
||||
version: 2.10.3
|
||||
'@vitejs/plugin-vue':
|
||||
specifier: 'catalog:'
|
||||
version: 6.0.6(vite@8.0.8(@types/node@25.6.0)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3))(vue@3.5.32(typescript@5.9.3))
|
||||
version: 6.0.6(vite@8.0.8(@types/node@24.12.2)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3))(vue@3.5.32(typescript@5.9.3))
|
||||
'@vue-macros/volar':
|
||||
specifier: 'catalog:'
|
||||
version: 3.1.2(typescript@5.9.3)(vue-tsc@3.2.6(typescript@5.9.3))(vue@3.5.32(typescript@5.9.3))
|
||||
@@ -2254,7 +2254,7 @@ importers:
|
||||
version: 6.8.3
|
||||
electron-vite:
|
||||
specifier: 'catalog:'
|
||||
version: 5.0.0(vite@8.0.8(@types/node@25.6.0)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3))
|
||||
version: 5.0.0(vite@8.0.8(@types/node@24.12.2)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3))
|
||||
get-port-please:
|
||||
specifier: 'catalog:'
|
||||
version: 3.2.0
|
||||
@@ -2275,31 +2275,31 @@ importers:
|
||||
version: 2.2.6
|
||||
unocss-preset-scrollbar:
|
||||
specifier: 'catalog:'
|
||||
version: 4.0.0(unocss@66.6.8(@emnapi/core@1.10.0)(@emnapi/runtime@1.10.0)(vite@8.0.8(@types/node@25.6.0)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3)))
|
||||
version: 4.0.0(unocss@66.6.8(@emnapi/core@1.10.0)(@emnapi/runtime@1.10.0)(vite@8.0.8(@types/node@24.12.2)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3)))
|
||||
unplugin-info:
|
||||
specifier: 'catalog:'
|
||||
version: 1.3.2(esbuild@0.27.2)(rollup@4.60.1)(vite@8.0.8(@types/node@25.6.0)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3))
|
||||
version: 1.3.2(esbuild@0.27.2)(rollup@4.60.1)(vite@8.0.8(@types/node@24.12.2)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3))
|
||||
unplugin-yaml:
|
||||
specifier: 'catalog:'
|
||||
version: 4.1.0(esbuild@0.27.2)(rolldown@1.0.0-rc.16)(rollup@4.60.1)(vite@8.0.8(@types/node@25.6.0)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3))
|
||||
version: 4.1.0(esbuild@0.27.2)(rolldown@1.0.0-rc.16)(rollup@4.60.1)(vite@8.0.8(@types/node@24.12.2)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3))
|
||||
vite:
|
||||
specifier: 'catalog:'
|
||||
version: 8.0.8(@types/node@25.6.0)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3)
|
||||
version: 8.0.8(@types/node@24.12.2)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3)
|
||||
vite-bundle-visualizer:
|
||||
specifier: 'catalog:'
|
||||
version: 1.2.1(rolldown@1.0.0-rc.16)(rollup@4.60.1)
|
||||
vite-plugin-mkcert:
|
||||
specifier: 'catalog:'
|
||||
version: 2.0.0(vite@8.0.8(@types/node@25.6.0)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3))
|
||||
version: 2.0.0(vite@8.0.8(@types/node@24.12.2)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3))
|
||||
vite-plugin-vue-devtools:
|
||||
specifier: 'catalog:'
|
||||
version: 8.1.1(vite@8.0.8(@types/node@25.6.0)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3))(vue@3.5.32(typescript@5.9.3))
|
||||
version: 8.1.1(vite@8.0.8(@types/node@24.12.2)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3))(vue@3.5.32(typescript@5.9.3))
|
||||
vite-plugin-vue-layouts:
|
||||
specifier: 'catalog:'
|
||||
version: 0.11.0(vite@8.0.8(@types/node@25.6.0)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3))(vue-router@5.0.4(@pinia/colada@1.2.1(pinia@3.0.4(typescript@5.9.3)(vue@3.5.32(typescript@5.9.3)))(vue@3.5.32(typescript@5.9.3)))(@vue/compiler-sfc@3.5.32)(pinia@3.0.4(typescript@5.9.3)(vue@3.5.32(typescript@5.9.3)))(vue@3.5.32(typescript@5.9.3)))(vue@3.5.32(typescript@5.9.3))
|
||||
version: 0.11.0(vite@8.0.8(@types/node@24.12.2)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3))(vue-router@5.0.4(@pinia/colada@1.2.1(pinia@3.0.4(typescript@5.9.3)(vue@3.5.32(typescript@5.9.3)))(vue@3.5.32(typescript@5.9.3)))(@vue/compiler-sfc@3.5.32)(pinia@3.0.4(typescript@5.9.3)(vue@3.5.32(typescript@5.9.3)))(vue@3.5.32(typescript@5.9.3)))(vue@3.5.32(typescript@5.9.3))
|
||||
vue-macros:
|
||||
specifier: 'catalog:'
|
||||
version: 3.1.2(@emnapi/core@1.10.0)(@emnapi/runtime@1.10.0)(@vueuse/core@14.2.1(vue@3.5.32(typescript@5.9.3)))(esbuild@0.27.2)(rolldown@1.0.0-rc.16)(rollup@4.60.1)(typescript@5.9.3)(vite@8.0.8(@types/node@25.6.0)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3))(vue-tsc@3.2.6(typescript@5.9.3))(vue@3.5.32(typescript@5.9.3))
|
||||
version: 3.1.2(@emnapi/core@1.10.0)(@emnapi/runtime@1.10.0)(@vueuse/core@14.2.1(vue@3.5.32(typescript@5.9.3)))(esbuild@0.27.2)(rolldown@1.0.0-rc.16)(rollup@4.60.1)(typescript@5.9.3)(vite@8.0.8(@types/node@24.12.2)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3))(vue-tsc@3.2.6(typescript@5.9.3))(vue@3.5.32(typescript@5.9.3))
|
||||
vue-tsc:
|
||||
specifier: 'catalog:'
|
||||
version: 3.2.6(typescript@5.9.3)
|
||||
@@ -3664,6 +3664,18 @@ importers:
|
||||
unplugin-yaml:
|
||||
specifier: 'catalog:'
|
||||
version: 4.1.0(@nuxt/kit@3.20.2(magicast@0.5.2))(esbuild@0.27.2)(rolldown@1.0.0-rc.17)(rollup@4.60.1)(vite@8.0.8(@types/node@25.6.0)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3))
|
||||
valibot:
|
||||
specifier: 'catalog:'
|
||||
version: 1.3.1(typescript@5.9.3)
|
||||
xast-util-to-xml:
|
||||
specifier: 'catalog:'
|
||||
version: 4.0.0
|
||||
xastscript:
|
||||
specifier: 'catalog:'
|
||||
version: 4.0.0
|
||||
yaml:
|
||||
specifier: 'catalog:'
|
||||
version: 2.8.3
|
||||
|
||||
packages/memory-pgvector:
|
||||
dependencies:
|
||||
@@ -21050,9 +21062,9 @@ snapshots:
|
||||
dependencies:
|
||||
electron: 41.2.1
|
||||
|
||||
'@electron-toolkit/tsconfig@2.0.0(@types/node@25.6.0)':
|
||||
'@electron-toolkit/tsconfig@2.0.0(@types/node@24.12.2)':
|
||||
dependencies:
|
||||
'@types/node': 25.6.0
|
||||
'@types/node': 24.12.2
|
||||
|
||||
'@electron-toolkit/utils@4.0.0(electron@41.2.1)':
|
||||
dependencies:
|
||||
@@ -21973,6 +21985,31 @@ snapshots:
|
||||
- supports-color
|
||||
- typescript
|
||||
|
||||
'@intlify/unplugin-vue-i18n@11.0.7(@vue/compiler-dom@3.5.32)(eslint@10.2.1(jiti@2.6.1))(rollup@4.60.1)(typescript@5.9.3)(vite@8.0.8(@types/node@24.12.2)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3))(vue-i18n@11.3.2(vue@3.5.32(typescript@5.9.3)))(vue@3.5.32(typescript@5.9.3))':
|
||||
dependencies:
|
||||
'@eslint-community/eslint-utils': 4.9.1(eslint@10.2.1(jiti@2.6.1))
|
||||
'@intlify/bundle-utils': 11.0.7(vue-i18n@11.3.2(vue@3.5.32(typescript@5.9.3)))
|
||||
'@intlify/shared': 11.3.2
|
||||
'@intlify/vue-i18n-extensions': 8.0.0(@intlify/shared@11.3.2)(@vue/compiler-dom@3.5.32)(vue-i18n@11.3.2(vue@3.5.32(typescript@5.9.3)))(vue@3.5.32(typescript@5.9.3))
|
||||
'@rollup/pluginutils': 5.3.0(rollup@4.60.1)
|
||||
'@typescript-eslint/scope-manager': 8.63.0
|
||||
'@typescript-eslint/typescript-estree': 8.63.0(typescript@5.9.3)
|
||||
debug: 4.4.3(supports-color@10.2.2)
|
||||
fast-glob: 3.3.3
|
||||
pathe: 2.0.3
|
||||
picocolors: 1.1.1
|
||||
unplugin: 2.3.11
|
||||
vite: 8.0.8(@types/node@24.12.2)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3)
|
||||
vue: 3.5.32(typescript@5.9.3)
|
||||
optionalDependencies:
|
||||
vue-i18n: 11.3.2(vue@3.5.32(typescript@5.9.3))
|
||||
transitivePeerDependencies:
|
||||
- '@vue/compiler-dom'
|
||||
- eslint
|
||||
- rollup
|
||||
- supports-color
|
||||
- typescript
|
||||
|
||||
'@intlify/unplugin-vue-i18n@11.0.7(@vue/compiler-dom@3.5.32)(eslint@10.2.1(jiti@2.6.1))(rollup@4.60.1)(typescript@5.9.3)(vite@8.0.8(@types/node@25.6.0)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3))(vue-i18n@11.3.2(vue@3.5.32(typescript@5.9.3)))(vue@3.5.32(typescript@5.9.3))':
|
||||
dependencies:
|
||||
'@eslint-community/eslint-utils': 4.9.1(eslint@10.2.1(jiti@2.6.1))
|
||||
@@ -24032,11 +24069,35 @@ snapshots:
|
||||
transitivePeerDependencies:
|
||||
- magicast
|
||||
|
||||
'@proj-airi/unplugin-fetch@0.2.3(vite@8.0.8(@types/node@24.12.2)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3))':
|
||||
dependencies:
|
||||
ofetch: 1.5.1
|
||||
vite: 8.0.8(@types/node@24.12.2)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3)
|
||||
|
||||
'@proj-airi/unplugin-fetch@0.2.3(vite@8.0.8(@types/node@25.6.0)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3))':
|
||||
dependencies:
|
||||
ofetch: 1.5.1
|
||||
vite: 8.0.8(@types/node@25.6.0)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3)
|
||||
|
||||
'@proj-airi/unplugin-live2d-sdk@0.1.7(@types/node@24.12.2)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3)':
|
||||
dependencies:
|
||||
ofetch: 1.5.1
|
||||
vite: 8.0.8(@types/node@24.12.2)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3)
|
||||
yauzl: 3.3.0
|
||||
transitivePeerDependencies:
|
||||
- '@types/node'
|
||||
- '@vitejs/devtools'
|
||||
- esbuild
|
||||
- jiti
|
||||
- less
|
||||
- sass
|
||||
- sass-embedded
|
||||
- stylus
|
||||
- sugarss
|
||||
- terser
|
||||
- tsx
|
||||
- yaml
|
||||
|
||||
'@proj-airi/unplugin-live2d-sdk@0.1.7(@types/node@25.6.0)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3)':
|
||||
dependencies:
|
||||
ofetch: 1.5.1
|
||||
@@ -25762,6 +25823,12 @@ snapshots:
|
||||
transitivePeerDependencies:
|
||||
- typescript
|
||||
|
||||
'@vitejs/plugin-vue@6.0.6(vite@8.0.8(@types/node@24.12.2)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3))(vue@3.5.32(typescript@5.9.3))':
|
||||
dependencies:
|
||||
'@rolldown/pluginutils': 1.0.0-rc.13
|
||||
vite: 8.0.8(@types/node@24.12.2)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3)
|
||||
vue: 3.5.32(typescript@5.9.3)
|
||||
|
||||
'@vitejs/plugin-vue@6.0.6(vite@8.0.8(@types/node@25.6.0)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3))(vue@3.5.32(typescript@5.9.3))':
|
||||
dependencies:
|
||||
'@rolldown/pluginutils': 1.0.0-rc.13
|
||||
@@ -26037,6 +26104,15 @@ snapshots:
|
||||
transitivePeerDependencies:
|
||||
- vue
|
||||
|
||||
'@vue-macros/devtools@3.1.2(typescript@5.9.3)(vite@8.0.8(@types/node@24.12.2)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3))':
|
||||
dependencies:
|
||||
sirv: 3.0.2
|
||||
vue: 3.5.32(typescript@5.9.3)
|
||||
optionalDependencies:
|
||||
vite: 8.0.8(@types/node@24.12.2)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3)
|
||||
transitivePeerDependencies:
|
||||
- typescript
|
||||
|
||||
'@vue-macros/devtools@3.1.2(typescript@5.9.3)(vite@8.0.8(@types/node@25.6.0)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3))':
|
||||
dependencies:
|
||||
sirv: 3.0.2
|
||||
@@ -28116,7 +28192,7 @@ snapshots:
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
electron-vite@5.0.0(vite@8.0.8(@types/node@25.6.0)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3)):
|
||||
electron-vite@5.0.0(vite@8.0.8(@types/node@24.12.2)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3)):
|
||||
dependencies:
|
||||
'@babel/core': 7.29.0
|
||||
'@babel/plugin-transform-arrow-functions': 7.27.1(@babel/core@7.29.0)
|
||||
@@ -28124,7 +28200,7 @@ snapshots:
|
||||
esbuild: 0.25.12
|
||||
magic-string: 0.30.21
|
||||
picocolors: 1.1.1
|
||||
vite: 8.0.8(@types/node@25.6.0)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3)
|
||||
vite: 8.0.8(@types/node@24.12.2)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3)
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
@@ -34153,11 +34229,6 @@ snapshots:
|
||||
'@unocss/preset-mini': 66.6.8
|
||||
unocss: 66.6.8(@emnapi/core@1.10.0)(@emnapi/runtime@1.10.0)(vite@8.0.8(@types/node@24.12.2)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3))
|
||||
|
||||
unocss-preset-scrollbar@4.0.0(unocss@66.6.8(@emnapi/core@1.10.0)(@emnapi/runtime@1.10.0)(vite@8.0.8(@types/node@25.6.0)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3))):
|
||||
dependencies:
|
||||
'@unocss/preset-mini': 66.6.8
|
||||
unocss: 66.6.8(@emnapi/core@1.10.0)(@emnapi/runtime@1.10.0)(vite@8.0.8(@types/node@25.6.0)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3))
|
||||
|
||||
unocss@66.6.8(@emnapi/core@1.10.0)(@emnapi/runtime@1.10.0)(vite@8.0.8(@types/node@24.12.2)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3)):
|
||||
dependencies:
|
||||
'@unocss/cli': 66.6.8
|
||||
@@ -34224,6 +34295,14 @@ snapshots:
|
||||
unplugin: 2.3.11
|
||||
vite: 8.0.8(@types/node@25.6.0)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3)
|
||||
|
||||
unplugin-combine@2.3.0(esbuild@0.27.2)(rolldown@1.0.0-rc.16)(rollup@4.60.1)(unplugin@2.3.11)(vite@8.0.8(@types/node@24.12.2)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3)):
|
||||
optionalDependencies:
|
||||
esbuild: 0.27.2
|
||||
rolldown: 1.0.0-rc.16
|
||||
rollup: 4.60.1
|
||||
unplugin: 2.3.11
|
||||
vite: 8.0.8(@types/node@24.12.2)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3)
|
||||
|
||||
unplugin-combine@2.3.0(esbuild@0.27.2)(rolldown@1.0.0-rc.16)(rollup@4.60.1)(unplugin@2.3.11)(vite@8.0.8(@types/node@25.6.0)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3)):
|
||||
optionalDependencies:
|
||||
esbuild: 0.27.2
|
||||
@@ -34245,6 +34324,19 @@ snapshots:
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
unplugin-info@1.3.2(esbuild@0.27.2)(rollup@4.60.1)(vite@8.0.8(@types/node@24.12.2)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3)):
|
||||
dependencies:
|
||||
ci-info: 4.4.0
|
||||
git-url-parse: 16.1.0
|
||||
simple-git: 3.36.0
|
||||
unplugin: 2.3.11
|
||||
optionalDependencies:
|
||||
esbuild: 0.27.2
|
||||
rollup: 4.60.1
|
||||
vite: 8.0.8(@types/node@24.12.2)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3)
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
unplugin-info@1.3.2(esbuild@0.27.2)(rollup@4.60.1)(vite@8.0.8(@types/node@25.6.0)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3)):
|
||||
dependencies:
|
||||
ci-info: 4.4.0
|
||||
@@ -34338,6 +34430,17 @@ snapshots:
|
||||
rollup: 2.80.0
|
||||
vite: 8.0.8(@types/node@25.6.0)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3)
|
||||
|
||||
unplugin-yaml@4.1.0(esbuild@0.27.2)(rolldown@1.0.0-rc.16)(rollup@4.60.1)(vite@8.0.8(@types/node@24.12.2)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3)):
|
||||
dependencies:
|
||||
'@rollup/pluginutils': 5.3.0(rollup@4.60.1)
|
||||
unplugin: 3.0.0
|
||||
yaml: 2.8.3
|
||||
optionalDependencies:
|
||||
esbuild: 0.27.2
|
||||
rolldown: 1.0.0-rc.16
|
||||
rollup: 4.60.1
|
||||
vite: 8.0.8(@types/node@24.12.2)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3)
|
||||
|
||||
unplugin-yaml@4.1.0(esbuild@0.27.2)(rolldown@1.0.0-rc.16)(rollup@4.60.1)(vite@8.0.8(@types/node@25.6.0)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3)):
|
||||
dependencies:
|
||||
'@rollup/pluginutils': 5.3.0(rollup@4.60.1)
|
||||
@@ -34576,12 +34679,22 @@ snapshots:
|
||||
- rollup
|
||||
- supports-color
|
||||
|
||||
vite-dev-rpc@1.1.0(vite@8.0.8(@types/node@24.12.2)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3)):
|
||||
dependencies:
|
||||
birpc: 2.9.0
|
||||
vite: 8.0.8(@types/node@24.12.2)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3)
|
||||
vite-hot-client: 2.1.0(vite@8.0.8(@types/node@24.12.2)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3))
|
||||
|
||||
vite-dev-rpc@1.1.0(vite@8.0.8(@types/node@25.6.0)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3)):
|
||||
dependencies:
|
||||
birpc: 2.9.0
|
||||
vite: 8.0.8(@types/node@25.6.0)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3)
|
||||
vite-hot-client: 2.1.0(vite@8.0.8(@types/node@25.6.0)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3))
|
||||
|
||||
vite-hot-client@2.1.0(vite@8.0.8(@types/node@24.12.2)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3)):
|
||||
dependencies:
|
||||
vite: 8.0.8(@types/node@24.12.2)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3)
|
||||
|
||||
vite-hot-client@2.1.0(vite@8.0.8(@types/node@25.6.0)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3)):
|
||||
dependencies:
|
||||
vite: 8.0.8(@types/node@25.6.0)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3)
|
||||
@@ -34627,6 +34740,21 @@ snapshots:
|
||||
- tsx
|
||||
- yaml
|
||||
|
||||
vite-plugin-inspect@11.3.3(vite@8.0.8(@types/node@24.12.2)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3)):
|
||||
dependencies:
|
||||
ansis: 4.2.0
|
||||
debug: 4.4.3(supports-color@10.2.2)
|
||||
error-stack-parser-es: 1.0.5
|
||||
ohash: 2.0.11
|
||||
open: 10.2.0
|
||||
perfect-debounce: 2.1.0
|
||||
sirv: 3.0.2
|
||||
unplugin-utils: 0.3.1
|
||||
vite: 8.0.8(@types/node@24.12.2)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3)
|
||||
vite-dev-rpc: 1.1.0(vite@8.0.8(@types/node@24.12.2)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3))
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
vite-plugin-inspect@11.3.3(vite@8.0.8(@types/node@25.6.0)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3)):
|
||||
dependencies:
|
||||
ansis: 4.2.0
|
||||
@@ -34658,6 +34786,13 @@ snapshots:
|
||||
- typescript
|
||||
- ws
|
||||
|
||||
vite-plugin-mkcert@2.0.0(vite@8.0.8(@types/node@24.12.2)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3)):
|
||||
dependencies:
|
||||
debug: 4.4.3(supports-color@10.2.2)
|
||||
supports-color: 10.2.2
|
||||
undici: 8.1.0
|
||||
vite: 8.0.8(@types/node@24.12.2)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3)
|
||||
|
||||
vite-plugin-mkcert@2.0.0(vite@8.0.8(@types/node@25.6.0)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3)):
|
||||
dependencies:
|
||||
debug: 4.4.3(supports-color@10.2.2)
|
||||
@@ -34676,6 +34811,20 @@ snapshots:
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
vite-plugin-vue-devtools@8.1.1(vite@8.0.8(@types/node@24.12.2)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3))(vue@3.5.32(typescript@5.9.3)):
|
||||
dependencies:
|
||||
'@vue/devtools-core': 8.1.1(vue@3.5.32(typescript@5.9.3))
|
||||
'@vue/devtools-kit': 8.1.1
|
||||
'@vue/devtools-shared': 8.1.1
|
||||
sirv: 3.0.2
|
||||
vite: 8.0.8(@types/node@24.12.2)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3)
|
||||
vite-plugin-inspect: 11.3.3(vite@8.0.8(@types/node@24.12.2)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3))
|
||||
vite-plugin-vue-inspector: 5.3.2(vite@8.0.8(@types/node@24.12.2)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3))
|
||||
transitivePeerDependencies:
|
||||
- '@nuxt/kit'
|
||||
- supports-color
|
||||
- vue
|
||||
|
||||
vite-plugin-vue-devtools@8.1.1(vite@8.0.8(@types/node@25.6.0)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3))(vue@3.5.32(typescript@5.9.3)):
|
||||
dependencies:
|
||||
'@vue/devtools-core': 8.1.1(vue@3.5.32(typescript@5.9.3))
|
||||
@@ -34690,6 +34839,21 @@ snapshots:
|
||||
- supports-color
|
||||
- vue
|
||||
|
||||
vite-plugin-vue-inspector@5.3.2(vite@8.0.8(@types/node@24.12.2)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3)):
|
||||
dependencies:
|
||||
'@babel/core': 7.29.0
|
||||
'@babel/plugin-proposal-decorators': 7.28.0(@babel/core@7.29.0)
|
||||
'@babel/plugin-syntax-import-attributes': 7.28.6(@babel/core@7.29.0)
|
||||
'@babel/plugin-syntax-import-meta': 7.10.4(@babel/core@7.29.0)
|
||||
'@babel/plugin-transform-typescript': 7.28.5(@babel/core@7.29.0)
|
||||
'@vue/babel-plugin-jsx': 1.5.0(@babel/core@7.29.0)
|
||||
'@vue/compiler-dom': 3.5.32
|
||||
kolorist: 1.8.0
|
||||
magic-string: 0.30.21
|
||||
vite: 8.0.8(@types/node@24.12.2)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3)
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
vite-plugin-vue-inspector@5.3.2(vite@8.0.8(@types/node@25.6.0)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3)):
|
||||
dependencies:
|
||||
'@babel/core': 7.29.0
|
||||
@@ -34705,6 +34869,16 @@ snapshots:
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
vite-plugin-vue-layouts@0.11.0(vite@8.0.8(@types/node@24.12.2)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3))(vue-router@5.0.4(@pinia/colada@1.2.1(pinia@3.0.4(typescript@5.9.3)(vue@3.5.32(typescript@5.9.3)))(vue@3.5.32(typescript@5.9.3)))(@vue/compiler-sfc@3.5.32)(pinia@3.0.4(typescript@5.9.3)(vue@3.5.32(typescript@5.9.3)))(vue@3.5.32(typescript@5.9.3)))(vue@3.5.32(typescript@5.9.3)):
|
||||
dependencies:
|
||||
debug: 4.4.3(supports-color@10.2.2)
|
||||
fast-glob: 3.3.3
|
||||
vite: 8.0.8(@types/node@24.12.2)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3)
|
||||
vue: 3.5.32(typescript@5.9.3)
|
||||
vue-router: 5.0.4(@pinia/colada@1.2.1(pinia@3.0.4(typescript@5.9.3)(vue@3.5.32(typescript@5.9.3)))(vue@3.5.32(typescript@5.9.3)))(@vue/compiler-sfc@3.5.32)(pinia@3.0.4(typescript@5.9.3)(vue@3.5.32(typescript@5.9.3)))(vue@3.5.32(typescript@5.9.3))
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
vite-plugin-vue-layouts@0.11.0(vite@8.0.8(@types/node@25.6.0)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3))(vue-router@5.0.4(@pinia/colada@1.2.1(pinia@3.0.4(typescript@5.9.3)(vue@3.5.32(typescript@5.9.3)))(vue@3.5.32(typescript@5.9.3)))(@vue/compiler-sfc@3.5.32)(pinia@3.0.4(typescript@5.9.3)(vue@3.5.32(typescript@5.9.3)))(vue@3.5.32(typescript@5.9.3)))(vue@3.5.32(typescript@5.9.3)):
|
||||
dependencies:
|
||||
debug: 4.4.3(supports-color@10.2.2)
|
||||
@@ -34989,6 +35163,54 @@ snapshots:
|
||||
- vue-tsc
|
||||
- webpack
|
||||
|
||||
vue-macros@3.1.2(@emnapi/core@1.10.0)(@emnapi/runtime@1.10.0)(@vueuse/core@14.2.1(vue@3.5.32(typescript@5.9.3)))(esbuild@0.27.2)(rolldown@1.0.0-rc.16)(rollup@4.60.1)(typescript@5.9.3)(vite@8.0.8(@types/node@24.12.2)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3))(vue-tsc@3.2.6(typescript@5.9.3))(vue@3.5.32(typescript@5.9.3)):
|
||||
dependencies:
|
||||
'@vue-macros/better-define': 3.1.2(@emnapi/core@1.10.0)(@emnapi/runtime@1.10.0)(vue@3.5.32(typescript@5.9.3))
|
||||
'@vue-macros/boolean-prop': 3.1.2(vue@3.5.32(typescript@5.9.3))
|
||||
'@vue-macros/chain-call': 3.1.2(vue@3.5.32(typescript@5.9.3))
|
||||
'@vue-macros/common': 3.1.2(vue@3.5.32(typescript@5.9.3))
|
||||
'@vue-macros/config': 3.1.2(vue@3.5.32(typescript@5.9.3))
|
||||
'@vue-macros/define-emit': 3.1.2(vue@3.5.32(typescript@5.9.3))
|
||||
'@vue-macros/define-models': 3.1.2(@vueuse/core@14.2.1(vue@3.5.32(typescript@5.9.3)))(vue@3.5.32(typescript@5.9.3))
|
||||
'@vue-macros/define-prop': 3.1.2(@emnapi/core@1.10.0)(@emnapi/runtime@1.10.0)(vue@3.5.32(typescript@5.9.3))
|
||||
'@vue-macros/define-props': 3.1.2(@vue-macros/reactivity-transform@3.1.2(vue@3.5.32(typescript@5.9.3)))(vue@3.5.32(typescript@5.9.3))
|
||||
'@vue-macros/define-props-refs': 3.1.2(vue@3.5.32(typescript@5.9.3))
|
||||
'@vue-macros/define-render': 3.1.2(vue@3.5.32(typescript@5.9.3))
|
||||
'@vue-macros/define-slots': 3.1.2(vue@3.5.32(typescript@5.9.3))
|
||||
'@vue-macros/define-stylex': 3.1.2(vue@3.5.32(typescript@5.9.3))
|
||||
'@vue-macros/devtools': 3.1.2(typescript@5.9.3)(vite@8.0.8(@types/node@24.12.2)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3))
|
||||
'@vue-macros/export-expose': 3.1.2(vue@3.5.32(typescript@5.9.3))
|
||||
'@vue-macros/export-props': 3.1.2(vue@3.5.32(typescript@5.9.3))
|
||||
'@vue-macros/export-render': 3.1.2(vue@3.5.32(typescript@5.9.3))
|
||||
'@vue-macros/hoist-static': 3.1.2(vue@3.5.32(typescript@5.9.3))
|
||||
'@vue-macros/jsx-directive': 3.1.2(typescript@5.9.3)
|
||||
'@vue-macros/named-template': 3.1.2(vue@3.5.32(typescript@5.9.3))
|
||||
'@vue-macros/reactivity-transform': 3.1.2(vue@3.5.32(typescript@5.9.3))
|
||||
'@vue-macros/script-lang': 3.1.2(vue@3.5.32(typescript@5.9.3))
|
||||
'@vue-macros/setup-block': 3.1.2(vue@3.5.32(typescript@5.9.3))
|
||||
'@vue-macros/setup-component': 3.1.2(vue@3.5.32(typescript@5.9.3))
|
||||
'@vue-macros/setup-sfc': 3.1.2(vue@3.5.32(typescript@5.9.3))
|
||||
'@vue-macros/short-bind': 3.1.2(vue@3.5.32(typescript@5.9.3))
|
||||
'@vue-macros/short-emits': 3.1.2(vue@3.5.32(typescript@5.9.3))
|
||||
'@vue-macros/short-vmodel': 3.1.2(vue@3.5.32(typescript@5.9.3))
|
||||
'@vue-macros/volar': 3.1.2(typescript@5.9.3)(vue-tsc@3.2.6(typescript@5.9.3))(vue@3.5.32(typescript@5.9.3))
|
||||
unplugin: 2.3.11
|
||||
unplugin-combine: 2.3.0(esbuild@0.27.2)(rolldown@1.0.0-rc.16)(rollup@4.60.1)(unplugin@2.3.11)(vite@8.0.8(@types/node@24.12.2)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3))
|
||||
unplugin-vue-define-options: 3.1.2(vue@3.5.32(typescript@5.9.3))
|
||||
vue: 3.5.32(typescript@5.9.3)
|
||||
transitivePeerDependencies:
|
||||
- '@emnapi/core'
|
||||
- '@emnapi/runtime'
|
||||
- '@rspack/core'
|
||||
- '@vueuse/core'
|
||||
- esbuild
|
||||
- rolldown
|
||||
- rollup
|
||||
- typescript
|
||||
- vite
|
||||
- vue-tsc
|
||||
- webpack
|
||||
|
||||
vue-macros@3.1.2(@emnapi/core@1.10.0)(@emnapi/runtime@1.10.0)(@vueuse/core@14.2.1(vue@3.5.32(typescript@5.9.3)))(esbuild@0.27.2)(rolldown@1.0.0-rc.16)(rollup@4.60.1)(typescript@5.9.3)(vite@8.0.8(@types/node@25.6.0)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3))(vue-tsc@3.2.6(typescript@5.9.3))(vue@3.5.32(typescript@5.9.3)):
|
||||
dependencies:
|
||||
'@vue-macros/better-define': 3.1.2(@emnapi/core@1.10.0)(@emnapi/runtime@1.10.0)(vue@3.5.32(typescript@5.9.3))
|
||||
|
||||
@@ -9,6 +9,7 @@ export default defineConfig({
|
||||
'packages/cap-vite',
|
||||
'packages/ccc',
|
||||
'packages/core-agent',
|
||||
'packages/i18n',
|
||||
'packages/better-ws',
|
||||
'packages/plugin-sdk',
|
||||
'packages/plugin-sdk-tamagotchi',
|
||||
|
||||
Reference in New Issue
Block a user