diff --git a/__test__/index.test.ts b/__test__/index.test.ts index a3e4ddd..e1b1cca 100644 --- a/__test__/index.test.ts +++ b/__test__/index.test.ts @@ -5,7 +5,7 @@ import * as url from 'node:url'; import yaml from 'js-yaml'; import { describe, test, expect } from '@jest/globals'; -import { parse, stringify } from '../src'; +import { parse, parseToMap, stringify, WikiArrayItem, WikiItem } from '../src'; const __dirname = url.fileURLToPath(new URL('.', import.meta.url)); @@ -86,3 +86,33 @@ describe('Wiki stringify', () => { }); } }); + +describe('parse map', () => { + const item = new WikiItem('A', '', 'array'); + + item.values = [new WikiArrayItem(undefined, 'b'), new WikiArrayItem(undefined, 'c')]; + + const expected = { type: '', data: new Map([['A', item]]) }; + + test('should merge keys', () => { + const o = parseToMap(`{{Infobox +|A= b +| A=c +}} +`); + + expect(o).toEqual(expected); + }); + + test('should merge previous array keys', () => { + const o = parseToMap(`{{Infobox +|A= { +[b] +} +| A=c +}} +`); + + expect(o).toEqual(expected); + }); +}); diff --git a/package.json b/package.json index 7c82ed3..d63e67d 100644 --- a/package.json +++ b/package.json @@ -33,6 +33,9 @@ "lint-staged": { "*.{md,js,jsx,ts,tsx,json,yml,yaml}": [ "prettier --ignore-path ./.prettierignore --write" + ], + "*.{js,ts}": [ + "eslint --fix" ] }, "files": [ diff --git a/src/index.ts b/src/index.ts index 981d175..6e63328 100644 --- a/src/index.ts +++ b/src/index.ts @@ -8,13 +8,32 @@ import { WikiSyntaxError, } from './error'; import { prefix, suffix } from './shared'; -import type { Wiki, WikiItemType } from './types'; +import type { Wiki, WikiItemType, WikiMap } from './types'; import { WikiArrayItem, WikiItem } from './types'; export * from './types'; export * from './error'; export { stringify } from './stringify'; +/** 解析 wiki 文本,以 `Map` 类型返回解析结果。 会合并重复出现的 key */ +export function parseToMap(s: string): WikiMap { + const w = parse(s); + + const data = new Map(); + + for (const item of w.data) { + const previous = data.get(item.key); + if (!previous) { + data.set(item.key, item); + continue; + } + + previous.push(item); + } + + return { type: w.type, data }; +} + export function parse(s: string): Wiki { const wiki: Wiki = { type: '', diff --git a/src/types.ts b/src/types.ts index d9722fb..4c35874 100644 --- a/src/types.ts +++ b/src/types.ts @@ -3,6 +3,12 @@ export interface Wiki { data: WikiItem[]; } +/** JS 的 map 会按照插入顺序排序 */ +export interface WikiMap { + type: string; + data: Map; +} + export type WikiItemType = 'array' | 'object'; export class WikiArrayItem { @@ -36,4 +42,26 @@ export class WikiItem { } } } + + private convertToArray() { + if (this.array) { + return; + } + + this.array = true; + this.values ??= []; + + this.values.push(new WikiArrayItem(undefined, this.value)); + this.value = undefined; + } + + push(item: WikiItem) { + this.convertToArray(); + + if (item.array) { + this.values?.push(...(item.values ?? [])); + } else { + this.values?.push(new WikiArrayItem(undefined, item.value)); + } + } }