Skip to content

Commit

Permalink
feat: add the XMLNS_1_0 namespace
Browse files Browse the repository at this point in the history
  • Loading branch information
lddubeau committed Sep 6, 2018
1 parent 7bfcca0 commit 022239c
Show file tree
Hide file tree
Showing 2 changed files with 145 additions and 19 deletions.
84 changes: 84 additions & 0 deletions src/xmlchars.ts
Original file line number Diff line number Diff line change
Expand Up @@ -211,3 +211,87 @@ export namespace XML_1_0 {
}
}
}

/**
* Character class utilities for XML NS 1.0.
*/
export namespace XMLNS_1_0 {

/**
* Third edition.
*/
export namespace ED3 {
/**
* Regular expression fragments. These fragments are designed to be included
* inside square brackets in a regular expression.
*/
export namespace fragments {
// tslint:disable-next-line:max-line-length
export const NC_NAME_START_CHAR = "A-Z_a-z\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u02FF\u0370-\u037D\u037F-\u1FFF\u200C-\u200D\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD\u{10000}-\u{EFFFF}";

export const NC_NAME_CHAR =
`-${NC_NAME_START_CHAR}.0-9\u00B7\u0300-\u036F\u203F-\u2040`;
}

/**
* Regular expression. These correspond to the productions of the same name
* in the specification.
*/
export namespace regexes {
export const NC_NAME_START_CHAR =
new RegExp(`^[${fragments.NC_NAME_START_CHAR}]$`, "u");

export const NC_NAME_CHAR =
new RegExp(`^[${fragments.NC_NAME_CHAR}]$`, "u");

export const NC_NAME =
new RegExp(
`^[${fragments.NC_NAME_START_CHAR}][${fragments.NC_NAME_CHAR}]*$`,
"u");
}

/**
* Determines whether a codepoint matches
* [[regexes.NC_NAME_START_CHAR]].
*
* @param c The code point.
*
* @returns ``true`` if the codepoint matches.
*/
// tslint:disable-next-line:cyclomatic-complexity
export function isNCNameStartChar(c: number): boolean {
return ((c >= 0x41 && c <= 0x5A) ||
c === 0x5F ||
(c >= 0x61 && c <= 0x7A) ||
(c >= 0xC0 && c <= 0xD6) ||
(c >= 0xD8 && c <= 0xF6) ||
(c >= 0x00F8 && c <= 0x02FF) ||
(c >= 0x0370 && c <= 0x037D) ||
(c >= 0x037F && c <= 0x1FFF) ||
(c >= 0x200C && c <= 0x200D) ||
(c >= 0x2070 && c <= 0x218F) ||
(c >= 0x2C00 && c <= 0x2FEF) ||
(c >= 0x3001 && c <= 0xD7FF) ||
(c >= 0xF900 && c <= 0xFDCF) ||
(c >= 0xFDF0 && c <= 0xFFFD) ||
(c >= 0x10000 && c <= 0xEFFFF));
}

/**
* Determines whether a codepoint matches [[regexes.NC_NAME_CHAR]].
*
* @param c The code point.
*
* @returns ``true`` if the codepoint matches.
*/
export function isNCNameChar(c: number): boolean {
return isNCNameStartChar(c) ||
(c === 0x2D ||
c === 0x2E ||
(c >= 0x30 && c <= 0x39) ||
c === 0x00B7 ||
(c >= 0x0300 && c <= 0x036F) ||
(c >= 0x203F && c <= 0x2040));
}
}
}
80 changes: 61 additions & 19 deletions test/xmlchars.spec.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// tslint:disable-next-line:missing-jsdoc
import { expect } from "chai";
import { XML_1_0 } from "../src/xmlchars";
import { XML_1_0, XMLNS_1_0 } from "../src/xmlchars";

interface Fixture {
name: string;
Expand All @@ -22,6 +22,11 @@ const poo: Fixture = {
data: "\u{1F4A9}",
};

const colon: Fixture = {
name: "colon",
data: ":",
};

const space: Fixture = {
name: "space",
data: " ",
Expand Down Expand Up @@ -92,6 +97,7 @@ const ALL_FIXTURES = new Set([
x,
abc,
poo,
colon,
space,
tab,
newline,
Expand All @@ -111,9 +117,6 @@ interface Case {
matching: Fixture[];
}

type ED4_REGEX_NAMES = keyof typeof XML_1_0.ED4.regexes;
type ED5_REGEX_NAMES = keyof typeof XML_1_0.ED5.regexes;

function makeTests(re: RegExp, testCase: Case): void {
describe("matches", () => {
for (const matchingCase of testCase.matching) {
Expand Down Expand Up @@ -172,26 +175,26 @@ function makeCodePointTestTests(codePointTest: (c: number) => boolean,
describe("XML_1_0", () => {
describe("ED5", () => {
// tslint:disable-next-line:mocha-no-side-effect-code
const cases: Record<ED5_REGEX_NAMES, Case> = {
const cases: Record<keyof typeof XML_1_0.ED5.regexes, Case> = {
CHAR: {
matching: [x, poo, space, tab, newline, cr, ideographic, combining,
digit, extender],
matching: [x, poo, colon, space, tab, newline, cr, ideographic,
combining, digit, extender],
},
S: {
matching: [space, tab, newline, cr],
},
NAME_START_CHAR: {
matching: [x, ideographic, poo],
matching: [x, ideographic, poo, colon],
},
NAME_CHAR: {
matching: [x, ideographic, poo, combining, extender, digit],
matching: [x, ideographic, poo, colon, combining, extender, digit],
},
NAME: {
matching: [x, abc, ideographic, nameWithColon, poo],
matching: [x, abc, ideographic, colon, nameWithColon, poo],
},
NMTOKEN: {
matching: [x, abc, ideographic, nameWithColon, leadingDot, leadingDash,
leadingDigit, combining, extender, digit, poo],
matching: [x, abc, ideographic, colon, nameWithColon, leadingDot,
leadingDash, leadingDigit, combining, extender, digit, poo],
},
// tslint:disable-next-line:no-any
} as any;
Expand Down Expand Up @@ -229,10 +232,10 @@ describe("XML_1_0", () => {

describe("ED4.regexes", () => {
// tslint:disable-next-line:mocha-no-side-effect-code
const cases: Record<ED4_REGEX_NAMES, Case> = {
const cases: Record<keyof typeof XML_1_0.ED4.regexes, Case> = {
CHAR: {
matching: [x, poo, space, tab, newline, cr, ideographic, combining,
digit, extender],
matching: [x, poo, colon, space, tab, newline, cr, ideographic,
combining, digit, extender],
},
S: {
matching: [space, tab, newline, cr],
Expand All @@ -256,14 +259,14 @@ describe("XML_1_0", () => {
matching: [x, ideographic],
},
NAME_CHAR: {
matching: [x, ideographic, digit, extender, combining],
matching: [x, ideographic, colon, digit, extender, combining],
},
NAME: {
matching: [x, abc, ideographic, nameWithColon],
matching: [x, abc, ideographic, colon, nameWithColon],
},
NMTOKEN: {
matching: [x, abc, ideographic, nameWithColon, leadingDot, leadingDash,
leadingDigit, combining, extender, digit],
matching: [x, abc, ideographic, colon, nameWithColon, leadingDot,
leadingDash, leadingDigit, combining, extender, digit],
},
// tslint:disable-next-line:no-any
} as any;
Expand All @@ -277,3 +280,42 @@ describe("XML_1_0", () => {
}
});
});

describe("XML_NS_1_0", () => {
describe("ED3", () => {
// tslint:disable-next-line:mocha-no-side-effect-code
const cases: Record<keyof typeof XMLNS_1_0.ED3.regexes, Case> = {
NC_NAME_START_CHAR: {
matching: [x, ideographic, poo],
},
NC_NAME_CHAR: {
matching: [x, ideographic, poo, combining, extender, digit],
},
NC_NAME: {
matching: [x, abc, ideographic, poo],
},
// tslint:disable-next-line:no-any
} as any;

describe(".regexes", () => {
// tslint:disable-next-line:mocha-no-side-effect-code
for (const name of (Object.keys(cases) as (keyof typeof cases)[])) {
describe(name, () => {
// tslint:disable-next-line:mocha-no-side-effect-code
makeTests(XMLNS_1_0.ED3.regexes[name], cases[name]);
});
}
});

describe(".isNCNameStartChar", () => {
// tslint:disable-next-line:mocha-no-side-effect-code
makeCodePointTestTests(XMLNS_1_0.ED3.isNCNameStartChar,
cases.NC_NAME_START_CHAR);
});

describe(".isNCNameChar", () => {
// tslint:disable-next-line:mocha-no-side-effect-code
makeCodePointTestTests(XMLNS_1_0.ED3.isNCNameChar, cases.NC_NAME_CHAR);
});
});
});

0 comments on commit 022239c

Please sign in to comment.