UNPKG

@rxap/xml-parser

Version:

Provides a set of decorators and services for parsing and serializing XML documents into TypeScript classes. It simplifies the process of mapping XML elements and attributes to class properties, handling data validation, and serializing objects back into

146 lines 8.45 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.ElementChildrenTextContentSerializer = exports.ElementChildrenTextContentParser = void 0; exports.AssertElementChildrenTextContentOptions = AssertElementChildrenTextContentOptions; exports.ElementChildrenTextContent = ElementChildrenTextContent; const tslib_1 = require("tslib"); const mixin_1 = require("@rxap/mixin"); const reflect_metadata_1 = require("@rxap/reflect-metadata"); const utilities_1 = require("@rxap/utilities"); const error_1 = require("../error"); const metadata_keys_1 = require("./metadata-keys"); const children_element_mixin_1 = require("./mixins/children-element.mixin"); const tag_element_mixin_1 = require("./mixins/tag-element.mixin"); const text_content_element_mixin_1 = require("./mixins/text-content-element.mixin"); const required_property_1 = require("./required-property"); const add_parser_to_metadata_1 = require("./utilities/add-parser-to-metadata"); const add_serializer_to_metadata_1 = require("./utilities/add-serializer-to-metadata"); /** * Asserts that the provided `options` object conforms to the `ElementChildrenTextContentOptions` type. * * This function checks if the given `options` object meets the criteria of being an instance of `ElementChildrenTextContentOptions` by verifying the presence of a `tag` property, which is essential for identifying the object as a valid `ElementChildrenTextContentOptions`. * * @param options - The object to be validated against the `ElementChildrenTextContentOptions` type. * @throws {Error} Throws an error if the `options` object does not have the required `tag` property, indicating that it is not a valid `ElementChildrenTextContentOptions`. * */ function AssertElementChildrenTextContentOptions(options) { if (!(0, tag_element_mixin_1.IsTagElementOptions)(options)) { throw new Error('The object is not a ElementChildrenTextContentOptions. The required property "tag" is missing!'); } } let ElementChildrenTextContentParser = class ElementChildrenTextContentParser { constructor(propertyKey, options) { this.propertyKey = propertyKey; this.options = options; this.parse = this.parse.bind(this); Reflect.set(this.parse, 'propertyKey', propertyKey); } parse(xmlParser, element, parsedElement) { var _a; const elementChildren = this.getChildren(element); if (!elementChildren) { throw new error_1.RxapXmlParserValidateRequiredError(`The child group element '${this.options.group}' is required for ${parsedElement.__tag}!`, parsedElement.__tag); } let list = elementChildren.filter(child => child.hasName(this.tag)).map(child => { const rawValue = child.getTextContent(undefined, true); if (rawValue !== undefined) { return this.parseValue(rawValue); } return undefined; }).filter(item => item !== undefined); if (list.length === 0) { list = (_a = this.defaultValue) !== null && _a !== void 0 ? _a : []; } if (this.required && list.length === 0) { throw new error_1.RxapXmlParserValidateRequiredError(`Some element child <${this.tag}> is required in <${parsedElement.__tag}>!`, parsedElement.__tag); } if (this.min !== null && this.min > list.length) { throw new error_1.RxapXmlParserValidateError(`Element child <${this.tag}> should be at least ${this.min} in <${parsedElement.__tag}>!`, parsedElement.__tag); } if (this.max !== null && this.max > list.length) { throw new error_1.RxapXmlParserValidateError(`Element child <${this.tag}> should be at most ${this.max} in <${parsedElement.__tag}>!`, parsedElement.__tag); } // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore parsedElement[this.propertyKey] = list; return parsedElement; } }; exports.ElementChildrenTextContentParser = ElementChildrenTextContentParser; exports.ElementChildrenTextContentParser = ElementChildrenTextContentParser = tslib_1.__decorate([ (0, mixin_1.Mixin)(text_content_element_mixin_1.TextContentElementMixin, tag_element_mixin_1.TagElementMixin, children_element_mixin_1.ChildrenElementMixin), tslib_1.__metadata("design:paramtypes", [String, Object]) ], ElementChildrenTextContentParser); let ElementChildrenTextContentSerializer = class ElementChildrenTextContentSerializer { constructor(propertyKey, options) { this.propertyKey = propertyKey; this.options = options; this.serialize = this.serialize.bind(this); Reflect.set(this.serialize, 'propertyKey', propertyKey); } serialize(xmlParser, element, parsedElement) { // @ts-expect-error the propertyKey is set by the property decorator const children = parsedElement[this.propertyKey]; if (children) { if (!Array.isArray(children)) { throw new error_1.RxapXmlSerializerValidateError(`The property ${this.propertyKey} is not an array!`, parsedElement.__tag); } element = this.coerceGroup(element); for (const child of children) { element.addChildTextContent(this.tag, this.serializeValue(child)); } } else if (this.required) { throw new error_1.RxapXmlSerializerValidateRequiredError(`Some element child <${this.tag}> is required in <${parsedElement.__tag}>!`, parsedElement.__tag); } } }; exports.ElementChildrenTextContentSerializer = ElementChildrenTextContentSerializer; exports.ElementChildrenTextContentSerializer = ElementChildrenTextContentSerializer = tslib_1.__decorate([ (0, mixin_1.Mixin)(text_content_element_mixin_1.TextContentElementMixin, tag_element_mixin_1.TagElementMixin, children_element_mixin_1.ChildrenElementMixin), tslib_1.__metadata("design:paramtypes", [String, Object]) ], ElementChildrenTextContentSerializer); /** * Decorator factory that creates a decorator to parse the text content of children elements of a specified XML/HTML tag. * * This decorator can be applied to properties within classes that are intended to parse XML/HTML data. It configures * the parsing behavior based on the provided options or defaults derived from the property name if no options are specified. * * @param {Partial<ElementChildrenTextContentParserOptions<Value>> | string} optionsOrString - Configuration options for the decorator, * or a string specifying the tag name of the element whose children's text content should be parsed. * If a string is provided, it is used as the tag name. If an object is provided, it can specify various parsing options. * If omitted, the tag name is derived by dasherizing the property name. * * @returns {Function} A class property decorator that configures the parser for the specified property. * * ### Usage * * ```typescript * @ElementChildrenTextContent({ tag: 'item', required: true }) * items: string[]; * ``` * * In the above example, the decorator will configure the parser to parse the text content of children of `<item>` elements. * The `required` option specifies that at least one `<item>` element must be present. */ function ElementChildrenTextContent(optionsOrString) { return function (target, propertyKey) { let options = optionsOrString === undefined ? { tag: (0, utilities_1.dasherize)(propertyKey) } : typeof optionsOrString === 'string' ? { tag: optionsOrString } : optionsOrString; options = (0, utilities_1.deepMerge)(options, (0, reflect_metadata_1.getMetadata)(metadata_keys_1.ElementParserMetaData.OPTIONS, target, propertyKey) || {}); if (!options.tag) { options.tag = (0, utilities_1.dasherize)(propertyKey); } AssertElementChildrenTextContentOptions(options); const parser = new ElementChildrenTextContentParser(propertyKey, options); (0, add_parser_to_metadata_1.AddParserToMetadata)(parser, target); const serializer = new ElementChildrenTextContentSerializer(propertyKey, options); (0, add_serializer_to_metadata_1.AddSerializerToMetadata)(serializer, target); if (options.required) { (0, required_property_1.RequiredProperty)()(target, propertyKey); } }; } //# sourceMappingURL=element-children-text-content.js.map