app-parser.ts 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106
  1. import { AppConfig } from 'src/app/app.config';
  2. import { xmlParser } from '.';
  3. import { ApparatusEntry, Note, Reading, XMLElement } from '../../models/evt-models';
  4. import { getOuterHTML } from '../../utils/dom-utils';
  5. import { removeSpaces } from '../../utils/xml-utils';
  6. import { AttributeParser, EmptyParser, NoteParser } from './basic-parsers';
  7. import { createParser, getID, Parser } from './parser-models';
  8. @xmlParser('rdg', RdgParser)
  9. export class RdgParser extends EmptyParser implements Parser<XMLElement> {
  10. private readingGroupTagName = 'rdgGrp';
  11. attributeParser = createParser(AttributeParser, this.genericParse);
  12. public parse(rdg: XMLElement): Reading {
  13. return {
  14. type: Reading,
  15. id: getID(rdg),
  16. attributes: this.attributeParser.parse(rdg),
  17. witIDs: this.parseReadingWitnesses(rdg) || [],
  18. content: this.parseAppReadingContent(rdg),
  19. significant: this.isReadingSignificant(rdg),
  20. class: rdg.tagName.toLowerCase(),
  21. };
  22. }
  23. private parseReadingWitnesses(rdg: XMLElement) {
  24. return rdg.getAttribute('wit')?.split('#')
  25. .map((el) => removeSpaces(el))
  26. .filter((el) => el.length !== 0);
  27. }
  28. private parseAppReadingContent(rdg: XMLElement) {
  29. return Array.from(rdg.childNodes)
  30. .map((child: XMLElement) => this.genericParse(child));
  31. }
  32. private isReadingSignificant(rdg: XMLElement): boolean {
  33. const notSignificantReadings = AppConfig.evtSettings.edition.notSignificantVariants;
  34. let isSignificant = true;
  35. if (notSignificantReadings.length > 0) {
  36. isSignificant = this.isSignificant(notSignificantReadings, rdg.attributes);
  37. if (isSignificant && rdg.parentElement.tagName === this.readingGroupTagName) {
  38. isSignificant = this.isSignificant(notSignificantReadings, rdg.parentElement.attributes);
  39. }
  40. }
  41. return isSignificant;
  42. }
  43. private isSignificant(notSignificantReading: string[], attributes: NamedNodeMap): boolean {
  44. return !Array.from(attributes).some(({ name, value }) => notSignificantReading.includes(`${name}=${value}`));
  45. }
  46. }
  47. @xmlParser('evt-apparatus-entry-parser', AppParser)
  48. export class AppParser extends EmptyParser implements Parser<XMLElement> {
  49. private noteTagName = 'note';
  50. private appEntryTagName = 'app';
  51. private readingTagName = 'rdg';
  52. private lemmaTagName = 'lem';
  53. attributeParser = createParser(AttributeParser, this.genericParse);
  54. noteParser = createParser(NoteParser, this.genericParse);
  55. rdgParser = createParser(RdgParser, this.genericParse);
  56. public parse(appEntry: XMLElement): ApparatusEntry {
  57. return {
  58. type: ApparatusEntry,
  59. id: getID(appEntry),
  60. attributes: this.attributeParser.parse(appEntry),
  61. content: [],
  62. lemma: this.parseLemma(appEntry),
  63. readings: this.parseReadings(appEntry),
  64. notes: this.parseAppNotes(appEntry),
  65. originalEncoding: getOuterHTML(appEntry),
  66. class: appEntry.tagName.toLowerCase(),
  67. nestedAppsIDs: this.getNestedAppsIDs(appEntry),
  68. };
  69. }
  70. private getNestedAppsIDs(app: XMLElement): string[] {
  71. const nesApps = app.querySelectorAll('app');
  72. return Array.from(nesApps).map((a: XMLElement) => getID(a));
  73. }
  74. private parseAppNotes(appEntry: XMLElement): Note[] {
  75. const notes = Array.from(appEntry.children)
  76. .filter(({ tagName }) => tagName === this.noteTagName)
  77. .map((note: XMLElement) => this.noteParser.parse(note));
  78. return notes;
  79. }
  80. private parseLemma(appEntry: XMLElement): Reading {
  81. return appEntry.querySelector(`${this.lemmaTagName}`) ?
  82. this.rdgParser.parse(appEntry.querySelector(`${this.lemmaTagName}`)) : undefined;
  83. }
  84. private parseReadings(appEntry: XMLElement): Reading[] {
  85. return Array.from(appEntry.querySelectorAll(`${this.readingTagName}`))
  86. .filter((el) => el.closest(this.appEntryTagName) === appEntry)
  87. .map((rdg: XMLElement) => this.rdgParser.parse(rdg));
  88. }
  89. }