diff --git a/build/gen-hanzi-data/stroke-type.ts b/build/gen-hanzi-data/stroke-type.ts index 6e35b9984b12904222212acf92cfdf1af9b6d4ec..e6e3b93e15466e201437f847248f2a9422a484e4 100644 --- a/build/gen-hanzi-data/stroke-type.ts +++ b/build/gen-hanzi-data/stroke-type.ts @@ -3,7 +3,7 @@ import cncharOrder from 'cnchar-order' import cncharTrad from 'cnchar-trad' import { type StrokeTypeMaybeUnclean, - type StrokeType + StrokeType } from '../../src-common/stroke-encodings' import { strokeTypeOverrides } from './stroke-type-overrides' import { compat } from './blocks/index' @@ -34,7 +34,11 @@ export function queryStrokeTypes ( if (override !== undefined) { return override } - return queryCncharStrokeTypes(compatChar) + let strokes = queryCncharStrokeTypes(compatChar) + if (expectedLen !== undefined) { + strokes = addGrassHengIfMissing(expectedLen, strokes) + } + return strokes } function queryCncharStrokeTypes (char: string): StrokeType[] { @@ -42,9 +46,43 @@ function queryCncharStrokeTypes (char: string): StrokeType[] { if (!Array.isArray(strokeShapes)) { return [] } - // if cnchar has multiple stroke types, only keep first, and map to a closed - // set of strokes without duplicate stroke kinds - return strokeShapes.map(t => normalizeStroke( - t.split('|')[0] as StrokeTypeMaybeUnclean - )) + return strokeShapes.map(t => + // if cnchar has multiple stroke types, only keep first, and map to a closed + // set of strokes without duplicate stroke kinds + normalizeStroke( + t.split('|')[0] as StrokeTypeMaybeUnclean + ) + ) +} + +const traditionalGrassStrokes = [ + StrokeType.SHU, + StrokeType.HENG, + StrokeType.SHU, + StrokeType.HENG +] + +/** + * If the character has one stroke less than expected, and the first strokes + * are consistent with a simplified grass radical, then return a new array that + * starts with the four strokes of a traditional grass radical and then + * continues with the given strokes starting from the fourth stroke. + * + * If the length is not one short by one, or if the start does not look like a + * simplified grass radical, then return the given strokes array unchanged. + */ +function addGrassHengIfMissing ( + expectedLen: number, + strokes: StrokeType[] +): StrokeType[] { + const applyPatch = + // HanziWriter has one more stroke + (strokes.length + 1) === expectedLen && + // and the strokes look like the simplified version + strokes[0] === StrokeType.HENG && + strokes[1] === StrokeType.SHU && + strokes[2] === StrokeType.SHU + return applyPatch + ? [...traditionalGrassStrokes, ...strokes.slice(3)] + : strokes } diff --git a/test/data/stroke-type.test.ts b/test/data/stroke-type.test.ts index c8da210a36aeebbfde101cb357325d7a558f86ee..14cbb7c608b5846d9a051cb37b32e413f39ddcd8 100644 --- a/test/data/stroke-type.test.ts +++ b/test/data/stroke-type.test.ts @@ -1,6 +1,9 @@ import { StrokeType } from '../../src-common/stroke-encodings' import { queryStrokeTypes } from '../../build/gen-hanzi-data/stroke-type' import { cjkRadicals, kangxiRadicals } from './radicals' +import { + queryPatchedHanziWriterData +} from '../../build/gen-hanzi-data/patched-hanzi-writer' describe('Kangxi radicals', () => { describe('have non-empty strokes', () => { @@ -53,3 +56,38 @@ describe('CJK Radicals Supplement radicals', () => { expect(queryStrokeTypes(char)).toEqual(strokes) } }) + +describe('Traditional characters with grass radical at the start', () => { + const chars = [ + '葉', + '蓮', + '夢', + '觀', + '歡', + '莊', + '藥', + '蓋', + '藝', + '華', + '蔭', + '舊', + '蘭', + '蘋', + '蕩', + '蔣', + '蕭', + '薑' + ] + for (const char of chars) { + test(char, async () => { + const hanziWriterCount = (await queryPatchedHanziWriterData(char)) + .strokes.length + expect(queryStrokeTypes(char, hanziWriterCount).slice(0, 4)).toEqual([ + StrokeType.SHU, + StrokeType.HENG, + StrokeType.SHU, + StrokeType.HENG + ]) + }) + } +})