@btc-embedded/cdk-extensions 0.23.3 → 0.23.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.jsii +41 -41
- package/CHANGELOG.md +14 -0
- package/assets/cli/catnip.js +154 -166
- package/lib/constructs/EventPipe.js +1 -1
- package/lib/constructs/ExportedService.js +1 -1
- package/lib/constructs/S3Bucket.js +1 -1
- package/lib/constructs/SecureRestApi.js +1 -1
- package/lib/constructs/SecureRestApiV2.js +1 -1
- package/lib/constructs/api-keys/ApiKeyClientAuthorization.js +1 -1
- package/lib/constructs/api-keys/ApiKeyManagement.js +1 -1
- package/lib/constructs/api-keys/ApiKeyPreTokenHandler.js +1 -1
- package/lib/constructs/api-keys/ApiKeyStore.js +1 -1
- package/lib/extensions/ApiGatewayExtension.js +1 -1
- package/lib/extensions/ApplicationContainer.js +1 -1
- package/lib/extensions/ApplicationLoadBalancerExtension.js +1 -1
- package/lib/extensions/ApplicationLoadBalancerExtensionV2.js +1 -1
- package/lib/extensions/CloudMapExtension.js +1 -1
- package/lib/extensions/DeactivatableServiceExtension.js +1 -1
- package/lib/extensions/DeploymentConfigExtension.js +1 -1
- package/lib/extensions/DocumentDbAccessExtension.js +1 -1
- package/lib/extensions/DomainEventMessagingExtension.js +1 -1
- package/lib/extensions/EfsMountExtension.js +1 -1
- package/lib/extensions/ExtraContainerExtension.js +1 -1
- package/lib/extensions/HTTPApiExtension.js +1 -1
- package/lib/extensions/LogExtension.js +1 -1
- package/lib/extensions/ModifyContainerDefinitionExtension.js +1 -1
- package/lib/extensions/ModifyTaskDefinitionExtension.js +1 -1
- package/lib/extensions/OpenIdExtension.js +1 -1
- package/lib/extensions/OpenTelemetryExtension.js +1 -1
- package/lib/extensions/PostgresDbAccessExtension.js +1 -1
- package/lib/extensions/SharedVolumeExtension.js +1 -1
- package/lib/extensions/TcpKeepAliveExtension.js +1 -1
- package/lib/platform/ApiGateway.js +1 -1
- package/lib/platform/ApiGatewayVpcLink.js +2 -2
- package/lib/platform/ApplicationLoadBalancer.js +1 -1
- package/lib/platform/ApplicationLoadBalancerV2.d.ts +1 -0
- package/lib/platform/ApplicationLoadBalancerV2.js +10 -3
- package/lib/platform/AuroraPostgresDB.js +5 -4
- package/lib/platform/BTCLogGroup.js +1 -1
- package/lib/platform/CognitoUserPool.js +2 -2
- package/lib/platform/DefaultUserPoolClients.js +1 -1
- package/lib/platform/DocumentDB.js +2 -2
- package/lib/platform/EcsCluster.js +1 -1
- package/lib/platform/EfsFileSystem.js +1 -1
- package/lib/platform/HostedZone.js +1 -1
- package/lib/platform/PrivateDnsNamespace.js +1 -1
- package/lib/platform/ResourceServer.js +1 -1
- package/lib/platform/Vpc.js +1 -1
- package/lib/platform/VpcV2.js +1 -1
- package/lib/stacks/ApplicationStack.js +1 -1
- package/lib/utils/BasePlatformStackResolver.js +1 -1
- package/lib/utils/StackParameter.js +1 -1
- package/node_modules/@nodable/entities/README.md +41 -0
- package/node_modules/@nodable/entities/package.json +54 -0
- package/node_modules/@nodable/entities/src/EntityDecoder.js +543 -0
- package/node_modules/@nodable/entities/src/EntityEncoder.js +194 -0
- package/node_modules/@nodable/entities/src/entities.js +1177 -0
- package/node_modules/@nodable/entities/src/entityTries.js +49 -0
- package/node_modules/@nodable/entities/src/index.d.ts +264 -0
- package/node_modules/@nodable/entities/src/index.js +29 -0
- package/node_modules/fast-xml-builder/CHANGELOG.md +40 -0
- package/node_modules/fast-xml-builder/LICENSE +21 -0
- package/node_modules/fast-xml-builder/README.md +74 -0
- package/node_modules/fast-xml-builder/lib/fxb.cjs +1 -0
- package/node_modules/fast-xml-builder/lib/fxb.d.cts +270 -0
- package/node_modules/fast-xml-builder/lib/fxb.min.js +2 -0
- package/node_modules/fast-xml-builder/lib/fxb.min.js.map +1 -0
- package/node_modules/fast-xml-builder/package.json +81 -0
- package/node_modules/fast-xml-builder/src/fxb.d.ts +270 -0
- package/node_modules/fast-xml-builder/src/fxb.js +599 -0
- package/node_modules/fast-xml-builder/src/ignoreAttributes.js +18 -0
- package/node_modules/fast-xml-builder/src/orderedJs2Xml.js +359 -0
- package/node_modules/fast-xml-builder/src/util.js +16 -0
- package/node_modules/fast-xml-parser/CHANGELOG.md +165 -0
- package/node_modules/fast-xml-parser/README.md +21 -44
- package/node_modules/fast-xml-parser/lib/fxbuilder.min.js +1 -1
- package/node_modules/fast-xml-parser/lib/fxbuilder.min.js.map +1 -1
- package/node_modules/fast-xml-parser/lib/fxp.cjs +1 -1
- package/node_modules/fast-xml-parser/lib/fxp.d.cts +343 -31
- package/node_modules/fast-xml-parser/lib/fxp.min.js +1 -1
- package/node_modules/fast-xml-parser/lib/fxp.min.js.map +1 -1
- package/node_modules/fast-xml-parser/lib/fxparser.min.js +1 -1
- package/node_modules/fast-xml-parser/lib/fxparser.min.js.map +1 -1
- package/node_modules/fast-xml-parser/lib/fxvalidator.min.js +1 -1
- package/node_modules/fast-xml-parser/lib/fxvalidator.min.js.map +1 -1
- package/node_modules/fast-xml-parser/package.json +13 -8
- package/node_modules/fast-xml-parser/src/fxp.d.ts +335 -30
- package/node_modules/fast-xml-parser/src/fxp.js +1 -1
- package/node_modules/fast-xml-parser/src/util.js +18 -25
- package/node_modules/fast-xml-parser/src/v6/EntitiesParser.js +89 -87
- package/node_modules/fast-xml-parser/src/v6/OptionsBuilder.js +10 -10
- package/node_modules/fast-xml-parser/src/v6/OutputBuilders/BaseOutputBuilder.js +23 -23
- package/node_modules/fast-xml-parser/src/v6/OutputBuilders/JsArrBuilder.js +29 -29
- package/node_modules/fast-xml-parser/src/v6/OutputBuilders/JsMinArrBuilder.js +1 -1
- package/node_modules/fast-xml-parser/src/v6/OutputBuilders/JsObjBuilder.js +39 -39
- package/node_modules/fast-xml-parser/src/v6/OutputBuilders/ParserOptionsBuilder.js +21 -21
- package/node_modules/fast-xml-parser/src/v6/XMLParser.js +22 -22
- package/node_modules/fast-xml-parser/src/v6/valueParsers/EntitiesParser.js +85 -85
- package/node_modules/fast-xml-parser/src/validator.js +34 -34
- package/node_modules/fast-xml-parser/src/xmlbuilder/json2xml.js +5 -284
- package/node_modules/fast-xml-parser/src/xmlparser/DocTypeReader.js +335 -293
- package/node_modules/fast-xml-parser/src/xmlparser/OptionsBuilder.js +160 -43
- package/node_modules/fast-xml-parser/src/xmlparser/OrderedObjParser.js +540 -308
- package/node_modules/fast-xml-parser/src/xmlparser/XMLParser.js +26 -26
- package/node_modules/fast-xml-parser/src/xmlparser/node2json.js +99 -41
- package/node_modules/fast-xml-parser/src/xmlparser/xmlNode.js +10 -10
- package/node_modules/path-expression-matcher/LICENSE +21 -0
- package/node_modules/path-expression-matcher/README.md +872 -0
- package/node_modules/path-expression-matcher/lib/pem.cjs +1 -0
- package/node_modules/path-expression-matcher/lib/pem.d.cts +634 -0
- package/node_modules/path-expression-matcher/lib/pem.min.js +2 -0
- package/node_modules/path-expression-matcher/lib/pem.min.js.map +1 -0
- package/node_modules/path-expression-matcher/package.json +78 -0
- package/node_modules/path-expression-matcher/src/Expression.js +232 -0
- package/node_modules/path-expression-matcher/src/ExpressionSet.js +209 -0
- package/node_modules/path-expression-matcher/src/Matcher.js +570 -0
- package/node_modules/path-expression-matcher/src/index.d.ts +523 -0
- package/node_modules/path-expression-matcher/src/index.js +29 -0
- package/node_modules/strnum/CHANGELOG.md +12 -2
- package/node_modules/strnum/README.md +1 -0
- package/node_modules/strnum/package.json +5 -4
- package/node_modules/strnum/strnum.js +99 -65
- package/node_modules/xml-naming/README.md +189 -0
- package/node_modules/xml-naming/package.json +54 -0
- package/node_modules/xml-naming/src/index.d.ts +74 -0
- package/node_modules/xml-naming/src/index.js +270 -0
- package/package.json +3 -2
- package/renovate.json5 +1 -0
- package/node_modules/fast-xml-parser/src/xmlbuilder/orderedJs2Xml.js +0 -134
- package/node_modules/strnum/.github/SECURITY.md +0 -5
- package/node_modules/strnum/.vscode/launch.json +0 -25
- package/node_modules/strnum/algo.stflow +0 -84
- package/node_modules/strnum/strnum.test.js +0 -173
- package/node_modules/strnum/test.js +0 -9
- /package/node_modules/{fast-xml-parser/src/xmlbuilder → fast-xml-builder/src}/prettifyJs2Xml.js +0 -0
|
@@ -1,105 +1,114 @@
|
|
|
1
1
|
const hexRegex = /^[-+]?0x[a-fA-F0-9]+$/;
|
|
2
|
+
const binRegex = /^0b[01]+$/;
|
|
3
|
+
const octRegex = /^0o[0-7]+$/;
|
|
2
4
|
const numRegex = /^([\-\+])?(0*)([0-9]*(\.[0-9]*)?)$/;
|
|
3
|
-
// const octRegex = /^0x[a-z0-9]+/;
|
|
4
|
-
// const binRegex = /0x[a-z0-9]+/;
|
|
5
5
|
|
|
6
|
-
|
|
7
6
|
const consider = {
|
|
8
|
-
hex
|
|
9
|
-
|
|
7
|
+
hex: true,
|
|
8
|
+
binary: false,
|
|
9
|
+
octal: false,
|
|
10
10
|
leadingZeros: true,
|
|
11
11
|
decimalPoint: "\.",
|
|
12
12
|
eNotation: true,
|
|
13
|
-
//skipLike: /regex
|
|
13
|
+
//skipLike: /regex/,
|
|
14
|
+
infinity: "original", // "null", "infinity" (Infinity type), "string" ("Infinity" (the string literal))
|
|
14
15
|
};
|
|
15
16
|
|
|
16
|
-
export default function toNumber(str, options = {}){
|
|
17
|
-
options = Object.assign({}, consider, options
|
|
18
|
-
if(!str || typeof str !== "string"
|
|
19
|
-
|
|
20
|
-
let trimmedStr
|
|
21
|
-
|
|
22
|
-
if(
|
|
23
|
-
else if(
|
|
17
|
+
export default function toNumber(str, options = {}) {
|
|
18
|
+
options = Object.assign({}, consider, options);
|
|
19
|
+
if (!str || typeof str !== "string") return str;
|
|
20
|
+
|
|
21
|
+
let trimmedStr = str.trim();
|
|
22
|
+
|
|
23
|
+
if (trimmedStr.length === 0) return str;
|
|
24
|
+
else if (options.skipLike !== undefined && options.skipLike.test(trimmedStr)) return str;
|
|
25
|
+
else if (trimmedStr === "0") return 0;
|
|
24
26
|
else if (options.hex && hexRegex.test(trimmedStr)) {
|
|
25
27
|
return parse_int(trimmedStr, 16);
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
}else if (
|
|
29
|
-
return
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
}else{
|
|
28
|
+
} else if (options.binary && binRegex.test(trimmedStr)) {
|
|
29
|
+
return parse_int(trimmedStr, 2);
|
|
30
|
+
} else if (options.octal && octRegex.test(trimmedStr)) {
|
|
31
|
+
return parse_int(trimmedStr, 8);
|
|
32
|
+
} else if (!isFinite(trimmedStr)) { //Infinity
|
|
33
|
+
return handleInfinity(str, Number(trimmedStr), options);
|
|
34
|
+
} else if (trimmedStr.includes('e') || trimmedStr.includes('E')) { //eNotation
|
|
35
|
+
return resolveEnotation(str, trimmedStr, options);
|
|
36
|
+
} else {
|
|
33
37
|
//separate negative sign, leading zeros, and rest number
|
|
34
38
|
const match = numRegex.exec(trimmedStr);
|
|
35
39
|
// +00.123 => [ , '+', '00', '.123', ..
|
|
36
|
-
if(match){
|
|
40
|
+
if (match) {
|
|
37
41
|
const sign = match[1] || "";
|
|
38
42
|
const leadingZeros = match[2];
|
|
39
43
|
let numTrimmedByZeros = trimZeros(match[3]); //complete num without leading zeros
|
|
40
44
|
const decimalAdjacentToLeadingZeros = sign ? // 0., -00., 000.
|
|
41
|
-
str[leadingZeros.length+1] === "."
|
|
45
|
+
str[leadingZeros.length + 1] === "."
|
|
42
46
|
: str[leadingZeros.length] === ".";
|
|
43
47
|
|
|
44
48
|
//trim ending zeros for floating number
|
|
45
|
-
if(!options.leadingZeros //leading zeros are not allowed
|
|
46
|
-
&& (leadingZeros.length > 1
|
|
47
|
-
|| (leadingZeros.length === 1 && !decimalAdjacentToLeadingZeros))){
|
|
49
|
+
if (!options.leadingZeros //leading zeros are not allowed
|
|
50
|
+
&& (leadingZeros.length > 1
|
|
51
|
+
|| (leadingZeros.length === 1 && !decimalAdjacentToLeadingZeros))) {
|
|
48
52
|
// 00, 00.3, +03.24, 03, 03.24
|
|
49
53
|
return str;
|
|
50
54
|
}
|
|
51
|
-
else{//no leading zeros or leading zeros are allowed
|
|
55
|
+
else {//no leading zeros or leading zeros are allowed
|
|
52
56
|
const num = Number(trimmedStr);
|
|
53
57
|
const parsedStr = String(num);
|
|
54
58
|
|
|
55
|
-
if(
|
|
56
|
-
if(parsedStr.search(/[eE]/) !== -1){ //given number is long and parsed to eNotation
|
|
57
|
-
if(options.eNotation) return num;
|
|
59
|
+
if (num === 0) return num;
|
|
60
|
+
if (parsedStr.search(/[eE]/) !== -1) { //given number is long and parsed to eNotation
|
|
61
|
+
if (options.eNotation) return num;
|
|
58
62
|
else return str;
|
|
59
|
-
}else if(trimmedStr.indexOf(".") !== -1){ //floating number
|
|
60
|
-
if(parsedStr === "0") return num; //0.0
|
|
61
|
-
else if(parsedStr === numTrimmedByZeros) return num; //0.456. 0.79000
|
|
62
|
-
else if(
|
|
63
|
+
} else if (trimmedStr.indexOf(".") !== -1) { //floating number
|
|
64
|
+
if (parsedStr === "0") return num; //0.0
|
|
65
|
+
else if (parsedStr === numTrimmedByZeros) return num; //0.456. 0.79000
|
|
66
|
+
else if (parsedStr === `${sign}${numTrimmedByZeros}`) return num;
|
|
63
67
|
else return str;
|
|
64
68
|
}
|
|
65
|
-
|
|
66
|
-
let n = leadingZeros? numTrimmedByZeros : trimmedStr;
|
|
67
|
-
if(leadingZeros){
|
|
69
|
+
|
|
70
|
+
let n = leadingZeros ? numTrimmedByZeros : trimmedStr;
|
|
71
|
+
if (leadingZeros) {
|
|
68
72
|
// -009 => -9
|
|
69
|
-
return (n === parsedStr) || (sign+n === parsedStr) ? num : str
|
|
70
|
-
}else
|
|
73
|
+
return (n === parsedStr) || (sign + n === parsedStr) ? num : str
|
|
74
|
+
} else {
|
|
71
75
|
// +9
|
|
72
|
-
return (n === parsedStr) || (n === sign+parsedStr) ? num : str
|
|
76
|
+
return (n === parsedStr) || (n === sign + parsedStr) ? num : str
|
|
73
77
|
}
|
|
74
78
|
}
|
|
75
|
-
}else{ //non-numeric string
|
|
79
|
+
} else { //non-numeric string
|
|
76
80
|
return str;
|
|
77
81
|
}
|
|
78
82
|
}
|
|
79
83
|
}
|
|
80
84
|
|
|
81
85
|
const eNotationRegx = /^([-+])?(0*)(\d*(\.\d*)?[eE][-\+]?\d+)$/;
|
|
82
|
-
function resolveEnotation(str,trimmedStr,options){
|
|
83
|
-
if(!options.eNotation) return str;
|
|
84
|
-
const notation = trimmedStr.match(eNotationRegx);
|
|
85
|
-
if(notation){
|
|
86
|
+
function resolveEnotation(str, trimmedStr, options) {
|
|
87
|
+
if (!options.eNotation) return str;
|
|
88
|
+
const notation = trimmedStr.match(eNotationRegx);
|
|
89
|
+
if (notation) {
|
|
86
90
|
let sign = notation[1] || "";
|
|
87
91
|
const eChar = notation[3].indexOf("e") === -1 ? "E" : "e";
|
|
88
92
|
const leadingZeros = notation[2];
|
|
89
93
|
const eAdjacentToLeadingZeros = sign ? // 0E.
|
|
90
|
-
str[leadingZeros.length+1] === eChar
|
|
94
|
+
str[leadingZeros.length + 1] === eChar
|
|
91
95
|
: str[leadingZeros.length] === eChar;
|
|
92
96
|
|
|
93
|
-
if(leadingZeros.length > 1 && eAdjacentToLeadingZeros) return str;
|
|
94
|
-
else if(leadingZeros.length === 1
|
|
95
|
-
&& (notation[3].startsWith(`.${eChar}`) || notation[3][0] === eChar)){
|
|
97
|
+
if (leadingZeros.length > 1 && eAdjacentToLeadingZeros) return str;
|
|
98
|
+
else if (leadingZeros.length === 1
|
|
99
|
+
&& (notation[3].startsWith(`.${eChar}`) || notation[3][0] === eChar)) {
|
|
100
|
+
return Number(trimmedStr);
|
|
101
|
+
} else if (leadingZeros.length > 0) {
|
|
102
|
+
// Has leading zeros — only accept if leadingZeros option allows it
|
|
103
|
+
if (options.leadingZeros && !eAdjacentToLeadingZeros) {
|
|
104
|
+
trimmedStr = (notation[1] || "") + notation[3];
|
|
96
105
|
return Number(trimmedStr);
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
106
|
+
} else return str;
|
|
107
|
+
} else {
|
|
108
|
+
// No leading zeros — always valid e-notation, parse it
|
|
100
109
|
return Number(trimmedStr);
|
|
101
|
-
}
|
|
102
|
-
}else{
|
|
110
|
+
}
|
|
111
|
+
} else {
|
|
103
112
|
return str;
|
|
104
113
|
}
|
|
105
114
|
}
|
|
@@ -109,21 +118,46 @@ function resolveEnotation(str,trimmedStr,options){
|
|
|
109
118
|
* @param {string} numStr without leading zeros
|
|
110
119
|
* @returns
|
|
111
120
|
*/
|
|
112
|
-
function trimZeros(numStr){
|
|
113
|
-
if(numStr && numStr.indexOf(".") !== -1){//float
|
|
121
|
+
function trimZeros(numStr) {
|
|
122
|
+
if (numStr && numStr.indexOf(".") !== -1) {//float
|
|
114
123
|
numStr = numStr.replace(/0+$/, ""); //remove ending zeros
|
|
115
|
-
if(numStr === ".")
|
|
116
|
-
else if(numStr[0] === ".")
|
|
117
|
-
else if(numStr[numStr.length-1] === ".")
|
|
124
|
+
if (numStr === ".") numStr = "0";
|
|
125
|
+
else if (numStr[0] === ".") numStr = "0" + numStr;
|
|
126
|
+
else if (numStr[numStr.length - 1] === ".") numStr = numStr.substring(0, numStr.length - 1);
|
|
118
127
|
return numStr;
|
|
119
128
|
}
|
|
120
129
|
return numStr;
|
|
121
130
|
}
|
|
122
131
|
|
|
123
|
-
function parse_int(numStr, base){
|
|
124
|
-
|
|
125
|
-
if(
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
else
|
|
132
|
+
function parse_int(numStr, base) {
|
|
133
|
+
const str = numStr.trim();
|
|
134
|
+
if (base === 2 || base === 8) numStr = str.substring(2);
|
|
135
|
+
|
|
136
|
+
if (parseInt) return parseInt(numStr, base);
|
|
137
|
+
else if (Number.parseInt) return Number.parseInt(numStr, base);
|
|
138
|
+
else if (window && window.parseInt) return window.parseInt(numStr, base);
|
|
139
|
+
else throw new Error("parseInt, Number.parseInt, window.parseInt are not supported");
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* Handle infinite values based on user option
|
|
144
|
+
* @param {string} str - original input string
|
|
145
|
+
* @param {number} num - parsed number (Infinity or -Infinity)
|
|
146
|
+
* @param {object} options - user options
|
|
147
|
+
* @returns {string|number|null} based on infinity option
|
|
148
|
+
*/
|
|
149
|
+
function handleInfinity(str, num, options) {
|
|
150
|
+
const isPositive = num === Infinity;
|
|
151
|
+
|
|
152
|
+
switch (options.infinity.toLowerCase()) {
|
|
153
|
+
case "null":
|
|
154
|
+
return null;
|
|
155
|
+
case "infinity":
|
|
156
|
+
return num; // Return Infinity or -Infinity
|
|
157
|
+
case "string":
|
|
158
|
+
return isPositive ? "Infinity" : "-Infinity";
|
|
159
|
+
case "original":
|
|
160
|
+
default:
|
|
161
|
+
return str; // Return original string like "1e1000"
|
|
162
|
+
}
|
|
129
163
|
}
|
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
# xml-naming
|
|
2
|
+
|
|
3
|
+
Validates XML name productions as defined in the [XML 1.0](https://www.w3.org/TR/xml/) and [XML 1.1](https://www.w3.org/TR/xml11/) specifications.
|
|
4
|
+
|
|
5
|
+
Covers all five productions:
|
|
6
|
+
|
|
7
|
+
| Production | Description | Colon | Digit/hyphen start |
|
|
8
|
+
|---|---|---|---|
|
|
9
|
+
| `Name` | General XML name | ✅ | ❌ |
|
|
10
|
+
| `NCName` | Non-Colonized name | ❌ | ❌ |
|
|
11
|
+
| `QName` | Namespace-qualified name (`prefix:local`) | ✅ (one only) | ❌ |
|
|
12
|
+
| `NMToken` | Name token (relaxed start) | ✅ | ✅ |
|
|
13
|
+
| `NMTokens` | Whitespace-separated NMToken list | ✅ | ✅ |
|
|
14
|
+
|
|
15
|
+
Used internally by [fast-xml-parser](https://github.com/NaturalIntelligence/fast-xml-parser), [fast-xml-validator](https://github.com/NaturalIntelligence/fast-xml-validator), [@nodable\flexible-xml-parser](https://github.com/nodable/flexible-xml-parser) and [fast-svg-parser](https://github.com/amitguptagwl/fast-svg-parser).
|
|
16
|
+
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
## Install
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
npm install xml-naming
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
---
|
|
26
|
+
|
|
27
|
+
## Usage
|
|
28
|
+
|
|
29
|
+
### Boolean validators
|
|
30
|
+
|
|
31
|
+
```js
|
|
32
|
+
import { name, ncName, qName, nmToken, nmTokens } from 'xml-naming';
|
|
33
|
+
|
|
34
|
+
// Name — colon allowed anywhere, used for DOCTYPE entity names
|
|
35
|
+
name('foo') // true
|
|
36
|
+
name('a:b:c') // true ← multiple colons fine for Name
|
|
37
|
+
name('1foo') // false ← digit start invalid
|
|
38
|
+
|
|
39
|
+
// NCName — no colon, used for SVG id attributes, namespace prefixes
|
|
40
|
+
ncName('my-id') // true
|
|
41
|
+
ncName('xlink:href') // false ← colon not allowed
|
|
42
|
+
|
|
43
|
+
// QName — exactly one colon as prefix separator, used for element/attribute names
|
|
44
|
+
qName('svg:circle') // true
|
|
45
|
+
qName('foo') // true ← unprefixed QName is valid
|
|
46
|
+
qName('a:b:c') // false ← only one colon allowed
|
|
47
|
+
qName(':foo') // false ← cannot start with colon
|
|
48
|
+
|
|
49
|
+
// NMToken — any NameChar at start, used for DTD NMTOKEN attributes
|
|
50
|
+
nmToken('123') // true ← digit start is fine
|
|
51
|
+
nmToken('-bar') // true
|
|
52
|
+
nmToken('foo bar') // false ← space not allowed
|
|
53
|
+
|
|
54
|
+
// NMTokens — whitespace-separated NMToken list
|
|
55
|
+
nmTokens('tok1 tok2 -foo 123') // true
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
### XML version option
|
|
59
|
+
|
|
60
|
+
All validators accept an optional `{ xmlVersion }` option:
|
|
61
|
+
|
|
62
|
+
```js
|
|
63
|
+
import { name } from 'xml-naming';
|
|
64
|
+
|
|
65
|
+
name('\u0085', { xmlVersion: '1.0' }) // false — NEL (Next Line), not in 1.0 ranges
|
|
66
|
+
name('\u0085', { xmlVersion: '1.1' }) // true — explicitly allowed in 1.1
|
|
67
|
+
|
|
68
|
+
name('\uD800\uDC00', { xmlVersion: '1.0' }) // false
|
|
69
|
+
name('\uD800\uDC00', { xmlVersion: '1.1' }) // true
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
---
|
|
73
|
+
|
|
74
|
+
### Diagnostic validation
|
|
75
|
+
|
|
76
|
+
```js
|
|
77
|
+
import { validate } from 'xml-naming';
|
|
78
|
+
|
|
79
|
+
validate('svg:circle', 'qName')
|
|
80
|
+
// { valid: true, production: 'qName', input: 'svg:circle' }
|
|
81
|
+
|
|
82
|
+
validate('1foo', 'ncName')
|
|
83
|
+
// {
|
|
84
|
+
// valid: false,
|
|
85
|
+
// production: 'ncName',
|
|
86
|
+
// input: '1foo',
|
|
87
|
+
// reason: 'First character "1" is not a valid NameStartChar',
|
|
88
|
+
// position: 0
|
|
89
|
+
// }
|
|
90
|
+
|
|
91
|
+
validate('foo:bar', 'ncName')
|
|
92
|
+
// {
|
|
93
|
+
// valid: false,
|
|
94
|
+
// production: 'ncName',
|
|
95
|
+
// input: 'foo:bar',
|
|
96
|
+
// reason: 'Colon is not allowed in NCName',
|
|
97
|
+
// position: 3
|
|
98
|
+
// }
|
|
99
|
+
|
|
100
|
+
validate('a:b:c', 'qName')
|
|
101
|
+
// {
|
|
102
|
+
// valid: false,
|
|
103
|
+
// production: 'qName',
|
|
104
|
+
// input: 'a:b:c',
|
|
105
|
+
// reason: 'QName can have at most one colon',
|
|
106
|
+
// position: 3
|
|
107
|
+
// }
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
---
|
|
111
|
+
|
|
112
|
+
### Batch validation
|
|
113
|
+
|
|
114
|
+
```js
|
|
115
|
+
import { validateAll } from 'xml-naming';
|
|
116
|
+
|
|
117
|
+
validateAll(['svg', 'circle', '123bad', 'xlink:href'], 'ncName')
|
|
118
|
+
// [
|
|
119
|
+
// { valid: true, production: 'ncName', input: 'svg' },
|
|
120
|
+
// { valid: true, production: 'ncName', input: 'circle' },
|
|
121
|
+
// { valid: false, production: 'ncName', input: '123bad', reason: '...', position: 0 },
|
|
122
|
+
// { valid: false, production: 'ncName', input: 'xlink:href',reason: '...', position: 5 }
|
|
123
|
+
// ]
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
---
|
|
127
|
+
|
|
128
|
+
### Sanitize / auto-fix
|
|
129
|
+
|
|
130
|
+
Useful when generating XML/SVG programmatically from user-supplied strings:
|
|
131
|
+
|
|
132
|
+
```js
|
|
133
|
+
import { sanitize } from 'xml-naming';
|
|
134
|
+
|
|
135
|
+
sanitize('123abc', 'ncName') // '_123abc' ← digit start fixed
|
|
136
|
+
sanitize('my element','name') // 'my_element' ← space replaced
|
|
137
|
+
sanitize('foo:bar', 'ncName') // 'foobar' ← colon stripped
|
|
138
|
+
sanitize('hello!', 'name') // 'hello_' ← illegal char replaced
|
|
139
|
+
|
|
140
|
+
// Custom replacement character
|
|
141
|
+
sanitize('my element', 'name', { replacement: '-' }) // 'my-element'
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
---
|
|
145
|
+
|
|
146
|
+
## Which production should I use?
|
|
147
|
+
|
|
148
|
+
| Context | Production |
|
|
149
|
+
|---|---|
|
|
150
|
+
| XML element/attribute names (namespace-aware) | `qName` |
|
|
151
|
+
| SVG `id` attribute values | `ncName` |
|
|
152
|
+
| Namespace prefix alone | `ncName` |
|
|
153
|
+
| DOCTYPE `<!ENTITY name ...>` | `name` |
|
|
154
|
+
| DOCTYPE `<!NOTATION name ...>` | `name` |
|
|
155
|
+
| DTD `NMTOKEN` attribute values | `nmToken` |
|
|
156
|
+
| DTD `NMTOKENS` attribute values | `nmTokens` |
|
|
157
|
+
|
|
158
|
+
> **Note:** DOCTYPE entity and notation names must use `Name`, not `QName`. Colons carry no namespace meaning in the DTD subset.
|
|
159
|
+
|
|
160
|
+
---
|
|
161
|
+
|
|
162
|
+
## API
|
|
163
|
+
|
|
164
|
+
### `name(str, opts?)` → `boolean`
|
|
165
|
+
### `ncName(str, opts?)` → `boolean`
|
|
166
|
+
### `qName(str, opts?)` → `boolean`
|
|
167
|
+
### `nmToken(str, opts?)` → `boolean`
|
|
168
|
+
### `nmTokens(str, opts?)` → `boolean`
|
|
169
|
+
|
|
170
|
+
`opts`:
|
|
171
|
+
- `xmlVersion`: `'1.0'` (default) | `'1.1'`
|
|
172
|
+
|
|
173
|
+
### `validate(str, production, opts?)` → `ValidationResult`
|
|
174
|
+
|
|
175
|
+
`production`: `'name'` | `'ncName'` | `'qName'` | `'nmToken'` | `'nmTokens'`
|
|
176
|
+
|
|
177
|
+
### `validateAll(strings[], production, opts?)` → `ValidationResult[]`
|
|
178
|
+
|
|
179
|
+
### `sanitize(str, production?, opts?)` → `string`
|
|
180
|
+
|
|
181
|
+
`opts`:
|
|
182
|
+
- `xmlVersion`: `'1.0'` | `'1.1'`
|
|
183
|
+
- `replacement`: string (default `'_'`)
|
|
184
|
+
|
|
185
|
+
---
|
|
186
|
+
|
|
187
|
+
## License
|
|
188
|
+
|
|
189
|
+
MIT
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "xml-naming",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Validates XML name productions — Name, NCName, QName, NMToken, NMTokens — for XML 1.0 and 1.1",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./src/index.js",
|
|
7
|
+
"types": "./src/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"import": "./src/index.js",
|
|
11
|
+
"types": "./src/index.d.ts"
|
|
12
|
+
}
|
|
13
|
+
},
|
|
14
|
+
"files": [
|
|
15
|
+
"src",
|
|
16
|
+
"README.md"
|
|
17
|
+
],
|
|
18
|
+
"scripts": {
|
|
19
|
+
"test": "jasmine specs/*spec.js"
|
|
20
|
+
},
|
|
21
|
+
"keywords": [
|
|
22
|
+
"xml",
|
|
23
|
+
"xml-name",
|
|
24
|
+
"ncname",
|
|
25
|
+
"qname",
|
|
26
|
+
"nmtoken",
|
|
27
|
+
"xml-validation",
|
|
28
|
+
"xml-namespace",
|
|
29
|
+
"name-validator",
|
|
30
|
+
"xml-1.0",
|
|
31
|
+
"xml-1.1"
|
|
32
|
+
],
|
|
33
|
+
"author": "Amit Gupta (https://solothought.com)",
|
|
34
|
+
"license": "MIT",
|
|
35
|
+
"funding": [
|
|
36
|
+
{
|
|
37
|
+
"type": "github",
|
|
38
|
+
"url": "https://github.com/sponsors/NaturalIntelligence"
|
|
39
|
+
}
|
|
40
|
+
],
|
|
41
|
+
"devDependencies": {
|
|
42
|
+
"jasmine": "^5.0.0"
|
|
43
|
+
},
|
|
44
|
+
"engines": {
|
|
45
|
+
"node": ">=16.0.0"
|
|
46
|
+
},
|
|
47
|
+
"repository": {
|
|
48
|
+
"type": "git",
|
|
49
|
+
"url": "https://github.com/NaturalIntelligence/xml-naming"
|
|
50
|
+
},
|
|
51
|
+
"bugs": {
|
|
52
|
+
"url": "https://github.com/NaturalIntelligence/xml-naming/issues"
|
|
53
|
+
}
|
|
54
|
+
}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
export interface ValidationOptions {
|
|
2
|
+
/** XML specification version to validate against. Defaults to '1.0'. */
|
|
3
|
+
xmlVersion?: '1.0' | '1.1';
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
export interface SanitizeOptions extends ValidationOptions {
|
|
7
|
+
/** Character used to replace invalid characters. Defaults to '_'. */
|
|
8
|
+
replacement?: string;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export type Production = 'name' | 'ncName' | 'qName' | 'nmToken' | 'nmTokens';
|
|
12
|
+
|
|
13
|
+
export interface ValidationResult {
|
|
14
|
+
valid: boolean;
|
|
15
|
+
production: Production;
|
|
16
|
+
input: string;
|
|
17
|
+
/** Present only when valid is false. */
|
|
18
|
+
reason?: string;
|
|
19
|
+
/** Index of the first offending character. Present only when valid is false. */
|
|
20
|
+
position?: number;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Returns true if the string is a valid XML Name.
|
|
25
|
+
* Colons are permitted anywhere (Name production).
|
|
26
|
+
* Used for: DOCTYPE entity names, notation names, DTD element declarations.
|
|
27
|
+
*/
|
|
28
|
+
export function name(str: string, opts?: ValidationOptions): boolean;
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Returns true if the string is a valid NCName (Non-Colonized Name).
|
|
32
|
+
* Colons are not permitted.
|
|
33
|
+
* Used for: namespace prefixes, local names, SVG id attributes.
|
|
34
|
+
*/
|
|
35
|
+
export function ncName(str: string, opts?: ValidationOptions): boolean;
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Returns true if the string is a valid QName (Qualified Name).
|
|
39
|
+
* Allows exactly one colon as a prefix separator: prefix:localName.
|
|
40
|
+
* Used for: element and attribute names in namespace-aware XML/SVG.
|
|
41
|
+
*/
|
|
42
|
+
export function qName(str: string, opts?: ValidationOptions): boolean;
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Returns true if the string is a valid NMToken.
|
|
46
|
+
* Same character set as Name but no restriction on the first character.
|
|
47
|
+
* Used for: DTD NMTOKEN attribute values.
|
|
48
|
+
*/
|
|
49
|
+
export function nmToken(str: string, opts?: ValidationOptions): boolean;
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Returns true if the string is a valid NMTokens value.
|
|
53
|
+
* A whitespace-separated list of NMToken values.
|
|
54
|
+
* Used for: DTD NMTOKENS attribute values.
|
|
55
|
+
*/
|
|
56
|
+
export function nmTokens(str: string, opts?: ValidationOptions): boolean;
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Validates a string against a named XML production and returns a detailed result.
|
|
60
|
+
*/
|
|
61
|
+
export function validate(str: string, production: Production, opts?: ValidationOptions): ValidationResult;
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Validates an array of strings against a named XML production.
|
|
65
|
+
*/
|
|
66
|
+
export function validateAll(strings: string[], production: Production, opts?: ValidationOptions): ValidationResult[];
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Transforms an invalid string into the nearest valid XML name for the given production.
|
|
70
|
+
* - Strips or replaces illegal characters
|
|
71
|
+
* - Fixes invalid start characters by prepending the replacement character
|
|
72
|
+
* - Removes colons for NCName production
|
|
73
|
+
*/
|
|
74
|
+
export function sanitize(str: string, production?: Production, opts?: SanitizeOptions): string;
|