import { AndRule, type DataRef, LiteralRule, OrRule, type Rule, type RuleTestResponse, } from '@os-team/lexical-rules'; import SRule from '../rules/SRule.js'; import SystemLiteralRule from '../rules/SystemLiteralRule.js'; import PubidLiteralRule from '../rules/PubidLiteralRule.js'; import type { Parser } from './Parser.js'; export interface SystemExternalID { type: 'SYSTEM_EXTERNAL_ID'; systemValue: string; } export interface PublicExternalID { type: 'PUBLIC_EXTERNAL_ID'; pubidValue: string; systemValue: string; } export type ExternalID = SystemExternalID | PublicExternalID; /** * The external entity declaration. * See https://www.w3.org/TR/xml/#NT-ExternalID */ class ExternalIDParser implements Parser { private readonly rule: Rule< [string, undefined, string] | [string, undefined, string, undefined, string] >; public constructor() { const systemRule = new LiteralRule('SYSTEM'); // 'SYSTEM' const sRule = new SRule('+'); // S const systemLiteralRule = new SystemLiteralRule(); // SystemLiteral const systemExtIdRule = new AndRule([systemRule, sRule, systemLiteralRule]); // 'SYSTEM' S SystemLiteral const publicRule = new LiteralRule('PUBLIC'); // 'PUBLIC' const pubidLieralRule = new PubidLiteralRule(); // PubidLiteral const publicExtIdRule = new AndRule([ publicRule, sRule, pubidLieralRule, sRule, systemLiteralRule, ]); // 'PUBLIC' S PubidLiteral S SystemLiteral this.rule = new OrRule([systemExtIdRule, publicExtIdRule]); // 'SYSTEM' S SystemLiteral | 'PUBLIC' S PubidLiteral S SystemLiteral } public test(ref: DataRef, pos: number): RuleTestResponse { const [isValid, nextPos, res] = this.rule.test(ref, pos); if (!isValid || res === undefined) return [false, nextPos]; let externalID: ExternalID; if (res.length === 5) { const [, , pubidValue, , systemValue] = res; externalID = { type: 'PUBLIC_EXTERNAL_ID', pubidValue, systemValue }; } else { const [, , systemValue] = res; externalID = { type: 'SYSTEM_EXTERNAL_ID', systemValue }; } return [true, nextPos, externalID]; } public build(data: ExternalID) { return data.type === 'SYSTEM_EXTERNAL_ID' ? `SYSTEM "${data.systemValue.replaceAll('"', "'")}"` : `PUBLIC "${data.pubidValue.replaceAll( '"', "'" )}" "${data.systemValue.replaceAll('"', "'")}"`; } } export default ExternalIDParser;