aboutsummaryrefslogtreecommitdiffstats
path: root/src/lib/vendor/rss
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/vendor/rss')
-rw-r--r--src/lib/vendor/rss/rss.example.md110
-rw-r--r--src/lib/vendor/rss/rss.ts231
-rw-r--r--src/lib/vendor/rss/xml.example.md242
-rw-r--r--src/lib/vendor/rss/xml.ts144
4 files changed, 0 insertions, 727 deletions
diff --git a/src/lib/vendor/rss/rss.example.md b/src/lib/vendor/rss/rss.example.md
deleted file mode 100644
index 4e532fd..0000000
--- a/src/lib/vendor/rss/rss.example.md
+++ /dev/null
@@ -1,110 +0,0 @@
-```ts
-const doc = new XMLDocumentRoot().child(
- new XMLDeclaration().version().encoding(),
- new RSSRootElement()
- .channel(
- new RSSChannelElement(
- 'Latest blog posts for 7222e800',
- 'Some Description Here',
- 'https://estrogen.zone/~mem/blog/'
- )
- .pubDate(new Date('2026-01-14T15:53:57Z') /* When the last item was published */)
- .lastBuildDate(new Date() /* When this file was last updated - usually when your build process last ran */)
- .language('en')
- .child(new XMLElement('nonStandardElement').attribute('non-standard', 'true'))
- .items(
- new RSSItemElement(
- 'Some Fancy Blog Post Title',
- 'Imagine some crazy fun thing here that is guaranteed to get the reader hooked. A really good blurb would be here in practice.',
- 'https://estrogen.zone/~mem/blog/1234567890-your-fancy-post-slug/',
- )
- .author('7222e800')
- .guid('https://estrogen.zone/~mem/blog/1234567890', true)
- .pubDate(new Date('2026-01-14T15:53:57Z')),
- new RSSItemElement(
- 'Domesticated Catgirl Transport',
- 'Smuggling multiple thousands of catgirls over borders isn\'t an easy feat. Here\'s how we did it.',
- 'https://estrogen.zone/~mem/blog/1234566789-catgirl-smuggling-operation/',
- )
- .author('CatgirlSmuggler9000')
- .author('7222e800')
- .guid('https://estrogen.zone/~mem/blog/1234566789', true)
- .pubDate(new Date('2026-01-14T15:53:57Z')),
- )
- )
-);
-const xml = doc.toString();
-```
-
-will output
-
-```xml
-<?xml version="1.0" encoding="UTF-8" ?>
-<rss version="2.0"
- xmlns:content="http://purl.org/rss/1.0/modules/content/">
- <channel>
- <title>
- Latest blog posts for 7222e800
- </title>
- <description>
- Some Description Here
- </description>
- <link>
- https://estrogen.zone/~mem/blog/
- </link>
- <pubDate>
- Wed, 14 Jan 2026 15:53:57 GMT
- </pubDate>
- <lastBuildDate>
- Mon, 26 Jan 2026 04:45:27 GMT
- </lastBuildDate>
- <language>
- en
- </language>
- <nonStandardElement non-standard="true" />
- <item>
- <title>
- Some Fancy Blog Post Title
- </title>
- <description>
- Imagine some crazy fun thing here that is guaranteed to get the reader hooked. A really good blurb would be here in practice.
- </description>
- <link>
- https://estrogen.zone/~mem/blog/1234567890-your-fancy-post-slug/
- </link>
- <author>
- 7222e800
- </author>
- <guid isPermaLink="true">
- https://estrogen.zone/~mem/blog/1234567890
- </guid>
- <pubDate>
- Wed, 14 Jan 2026 15:53:57 GMT
- </pubDate>
- </item>
- <item>
- <title>
- Domesticated Catgirl Transport
- </title>
- <description>
- Smuggling multiple thousands of catgirls over borders isn't an easy feat. Here's how we did it.
- </description>
- <link>
- https://estrogen.zone/~mem/blog/1234566789-catgirl-smuggling-operation/
- </link>
- <author>
- CatgirlSmuggler9000
- </author>
- <author>
- 7222e800
- </author>
- <guid isPermaLink="true">
- https://estrogen.zone/~mem/blog/1234566789
- </guid>
- <pubDate>
- Wed, 14 Jan 2026 15:32:57 GMT
- </pubDate>
- </item>
- </channel>
-</rss>
-```
diff --git a/src/lib/vendor/rss/rss.ts b/src/lib/vendor/rss/rss.ts
deleted file mode 100644
index f44a6d2..0000000
--- a/src/lib/vendor/rss/rss.ts
+++ /dev/null
@@ -1,231 +0,0 @@
-import { XMLElement, XMLRootElement, XMLTagType, XMLText } from './xml';
-
-class XMLElementWithRSSUtil extends XMLElement {
- protected replaceChildByTagName(tag: string) {
- const existingEl = this.findElementChild(v => v.tagName === tag);
- if (existingEl) {
- existingEl.children.length = 0;
- existingEl.attributes.clear();
- }
- const el = existingEl ?? new XMLElement(tag);
- if (!existingEl)
- this.child(el)
- return el
- }
-}
-export class RSSItemElement extends XMLElementWithRSSUtil {
- public constructor(title: string | null, description: string | null, link: string | URL | null) {
- super("item");
- if (title !== null)
- this.title(title);
- if (description !== null)
- this.description(description)
- if (link !== null)
- this.link(link)
- }
- /** Replaces the title of the item */
- public title(title: string) {
- this.replaceChildByTagName('title').child(new XMLText(title))
- return this;
- }
- /** Replaces the link to the item */
- public link(link: string | URL) {
- this.replaceChildByTagName('link').child(new XMLText(typeof link === 'string' ? link : link.href))
- return this;
- }
- /** Sets the description of the item, replacing it if it already exists */
- public description(description: string) {
- this.replaceChildByTagName('description').child(new XMLText(description))
- return this;
- }
- /** Sets the URL for the comment section of an item, replacing it if it already exists */
- public comments(comments: string | URL) {
- return this.child(new XMLElement('comments').child(new XMLText(typeof comments === 'string' ? comments : comments.href)));
- }
- /** Sets the timestamp where the most recent item in the channel was published, replacing it if it already exists */
- public pubDate(pubDate: Date) {
- this.replaceChildByTagName('pubDate').child(new XMLText(pubDate.toUTCString()))
- return this;
- }
- /** Specifies a third-party source for the item. */
- public source(sourceName: string, sourceUrl: string | URL) {
- return this.child(new XMLElement('source').attribute('url', typeof sourceUrl === 'string' ? sourceUrl : sourceUrl.href).child(new XMLText(sourceName)))
- }
- /** Adds a category to the post */
- public category(
- category: string,
- ) {
- return this.child(new XMLElement('category').child(new XMLText(category)));
- }
- /** Adds a author to the post */
- public author(
- author: string,
- ) {
- return this.child(new XMLElement('author').child(new XMLText(author)));
- }
- /** Adds a unique ID to the post. This ID must be globally unique, but has no format specifications. */
- public guid(
- id: string,
- /** If this is a permanent link to the post. If true, this must be a URL that permanently points to this item. */
- isPermaLink: boolean
- ) {
- return this.child(new XMLElement('guid').child(new XMLText(id)).attribute('isPermaLink', isPermaLink ? 'true' : 'false'));
- }
- /** Adds a media file to be included with an item */
- public enclosure(
- url: string,
- mimeType: string,
- /** in bytes */
- length: number
- ) {
- return this.child(
- new XMLElement('enclosure')
- .attribute('url', url)
- .attribute('length', length.toString())
- .attribute('type', mimeType)
- )
- }
-}
-export class RSSChannelElement extends XMLElementWithRSSUtil {
- public constructor(title: string | null, description: string | null, link: URL | string | null) {
- super("channel");
- if (title !== null)
- this.title(title);
- if (description !== null)
- this.description(description)
- if (link !== null)
- this.link(link)
- }
- /** Replaces the title of the channel */
- public title(title: string) {
- this.replaceChildByTagName('title').child(new XMLText(title))
- return this;
- }
- /** Replaces the link to the channel */
- public link(link: string | URL) {
- this.replaceChildByTagName('link').child(new XMLText(typeof link === 'string' ? link : link.href))
- return this;
- }
- /** Sets the description of the channel, replacing it if it already exists */
- public description(description: string) {
- this.replaceChildByTagName('description').child(new XMLText(description))
- return this;
- }
- /** Sets the timestamp where the most recent item in the channel was published, replacing it if it already exists */
- public pubDate(pubDate: Date) {
- this.replaceChildByTagName('pubDate').child(new XMLText(pubDate.toUTCString()))
- return this;
- }
- /** Sets the timestamp where the RSS file was last modified in any way, replacing it if it already exists */
- public lastBuildDate(lastBuildDate: Date) {
- this.replaceChildByTagName('lastBuildDate').child(new XMLText(lastBuildDate.toUTCString()))
- return this;
- }
- /** Sets the time to live for the channel - the maximum time until clients should re-fetch it, replacing it if it already exists */
- public ttl(ttl: number) {
- this.replaceChildByTagName('ttl').child(new XMLText(ttl.toString()))
- return this;
- }
- /** Adds the copyright information of the channel */
- public copyright(copyright: string) {
- return this.child(new XMLElement('copyright').child(new XMLText(copyright)))
- }
- /** Adds the generator used for this RSS feed - we recommend calling this and keeping it at .rsstrogen() - Can be called multiple times */
- public generator(generator: string = 'rsstrogen') {
- return this.child(new XMLElement('generator').child(new XMLText(generator)));
- }
- /** Adds the webmaster managing this feed's email address */
- public webmaster(webmaster: string) {
- return this.child(new XMLElement('webMaster').child(new XMLText(webmaster)))
- }
- /** Adds the managing editor managing this feed's email address */
- public managingEditor(managingEditor: string) {
- return this.child(new XMLElement('managingEditor').child(new XMLText(managingEditor)))
- }
- /**
- * Adds a URL of an image to be displayed when aggregators present a feed
- *
- * **Note:** The image must be of type GIF, JPEG or PNG.
- */
- public image(image: {
- /** Defines the hyperlink to the website that offers the channel */
- link: string;
- /** Defines the text to display if the image could not be shown and/or for screen readers */
- alt: string;
- /** Specifies the URL to the image */
- url: URL | string;
- /** Specifies the text in the HTML title attribute of the link around the image. Defaults to the value of alt */
- description?: string | null;
- /** The resolution of the image. Per Spec: Default is 88x31, Max is 144x400. */
- resolution?: [width: number, height: number]
- }) {
- const img = new XMLElement('image').child(
- new XMLElement('link').child(new XMLText(image.link)),
- new XMLElement('title').child(new XMLText(image.alt)),
- new XMLElement('url').child(new XMLText(typeof image.url === 'string' ? image.url : image.url.href)),
- );
- if (image.description !== null)
- img.child(
- new XMLElement('description').child(new XMLText(image.description ?? image.alt)),
- );
- if (image.resolution)
- img.child(
- new XMLElement('width').child(new XMLText(image.resolution[0].toString())),
- new XMLElement('height').child(new XMLText(image.resolution[1].toString())),
- );
- return this.child(img);
- }
- /** Sets (or specifies an additional) language for the feed */
- public language(language: RSSLanguageCode) {
- return this.child(new XMLElement('language').child(new XMLText(language)));
- }
- /** Specifies a search engine/text input should be specified with the feed */
- public search(engine: {
- /** @default "Search" */
- title?: string,
- /** @example "Search Neobot Systems" */
- description: string,
- /** @example "https://search.example.com/search?" */
- link: string,
- /** @example "query" */
- param: string,
- }) {
- this.replaceChildByTagName('textInput').child(
- new XMLElement('title').child(new XMLText(engine.title ?? 'Search')),
- new XMLElement('description').child(new XMLText(engine.description)),
- new XMLElement('link').child(new XMLText(engine.link)),
- new XMLElement('name').child(new XMLText(engine.param)),
- );
- return this;
- }
- /** Adds a category to the feed */
- public category(
- category: string,
- /** Optional - A string or URL that identifies a categorization taxonomy. */
- domain?: string
- ) {
- const cat = new XMLElement('category');
- if (domain !== undefined) cat.attribute('domain', domain)
- this.child(cat.child(new XMLText(category)))
- return this;
- }
- // TODO: add more tags
- /** Adds items to the RSS feed */
- public items(...items: RSSItemElement[]) {
- return this.child(...items);
- }
-}
-export class RSSRootElement extends XMLRootElement {
- public constructor() {
- super("rss")
- this
- .attribute("version", "2.0")
- .xmlns("content", "http://purl.org/rss/1.0/modules/content/")
- }
- public channel(...channels: RSSChannelElement[]) {
- return this.child(...channels)
- }
-}
-
-/** @link https://www.rssboard.org/rss-language-codes */
-export type RSSLanguageCode = 'af' | 'sq' | 'eu' | 'be' | 'bg' | 'ca' | 'zh-cn' | 'zh-tw' | 'hr' | 'cs' | 'da' | 'nl' | 'nl-be' | 'nl-nl' | 'en' | 'en-au' | 'en-bz' | 'en-ca' | 'en-ie' | 'en-jm' | 'en-nz' | 'en-ph' | 'en-za' | 'en-tt' | 'en-gb' | 'en-us' | 'en-zw' | ' et' | 'fo' | 'fi' | 'fr' | 'fr-be' | 'fr-ca' | 'fr-fr' | 'fr-lu' | 'fr-mc' | 'fr-ch' | 'gl' | 'gd' | 'de' | 'de-at' | 'de-de' | 'de-li' | 'de-lu' | 'de-ch' | 'el' | 'haw' | 'hu' | 'is' | 'in' | 'ga' | 'it' | 'it-it' | 'it-ch' | 'ja' | 'ko' | 'mk' | 'no' | 'pl' | 'pt' | 'pt-br' | 'pt-pt' | 'ro' | 'ro-mo' | 'ro-ro' | 'ru' | 'ru-mo' | 'ru-ru' | 'sr' | 'sk' | 'sl' | 'es' | 'es-ar' | 'es-bo' | 'es-cl' | 'es-co' | 'es-cr' | 'es-do' | 'es-ec' | 'es-sv' | 'es-gt' | 'es-hn' | 'es-mx' | 'es-ni' | 'es-pa' | 'es-py' | 'es-pe' | 'es-pr' | 'es-es' | 'es-uy' | 'es-ve' | 'sv' | 'sv-fi' | 'sv-se' | 'tr' | 'uk'
diff --git a/src/lib/vendor/rss/xml.example.md b/src/lib/vendor/rss/xml.example.md
deleted file mode 100644
index 591904a..0000000
--- a/src/lib/vendor/rss/xml.example.md
+++ /dev/null
@@ -1,242 +0,0 @@
-# xml example
-
-If you like directly working with XML, here's an example of how to for this:
-
-```ts
-const posts = [
- {
- title: 'Launching SSH during early boot with mkinitfs',
- url: 'https://estrogen.zone/~mem/blog/1768406136-alpine-ssh-early-initfs-disk-decryption/',
- blurb: 'Replacing the early init with our own script to launch SSH, killing it in early userspace, and allowing remote disk decryption in the mean time',
- author: '7222e800',
- guid: 'https://estrogen.zone/~mem/blog/1768406136',
- published: new Date('2026-01-14T15:53:57Z').toUTCString()
- }
-];
-const doc = new XMLDocumentRoot().child(
- new XMLDeclaration().version().encoding(),
- new XMLRootElement("rss")
- .attribute("version", "2.0")
- .xmlns("content", "http://purl.org/rss/1.0/modules/content/")
- .child(
- new XMLElement('channel')
- .child(
- new XMLElement('title').child(new XMLText('Latest blog posts for 7222e800')),
- new XMLElement('link').child(new XMLText('https://estrogen.zone/~mem/blog/')),
- new XMLElement('description').child(new XMLText('Some Description')),
- new XMLElement('pubDate').child(new XMLText(new Date().toUTCString())),
- ...posts.map(post => new XMLElement('item').child(
- new XMLElement('title').child(new XMLText(post.title)),
- new XMLElement('link').child(new XMLText(post.url)),
- new XMLElement('description').child(new XMLText(post.blurb)),
- new XMLElement('author').child(new XMLText(post.author)),
- new XMLElement('guid').child(new XMLText(post.guid)),
- new XMLElement('published').child(new XMLText(post.published)),
- ))
- )
- )
-);
-console.log(
- util.inspect(
- doc,
- { compact: false, colors: true, breakLength: 80, depth: 90 }, true
- )
-);
-console.log(doc.toString());
-```
-
-as of writing, will output this internal state:
-
-```log
-XMLDocumentRoot {
- attributes: Map(0) {},
- children: [
- XMLDeclaration {
- attributes: Map(2) {
- 'version' => '1.0',
- 'encoding' => 'UTF-8'
- },
- children: [],
- tagType: '#declaration'
- },
- XMLRootElement {
- attributes: Map(2) {
- 'version' => '2.0',
- 'xmlns:content' => 'http://purl.org/rss/1.0/modules/content/'
- },
- children: [
- XMLElement {
- attributes: Map(0) {},
- children: [
- XMLElement {
- attributes: Map(0) {},
- children: [
- XMLText {
- tagType: '#text',
- text: 'Latest blog posts for 7222e800'
- }
- ],
- tagType: '#element',
- tagName: 'title'
- },
- XMLElement {
- attributes: Map(0) {},
- children: [
- XMLText {
- tagType: '#text',
- text: 'https://estrogen.zone/~mem/blog/'
- }
- ],
- tagType: '#element',
- tagName: 'link'
- },
- XMLElement {
- attributes: Map(0) {},
- children: [
- XMLText {
- tagType: '#text',
- text: 'Some Description'
- }
- ],
- tagType: '#element',
- tagName: 'description'
- },
- XMLElement {
- attributes: Map(0) {},
- children: [
- XMLText {
- tagType: '#text',
- text: 'Mon, 26 Jan 2026 03:34:31 GMT'
- }
- ],
- tagType: '#element',
- tagName: 'pubDate'
- },
- XMLElement {
- attributes: Map(0) {},
- children: [
- XMLElement {
- attributes: Map(0) {},
- children: [
- XMLText {
- tagType: '#text',
- text: 'Launching SSH during early boot with mkinitfs'
- }
- ],
- tagType: '#element',
- tagName: 'title'
- },
- XMLElement {
- attributes: Map(0) {},
- children: [
- XMLText {
- tagType: '#text',
- text: 'https://estrogen.zone/~mem/blog/1768406136-alpine-ssh-early-initfs-disk-decryption/'
- }
- ],
- tagType: '#element',
- tagName: 'link'
- },
- XMLElement {
- attributes: Map(0) {},
- children: [
- XMLText {
- tagType: '#text',
- text: 'Replacing the early init with our own script to launch SSH, killing it in early userspace, and allowing remote disk decryption in the mean time'
- }
- ],
- tagType: '#element',
- tagName: 'description'
- },
- XMLElement {
- attributes: Map(0) {},
- children: [
- XMLText {
- tagType: '#text',
- text: '7222e800'
- }
- ],
- tagType: '#element',
- tagName: 'author'
- },
- XMLElement {
- attributes: Map(0) {},
- children: [
- XMLText {
- tagType: '#text',
- text: 'https://estrogen.zone/~mem/blog/1768406136'
- }
- ],
- tagType: '#element',
- tagName: 'guid'
- },
- XMLElement {
- attributes: Map(0) {},
- children: [
- XMLText {
- tagType: '#text',
- text: 'Wed, 14 Jan 2026 15:53:57 GMT'
- }
- ],
- tagType: '#element',
- tagName: 'published'
- }
- ],
- tagType: '#element',
- tagName: 'item'
- }
- ],
- tagType: '#element',
- tagName: 'channel'
- }
- ],
- tagType: '#element',
- tagName: 'rss'
- }
- ],
- tagType: '#document'
-}
-```
-
-and this RSS:
-
-```xml
-<?xml version="1.0" encoding="UTF-8" ?>
-<rss version="2.0"
- xmlns:content="http://purl.org/rss/1.0/modules/content/">
- <channel>
- <title>
- Latest blog posts for 7222e800
- </title>
- <link>
- https://estrogen.zone/~mem/blog/
- </link>
- <description>
- Some Description
- </description>
- <pubDate>
- Mon, 26 Jan 2026 03:34:31 GMT
- </pubDate>
- <item>
- <title>
- Launching SSH during early boot with mkinitfs
- </title>
- <link>
- https://estrogen.zone/~mem/blog/1768406136-alpine-ssh-early-initfs-disk-decryption/
- </link>
- <description>
- Replacing the early init with our own script to launch SSH, killing it in early userspace, and allowing remote disk decryption in the mean time
- </description>
- <author>
- 7222e800
- </author>
- <guid>
- https://estrogen.zone/~mem/blog/1768406136
- </guid>
- <published>
- Wed, 14 Jan 2026 15:53:57 GMT
- </published>
- </item>
- </channel>
-</rss>
-```
diff --git a/src/lib/vendor/rss/xml.ts b/src/lib/vendor/rss/xml.ts
deleted file mode 100644
index 8a0d2c4..0000000
--- a/src/lib/vendor/rss/xml.ts
+++ /dev/null
@@ -1,144 +0,0 @@
-// String methods based on https://github.com/cburgmer/xmlserializer/blob/master/xmlserializer.js
-
-export const removeInvalidXMLCharacters = (content: string) =>
- // See http://www.w3.org/TR/xml/#NT-Char for valid XML 1.0 characters
- content.replace(/[\x00-\x08\x0B\x0C\x0E-\x1F]/g, '');
-
-export const serializeAttributeValue = (value: string) => value
- .replace(/&/g, '&amp;')
- .replace(/</g, '&lt;')
- .replace(/>/g, '&gt;')
- .replace(/"/g, '&quot;')
- .replace(/'/g, '&apos;');
-
-export const serializeTextContent = (content: string) => content
- .replace(/&/g, '&amp;')
- .replace(/</g, '&lt;')
- .replace(/>/g, '&gt;');
-
-export const serializeAttribute = (name: string, value: string) => name + '="' + serializeAttributeValue(value) + '"';
-export const indent = (text: string, size: number) => text.split('\n').map(line => `${' '.repeat(size)}${line}`).join('\n')
-
-export enum XMLTagType {
- DocumentRoot = '#document',
- XMLDeclaration = '#declaration',
- Element = '#element',
- Text = '#text',
- Comment = '#comment',
- CData = '#cdata-section',
-}
-export abstract class BaseXMLTag {
- public abstract readonly tagType: XMLTagType;
- public abstract toString(): string;
-}
-export abstract class XMLTagWithAttributes extends BaseXMLTag {
- public attributes = new Map<string, string>();
- protected get attributeString() {
- let str = '';
- for (const segment of this.attributes.entries().map(([k, v]) => serializeAttribute(k, v))) {
- if (str && str.length + segment.length > 60)
- str += `\n${indent(segment, 2)}`;
- else
- str += ` ${segment}`;
- }
- return str;
- }
- public attribute(name: string, value: string) {
- this.attributes.set(name, value);
- return this;
- }
- public getAttribute(name: string) {
- return this.attributes.get(name);
- }
-}
-export abstract class XMLTagWithChildrenAndAttributes extends XMLTagWithAttributes {
- public children: XMLTag[] = [];
- protected get contentString() {
- return this.children.map(v => v.toString()).join('\n');
- }
- public child(...children: XMLTag[]) {
- this.children.push(...children);
- return this;
- }
-}
-export class XMLDocumentRoot extends XMLTagWithChildrenAndAttributes {
- public readonly tagType = XMLTagType.DocumentRoot as const;
- public toString(): string {
- return removeInvalidXMLCharacters(this.contentString);
- }
-}
-export class XMLDeclaration extends XMLTagWithChildrenAndAttributes {
- public readonly tagType = XMLTagType.XMLDeclaration as const;
- public toString(): string {
- return `<?xml${this.attributeString} ?>`;
- }
- public version(version = "1.0") {
- return this.attribute("version", version)
- }
- public encoding(encoding = "UTF-8") {
- return this.attribute("encoding", encoding);
- }
-};
-export class XMLElement extends XMLTagWithChildrenAndAttributes {
- public readonly tagType = XMLTagType.Element as const;
- public constructor(public tagName: string) { super() }
- protected findElementChild(query: (element: XMLElement) => boolean) {
- return this.children.find(el => el.tagType === XMLTagType.Element && query(el)) as XMLElement
- }
- public toString(): string {
- return `<${this.tagName}${this.attributeString}${this.children.length ? `>
-${indent(this.contentString, 2)}
-</${this.tagName}>` : ' />'}`
- }
-}
-export class XMLRootElement extends XMLElement {
- /**
- * @param subns Leave as empty string for root namespace
- */
- public xmlns(subns: string, value: string) {
- this.attribute(`xmlns${subns ? `:${subns}` : ''}`, value)
- return this;
- }
-}
-export class XMLText extends BaseXMLTag {
- public tagType = XMLTagType.Text as const;
- public constructor(public text: string) { super() }
- public toString(): string {
- return serializeTextContent(this.text);
- }
-}
-export class XMLComment extends BaseXMLTag {
- public tagType = XMLTagType.Comment as const;
- public constructor(
- public text: string,
- /** Set to 0 for no wrapping at all */
- public wrapAt = 70,
- public addSpacesAroundCommentTags = true
- ) { super() }
- public toString(): string {
- let text = this.text;
- if (this.wrapAt) {
- const lines = text.split('\n')
- const newLines = [] as string[]
- if (lines.length === 1 && lines[0].length < this.wrapAt) {
- if (this.addSpacesAroundCommentTags)
- newLines[0] = ` ${text} `
- } else
- for (let line of lines)
- while (line.length) {
- newLines.push(line.substring(0, this.wrapAt))
- line = line.substring(this.wrapAt)
- }
- } else if (this.addSpacesAroundCommentTags) this.text = ` ${this.text} `
- return `<!--${text
- .replace(/-/g, '&#45;')}-->`;
- }
-}
-export class XMLCData extends BaseXMLTag {
- public tagType = XMLTagType.CData as const;
- public constructor(public content: string) { super() }
- public toString(): string {
- return `<![CDATA[${this.content.replace(/\]\]>/gu, ']]]]><![CDATA[>')}]]>`;
- }
-}
-export type XMLTag = XMLDocumentRoot | XMLDeclaration | XMLElement | XMLText | XMLComment | XMLCData;