@dan-uni/dan-any 1.4.4 → 1.4.6

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.
@@ -13992,6 +13992,7 @@
13992
13992
  unpairedTags: [],
13993
13993
  processEntities: true,
13994
13994
  htmlEntities: false,
13995
+ entityDecoder: null,
13995
13996
  ignoreDeclaration: false,
13996
13997
  ignorePiTags: false,
13997
13998
  transformTagName: false,
@@ -14011,16 +14012,17 @@
14011
14012
  if (DANGEROUS_PROPERTY_NAMES.some((dangerous)=>normalized === dangerous.toLowerCase())) throw new Error(`[SECURITY] Invalid ${optionName}: "${propertyName}" is a reserved JavaScript keyword that could cause prototype pollution`);
14012
14013
  if (criticalProperties.some((dangerous)=>normalized === dangerous.toLowerCase())) throw new Error(`[SECURITY] Invalid ${optionName}: "${propertyName}" is a reserved JavaScript keyword that could cause prototype pollution`);
14013
14014
  }
14014
- function normalizeProcessEntities(value) {
14015
+ function normalizeProcessEntities(value, htmlEntities) {
14015
14016
  if ('boolean' == typeof value) return {
14016
14017
  enabled: value,
14017
14018
  maxEntitySize: 10000,
14018
- maxExpansionDepth: 10,
14019
- maxTotalExpansions: 1000,
14019
+ maxExpansionDepth: 10000,
14020
+ maxTotalExpansions: 1 / 0,
14020
14021
  maxExpandedLength: 100000,
14021
- maxEntityCount: 100,
14022
+ maxEntityCount: 1000,
14022
14023
  allowedTags: null,
14023
- tagFilter: null
14024
+ tagFilter: null,
14025
+ appliesTo: "all"
14024
14026
  };
14025
14027
  if ('object' == typeof value && null !== value) return {
14026
14028
  enabled: false !== value.enabled,
@@ -14030,7 +14032,8 @@
14030
14032
  maxExpandedLength: Math.max(1, value.maxExpandedLength ?? 100000),
14031
14033
  maxEntityCount: Math.max(1, value.maxEntityCount ?? 1000),
14032
14034
  allowedTags: value.allowedTags ?? null,
14033
- tagFilter: value.tagFilter ?? null
14035
+ tagFilter: value.tagFilter ?? null,
14036
+ appliesTo: value.appliesTo ?? "all"
14034
14037
  };
14035
14038
  return normalizeProcessEntities(true);
14036
14039
  }
@@ -14060,7 +14063,7 @@
14060
14063
  ];
14061
14064
  for (const { value, name } of propertyNameOptions)if (value) validatePropertyName(value, name);
14062
14065
  if (null === built.onDangerousProperty) built.onDangerousProperty = defaultOnDangerousProperty;
14063
- built.processEntities = normalizeProcessEntities(built.processEntities);
14066
+ built.processEntities = normalizeProcessEntities(built.processEntities, built.htmlEntities);
14064
14067
  built.unpairedTagsSet = new Set(built.unpairedTags);
14065
14068
  if (built.stopNodes && Array.isArray(built.stopNodes)) built.stopNodes = built.stopNodes.map((node)=>{
14066
14069
  if ('string' == typeof node && node.startsWith('*.')) return '..' + node.substring(2);
@@ -14128,11 +14131,7 @@
14128
14131
  [entityName, val, i] = this.readEntityExp(xmlData, i + 1, this.suppressValidationErr);
14129
14132
  if (-1 === val.indexOf("&")) {
14130
14133
  if (false !== this.options.enabled && null != this.options.maxEntityCount && entityCount >= this.options.maxEntityCount) throw new Error(`Entity count (${entityCount + 1}) exceeds maximum allowed (${this.options.maxEntityCount})`);
14131
- const escaped = entityName.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
14132
- entities[entityName] = {
14133
- regx: RegExp(`&${escaped};`, "g"),
14134
- val: val
14135
- };
14134
+ entities[entityName] = val;
14136
14135
  entityCount++;
14137
14136
  }
14138
14137
  } else if (hasBody && hasSeq(xmlData, "!ELEMENT", i)) {
@@ -14821,6 +14820,1333 @@
14821
14820
  return null;
14822
14821
  }
14823
14822
  }
14823
+ const BASIC_LATIN = {
14824
+ amp: '&',
14825
+ AMP: '&',
14826
+ lt: '<',
14827
+ LT: '<',
14828
+ gt: '>',
14829
+ GT: '>',
14830
+ quot: '"',
14831
+ QUOT: '"',
14832
+ apos: "'",
14833
+ lsquo: '‘',
14834
+ rsquo: '’',
14835
+ ldquo: '“',
14836
+ rdquo: '”',
14837
+ lsquor: '‚',
14838
+ rsquor: '’',
14839
+ ldquor: '„',
14840
+ bdquo: '„',
14841
+ comma: ',',
14842
+ period: '.',
14843
+ colon: ':',
14844
+ semi: ';',
14845
+ excl: '!',
14846
+ quest: '?',
14847
+ num: '#',
14848
+ dollar: '$',
14849
+ percent: '%',
14850
+ amp: '&',
14851
+ ast: '*',
14852
+ commat: '@',
14853
+ lowbar: '_',
14854
+ verbar: '|',
14855
+ vert: '|',
14856
+ sol: '/',
14857
+ bsol: '\\',
14858
+ lbrace: '{',
14859
+ rbrace: '}',
14860
+ lbrack: '[',
14861
+ rbrack: ']',
14862
+ lpar: '(',
14863
+ rpar: ')',
14864
+ nbsp: '\u00a0',
14865
+ iexcl: '¡',
14866
+ cent: '¢',
14867
+ pound: '£',
14868
+ curren: '¤',
14869
+ yen: '¥',
14870
+ brvbar: '¦',
14871
+ sect: '§',
14872
+ uml: '¨',
14873
+ copy: '©',
14874
+ COPY: '©',
14875
+ ordf: 'ª',
14876
+ laquo: '«',
14877
+ not: '¬',
14878
+ shy: '\u00ad',
14879
+ reg: '®',
14880
+ REG: '®',
14881
+ macr: '¯',
14882
+ deg: '°',
14883
+ plusmn: '±',
14884
+ sup2: '²',
14885
+ sup3: '³',
14886
+ acute: '´',
14887
+ micro: 'µ',
14888
+ para: '¶',
14889
+ middot: '·',
14890
+ cedil: '¸',
14891
+ sup1: '¹',
14892
+ ordm: 'º',
14893
+ raquo: '»',
14894
+ frac14: '¼',
14895
+ frac12: '½',
14896
+ half: '½',
14897
+ frac34: '¾',
14898
+ iquest: '¿',
14899
+ times: '×',
14900
+ div: '÷',
14901
+ divide: '÷'
14902
+ };
14903
+ const LATIN_ACCENTS = {
14904
+ Agrave: 'À',
14905
+ agrave: 'à',
14906
+ Aacute: 'Á',
14907
+ aacute: 'á',
14908
+ Acirc: 'Â',
14909
+ acirc: 'â',
14910
+ Atilde: 'Ã',
14911
+ atilde: 'ã',
14912
+ Auml: 'Ä',
14913
+ auml: 'ä',
14914
+ Aring: 'Å',
14915
+ aring: 'å',
14916
+ AElig: 'Æ',
14917
+ aelig: 'æ',
14918
+ Ccedil: 'Ç',
14919
+ ccedil: 'ç',
14920
+ Egrave: 'È',
14921
+ egrave: 'è',
14922
+ Eacute: 'É',
14923
+ eacute: 'é',
14924
+ Ecirc: 'Ê',
14925
+ ecirc: 'ê',
14926
+ Euml: 'Ë',
14927
+ euml: 'ë',
14928
+ Igrave: 'Ì',
14929
+ igrave: 'ì',
14930
+ Iacute: 'Í',
14931
+ iacute: 'í',
14932
+ Icirc: 'Î',
14933
+ icirc: 'î',
14934
+ Iuml: 'Ï',
14935
+ iuml: 'ï',
14936
+ ETH: 'Ð',
14937
+ eth: 'ð',
14938
+ Ntilde: 'Ñ',
14939
+ ntilde: 'ñ',
14940
+ Ograve: 'Ò',
14941
+ ograve: 'ò',
14942
+ Oacute: 'Ó',
14943
+ oacute: 'ó',
14944
+ Ocirc: 'Ô',
14945
+ ocirc: 'ô',
14946
+ Otilde: 'Õ',
14947
+ otilde: 'õ',
14948
+ Ouml: 'Ö',
14949
+ ouml: 'ö',
14950
+ Oslash: 'Ø',
14951
+ oslash: 'ø',
14952
+ Ugrave: 'Ù',
14953
+ ugrave: 'ù',
14954
+ Uacute: 'Ú',
14955
+ uacute: 'ú',
14956
+ Ucirc: 'Û',
14957
+ ucirc: 'û',
14958
+ Uuml: 'Ü',
14959
+ uuml: 'ü',
14960
+ Yacute: 'Ý',
14961
+ yacute: 'ý',
14962
+ THORN: 'Þ',
14963
+ thorn: 'þ',
14964
+ szlig: 'ß',
14965
+ yuml: 'ÿ',
14966
+ Yuml: 'Ÿ'
14967
+ };
14968
+ const LATIN_EXTENDED = {
14969
+ Amacr: 'Ā',
14970
+ amacr: 'ā',
14971
+ Abreve: 'Ă',
14972
+ abreve: 'ă',
14973
+ Aogon: 'Ą',
14974
+ aogon: 'ą',
14975
+ Cacute: 'Ć',
14976
+ cacute: 'ć',
14977
+ Ccirc: 'Ĉ',
14978
+ ccirc: 'ĉ',
14979
+ Cdot: 'Ċ',
14980
+ cdot: 'ċ',
14981
+ Ccaron: 'Č',
14982
+ ccaron: 'č',
14983
+ Dcaron: 'Ď',
14984
+ dcaron: 'ď',
14985
+ Dstrok: 'Đ',
14986
+ dstrok: 'đ',
14987
+ Emacr: 'Ē',
14988
+ emacr: 'ē',
14989
+ Ecaron: 'Ě',
14990
+ ecaron: 'ě',
14991
+ Edot: 'Ė',
14992
+ edot: 'ė',
14993
+ Eogon: 'Ę',
14994
+ eogon: 'ę',
14995
+ Gcirc: 'Ĝ',
14996
+ gcirc: 'ĝ',
14997
+ Gbreve: 'Ğ',
14998
+ gbreve: 'ğ',
14999
+ Gdot: 'Ġ',
15000
+ gdot: 'ġ',
15001
+ Gcedil: 'Ģ',
15002
+ Hcirc: 'Ĥ',
15003
+ hcirc: 'ĥ',
15004
+ Hstrok: 'Ħ',
15005
+ hstrok: 'ħ',
15006
+ Itilde: 'Ĩ',
15007
+ itilde: 'ĩ',
15008
+ Imacr: 'Ī',
15009
+ imacr: 'ī',
15010
+ Iogon: 'Į',
15011
+ iogon: 'į',
15012
+ Idot: 'İ',
15013
+ IJlig: 'IJ',
15014
+ ijlig: 'ij',
15015
+ Jcirc: 'Ĵ',
15016
+ jcirc: 'ĵ',
15017
+ Kcedil: 'Ķ',
15018
+ kcedil: 'ķ',
15019
+ kgreen: 'ĸ',
15020
+ Lacute: 'Ĺ',
15021
+ lacute: 'ĺ',
15022
+ Lcedil: 'Ļ',
15023
+ lcedil: 'ļ',
15024
+ Lcaron: 'Ľ',
15025
+ lcaron: 'ľ',
15026
+ Lmidot: 'Ŀ',
15027
+ lmidot: 'ŀ',
15028
+ Lstrok: 'Ł',
15029
+ lstrok: 'ł',
15030
+ Nacute: 'Ń',
15031
+ nacute: 'ń',
15032
+ Ncaron: 'Ň',
15033
+ ncaron: 'ň',
15034
+ Ncedil: 'Ņ',
15035
+ ncedil: 'ņ',
15036
+ ENG: 'Ŋ',
15037
+ eng: 'ŋ',
15038
+ Omacr: 'Ō',
15039
+ omacr: 'ō',
15040
+ Odblac: 'Ő',
15041
+ odblac: 'ő',
15042
+ OElig: 'Œ',
15043
+ oelig: 'œ',
15044
+ Racute: 'Ŕ',
15045
+ racute: 'ŕ',
15046
+ Rcaron: 'Ř',
15047
+ rcaron: 'ř',
15048
+ Rcedil: 'Ŗ',
15049
+ rcedil: 'ŗ',
15050
+ Sacute: 'Ś',
15051
+ sacute: 'ś',
15052
+ Scirc: 'Ŝ',
15053
+ scirc: 'ŝ',
15054
+ Scedil: 'Ş',
15055
+ scedil: 'ş',
15056
+ Scaron: 'Š',
15057
+ scaron: 'š',
15058
+ Tcedil: 'Ţ',
15059
+ tcedil: 'ţ',
15060
+ Tcaron: 'Ť',
15061
+ tcaron: 'ť',
15062
+ Tstrok: 'Ŧ',
15063
+ tstrok: 'ŧ',
15064
+ Utilde: 'Ũ',
15065
+ utilde: 'ũ',
15066
+ Umacr: 'Ū',
15067
+ umacr: 'ū',
15068
+ Ubreve: 'Ŭ',
15069
+ ubreve: 'ŭ',
15070
+ Uring: 'Ů',
15071
+ uring: 'ů',
15072
+ Udblac: 'Ű',
15073
+ udblac: 'ű',
15074
+ Uogon: 'Ų',
15075
+ uogon: 'ų',
15076
+ Wcirc: 'Ŵ',
15077
+ wcirc: 'ŵ',
15078
+ Ycirc: 'Ŷ',
15079
+ ycirc: 'ŷ',
15080
+ Zacute: 'Ź',
15081
+ zacute: 'ź',
15082
+ Zdot: 'Ż',
15083
+ zdot: 'ż',
15084
+ Zcaron: 'Ž',
15085
+ zcaron: 'ž'
15086
+ };
15087
+ const GREEK = {
15088
+ Alpha: 'Α',
15089
+ alpha: 'α',
15090
+ Beta: 'Β',
15091
+ beta: 'β',
15092
+ Gamma: 'Γ',
15093
+ gamma: 'γ',
15094
+ Delta: 'Δ',
15095
+ delta: 'δ',
15096
+ Epsilon: 'Ε',
15097
+ epsilon: 'ε',
15098
+ epsiv: 'ϵ',
15099
+ varepsilon: 'ϵ',
15100
+ Zeta: 'Ζ',
15101
+ zeta: 'ζ',
15102
+ Eta: 'Η',
15103
+ eta: 'η',
15104
+ Theta: 'Θ',
15105
+ theta: 'θ',
15106
+ thetasym: 'ϑ',
15107
+ vartheta: 'ϑ',
15108
+ Iota: 'Ι',
15109
+ iota: 'ι',
15110
+ Kappa: 'Κ',
15111
+ kappa: 'κ',
15112
+ kappav: 'ϰ',
15113
+ varkappa: 'ϰ',
15114
+ Lambda: 'Λ',
15115
+ lambda: 'λ',
15116
+ Mu: 'Μ',
15117
+ mu: 'μ',
15118
+ Nu: 'Ν',
15119
+ nu: 'ν',
15120
+ Xi: 'Ξ',
15121
+ xi: 'ξ',
15122
+ Omicron: 'Ο',
15123
+ omicron: 'ο',
15124
+ Pi: 'Π',
15125
+ pi: 'π',
15126
+ piv: 'ϖ',
15127
+ varpi: 'ϖ',
15128
+ Rho: 'Ρ',
15129
+ rho: 'ρ',
15130
+ rhov: 'ϱ',
15131
+ varrho: 'ϱ',
15132
+ Sigma: 'Σ',
15133
+ sigma: 'σ',
15134
+ sigmaf: 'ς',
15135
+ sigmav: 'ς',
15136
+ varsigma: 'ς',
15137
+ Tau: 'Τ',
15138
+ tau: 'τ',
15139
+ Upsilon: 'Υ',
15140
+ upsilon: 'υ',
15141
+ upsi: 'υ',
15142
+ Upsi: 'ϒ',
15143
+ upsih: 'ϒ',
15144
+ Phi: 'Φ',
15145
+ phi: 'φ',
15146
+ phiv: 'ϕ',
15147
+ varphi: 'ϕ',
15148
+ Chi: 'Χ',
15149
+ chi: 'χ',
15150
+ Psi: 'Ψ',
15151
+ psi: 'ψ',
15152
+ Omega: 'Ω',
15153
+ omega: 'ω',
15154
+ ohm: 'Ω',
15155
+ Gammad: 'Ϝ',
15156
+ gammad: 'ϝ',
15157
+ digamma: 'ϝ'
15158
+ };
15159
+ const CYRILLIC = {
15160
+ Afr: '𝔄',
15161
+ afr: '𝔞',
15162
+ Acy: 'А',
15163
+ acy: 'а',
15164
+ Bcy: 'Б',
15165
+ bcy: 'б',
15166
+ Vcy: 'В',
15167
+ vcy: 'в',
15168
+ Gcy: 'Г',
15169
+ gcy: 'г',
15170
+ Dcy: 'Д',
15171
+ dcy: 'д',
15172
+ IEcy: 'Е',
15173
+ iecy: 'е',
15174
+ IOcy: 'Ё',
15175
+ iocy: 'ё',
15176
+ ZHcy: 'Ж',
15177
+ zhcy: 'ж',
15178
+ Zcy: 'З',
15179
+ zcy: 'з',
15180
+ Icy: 'И',
15181
+ icy: 'и',
15182
+ Jcy: 'Й',
15183
+ jcy: 'й',
15184
+ Kcy: 'К',
15185
+ kcy: 'к',
15186
+ Lcy: 'Л',
15187
+ lcy: 'л',
15188
+ Mcy: 'М',
15189
+ mcy: 'м',
15190
+ Ncy: 'Н',
15191
+ ncy: 'н',
15192
+ Ocy: 'О',
15193
+ ocy: 'о',
15194
+ Pcy: 'П',
15195
+ pcy: 'п',
15196
+ Rcy: 'Р',
15197
+ rcy: 'р',
15198
+ Scy: 'С',
15199
+ scy: 'с',
15200
+ Tcy: 'Т',
15201
+ tcy: 'т',
15202
+ Ucy: 'У',
15203
+ ucy: 'у',
15204
+ Fcy: 'Ф',
15205
+ fcy: 'ф',
15206
+ KHcy: 'Х',
15207
+ khcy: 'х',
15208
+ TScy: 'Ц',
15209
+ tscy: 'ц',
15210
+ CHcy: 'Ч',
15211
+ chcy: 'ч',
15212
+ SHcy: 'Ш',
15213
+ shcy: 'ш',
15214
+ SHCHcy: 'Щ',
15215
+ shchcy: 'щ',
15216
+ HARDcy: 'Ъ',
15217
+ hardcy: 'ъ',
15218
+ Ycy: 'Ы',
15219
+ ycy: 'ы',
15220
+ SOFTcy: 'Ь',
15221
+ softcy: 'ь',
15222
+ Ecy: 'Э',
15223
+ ecy: 'э',
15224
+ YUcy: 'Ю',
15225
+ yucy: 'ю',
15226
+ YAcy: 'Я',
15227
+ yacy: 'я',
15228
+ DJcy: 'Ђ',
15229
+ djcy: 'ђ',
15230
+ GJcy: 'Ѓ',
15231
+ gjcy: 'ѓ',
15232
+ Jukcy: 'Є',
15233
+ jukcy: 'є',
15234
+ DScy: 'Ѕ',
15235
+ dscy: 'ѕ',
15236
+ Iukcy: 'І',
15237
+ iukcy: 'і',
15238
+ YIcy: 'Ї',
15239
+ yicy: 'ї',
15240
+ Jsercy: 'Ј',
15241
+ jsercy: 'ј',
15242
+ LJcy: 'Љ',
15243
+ ljcy: 'љ',
15244
+ NJcy: 'Њ',
15245
+ njcy: 'њ',
15246
+ TSHcy: 'Ћ',
15247
+ tshcy: 'ћ',
15248
+ KJcy: 'Ќ',
15249
+ kjcy: 'ќ',
15250
+ Ubrcy: 'Ў',
15251
+ ubrcy: 'ў',
15252
+ DZcy: 'Џ',
15253
+ dzcy: 'џ'
15254
+ };
15255
+ const MATH = {
15256
+ plus: '+',
15257
+ minus: '−',
15258
+ mnplus: '∓',
15259
+ mp: '∓',
15260
+ pm: '±',
15261
+ times: '×',
15262
+ div: '÷',
15263
+ divide: '÷',
15264
+ sdot: '⋅',
15265
+ star: '☆',
15266
+ starf: '★',
15267
+ bigstar: '★',
15268
+ lowast: '∗',
15269
+ ast: '*',
15270
+ midast: '*',
15271
+ compfn: '∘',
15272
+ smallcircle: '∘',
15273
+ bullet: '•',
15274
+ bull: '•',
15275
+ nbsp: '\u00a0',
15276
+ hellip: '…',
15277
+ mldr: '…',
15278
+ prime: '′',
15279
+ Prime: '″',
15280
+ tprime: '‴',
15281
+ bprime: '‵',
15282
+ backprime: '‵',
15283
+ minus: '−',
15284
+ minusd: '∸',
15285
+ dotminus: '∸',
15286
+ plusdo: '∔',
15287
+ dotplus: '∔',
15288
+ plusmn: '±',
15289
+ minusplus: '∓',
15290
+ mnplus: '∓',
15291
+ mp: '∓',
15292
+ setminus: '∖',
15293
+ smallsetminus: '∖',
15294
+ Backslash: '∖',
15295
+ setmn: '∖',
15296
+ ssetmn: '∖',
15297
+ lowbar: '_',
15298
+ verbar: '|',
15299
+ vert: '|',
15300
+ VerticalLine: '|',
15301
+ colon: ':',
15302
+ Colon: '∷',
15303
+ Proportion: '∷',
15304
+ ratio: '∶',
15305
+ equals: '=',
15306
+ ne: '≠',
15307
+ nequiv: '≢',
15308
+ equiv: '≡',
15309
+ Congruent: '≡',
15310
+ sim: '∼',
15311
+ thicksim: '∼',
15312
+ thksim: '∼',
15313
+ sime: '≃',
15314
+ simeq: '≃',
15315
+ TildeEqual: '≃',
15316
+ asymp: '≈',
15317
+ approx: '≈',
15318
+ thickapprox: '≈',
15319
+ thkap: '≈',
15320
+ TildeTilde: '≈',
15321
+ ncong: '≇',
15322
+ cong: '≅',
15323
+ TildeFullEqual: '≅',
15324
+ asympeq: '≍',
15325
+ CupCap: '≍',
15326
+ bump: '≎',
15327
+ Bumpeq: '≎',
15328
+ HumpDownHump: '≎',
15329
+ bumpe: '≏',
15330
+ bumpeq: '≏',
15331
+ HumpEqual: '≏',
15332
+ dotminus: '∸',
15333
+ minusd: '∸',
15334
+ plusdo: '∔',
15335
+ dotplus: '∔',
15336
+ le: '≤',
15337
+ LessEqual: '≤',
15338
+ ge: '≥',
15339
+ GreaterEqual: '≥',
15340
+ lesseqgtr: '⋚',
15341
+ lesseqqgtr: '⪋',
15342
+ greater: '>',
15343
+ less: '<'
15344
+ };
15345
+ const MATH_ADVANCED = {
15346
+ alefsym: 'ℵ',
15347
+ aleph: 'ℵ',
15348
+ beth: 'ℶ',
15349
+ gimel: 'ℷ',
15350
+ daleth: 'ℸ',
15351
+ forall: '∀',
15352
+ ForAll: '∀',
15353
+ part: '∂',
15354
+ PartialD: '∂',
15355
+ exist: '∃',
15356
+ Exists: '∃',
15357
+ nexist: '∄',
15358
+ nexists: '∄',
15359
+ empty: '∅',
15360
+ emptyset: '∅',
15361
+ emptyv: '∅',
15362
+ varnothing: '∅',
15363
+ nabla: '∇',
15364
+ Del: '∇',
15365
+ isin: '∈',
15366
+ isinv: '∈',
15367
+ in: '∈',
15368
+ Element: '∈',
15369
+ notin: '∉',
15370
+ notinva: '∉',
15371
+ ni: '∋',
15372
+ niv: '∋',
15373
+ SuchThat: '∋',
15374
+ ReverseElement: '∋',
15375
+ notni: '∌',
15376
+ notniva: '∌',
15377
+ prod: '∏',
15378
+ Product: '∏',
15379
+ coprod: '∐',
15380
+ Coproduct: '∐',
15381
+ sum: '∑',
15382
+ Sum: '∑',
15383
+ minus: '−',
15384
+ mp: '∓',
15385
+ plusdo: '∔',
15386
+ dotplus: '∔',
15387
+ setminus: '∖',
15388
+ lowast: '∗',
15389
+ radic: '√',
15390
+ Sqrt: '√',
15391
+ prop: '∝',
15392
+ propto: '∝',
15393
+ Proportional: '∝',
15394
+ varpropto: '∝',
15395
+ infin: '∞',
15396
+ infintie: '⧝',
15397
+ ang: '∠',
15398
+ angle: '∠',
15399
+ angmsd: '∡',
15400
+ measuredangle: '∡',
15401
+ angsph: '∢',
15402
+ mid: '∣',
15403
+ VerticalBar: '∣',
15404
+ nmid: '∤',
15405
+ nsmid: '∤',
15406
+ npar: '∦',
15407
+ parallel: '∥',
15408
+ spar: '∥',
15409
+ nparallel: '∦',
15410
+ nspar: '∦',
15411
+ and: '∧',
15412
+ wedge: '∧',
15413
+ or: '∨',
15414
+ vee: '∨',
15415
+ cap: '∩',
15416
+ cup: '∪',
15417
+ int: '∫',
15418
+ Integral: '∫',
15419
+ conint: '∮',
15420
+ ContourIntegral: '∮',
15421
+ Conint: '∯',
15422
+ DoubleContourIntegral: '∯',
15423
+ Cconint: '∰',
15424
+ there4: '∴',
15425
+ therefore: '∴',
15426
+ Therefore: '∴',
15427
+ becaus: '∵',
15428
+ because: '∵',
15429
+ Because: '∵',
15430
+ ratio: '∶',
15431
+ Proportion: '∷',
15432
+ minusd: '∸',
15433
+ dotminus: '∸',
15434
+ mDDot: '∺',
15435
+ homtht: '∻',
15436
+ sim: '∼',
15437
+ bsimg: '∽',
15438
+ backsim: '∽',
15439
+ ac: '∾',
15440
+ mstpos: '∾',
15441
+ acd: '∿',
15442
+ VerticalTilde: '≀',
15443
+ wr: '≀',
15444
+ wreath: '≀',
15445
+ nsime: '≄',
15446
+ nsimeq: '≄',
15447
+ nsimeq: '≄',
15448
+ ncong: '≇',
15449
+ simne: '≆',
15450
+ ncongdot: '⩭̸',
15451
+ ngsim: '≵',
15452
+ nsim: '≁',
15453
+ napprox: '≉',
15454
+ nap: '≉',
15455
+ ngeq: '≱',
15456
+ nge: '≱',
15457
+ nleq: '≰',
15458
+ nle: '≰',
15459
+ ngtr: '≯',
15460
+ ngt: '≯',
15461
+ nless: '≮',
15462
+ nlt: '≮',
15463
+ nprec: '⊀',
15464
+ npr: '⊀',
15465
+ nsucc: '⊁',
15466
+ nsc: '⊁'
15467
+ };
15468
+ const ARROWS = {
15469
+ larr: '←',
15470
+ leftarrow: '←',
15471
+ LeftArrow: '←',
15472
+ uarr: '↑',
15473
+ uparrow: '↑',
15474
+ UpArrow: '↑',
15475
+ rarr: '→',
15476
+ rightarrow: '→',
15477
+ RightArrow: '→',
15478
+ darr: '↓',
15479
+ downarrow: '↓',
15480
+ DownArrow: '↓',
15481
+ harr: '↔',
15482
+ leftrightarrow: '↔',
15483
+ LeftRightArrow: '↔',
15484
+ varr: '↕',
15485
+ updownarrow: '↕',
15486
+ UpDownArrow: '↕',
15487
+ nwarr: '↖',
15488
+ nwarrow: '↖',
15489
+ UpperLeftArrow: '↖',
15490
+ nearr: '↗',
15491
+ nearrow: '↗',
15492
+ UpperRightArrow: '↗',
15493
+ searr: '↘',
15494
+ searrow: '↘',
15495
+ LowerRightArrow: '↘',
15496
+ swarr: '↙',
15497
+ swarrow: '↙',
15498
+ LowerLeftArrow: '↙',
15499
+ lArr: '⇐',
15500
+ Leftarrow: '⇐',
15501
+ uArr: '⇑',
15502
+ Uparrow: '⇑',
15503
+ rArr: '⇒',
15504
+ Rightarrow: '⇒',
15505
+ dArr: '⇓',
15506
+ Downarrow: '⇓',
15507
+ hArr: '⇔',
15508
+ Leftrightarrow: '⇔',
15509
+ iff: '⇔',
15510
+ vArr: '⇕',
15511
+ Updownarrow: '⇕',
15512
+ lAarr: '⇚',
15513
+ Lleftarrow: '⇚',
15514
+ rAarr: '⇛',
15515
+ Rrightarrow: '⇛',
15516
+ lrarr: '⇆',
15517
+ leftrightarrows: '⇆',
15518
+ rlarr: '⇄',
15519
+ rightleftarrows: '⇄',
15520
+ lrhar: '⇋',
15521
+ leftrightharpoons: '⇋',
15522
+ ReverseEquilibrium: '⇋',
15523
+ rlhar: '⇌',
15524
+ rightleftharpoons: '⇌',
15525
+ Equilibrium: '⇌',
15526
+ udarr: '⇅',
15527
+ UpArrowDownArrow: '⇅',
15528
+ duarr: '⇵',
15529
+ DownArrowUpArrow: '⇵',
15530
+ llarr: '⇇',
15531
+ leftleftarrows: '⇇',
15532
+ rrarr: '⇉',
15533
+ rightrightarrows: '⇉',
15534
+ ddarr: '⇊',
15535
+ downdownarrows: '⇊',
15536
+ har: '↽',
15537
+ lhard: '↽',
15538
+ leftharpoondown: '↽',
15539
+ lharu: '↼',
15540
+ leftharpoonup: '↼',
15541
+ rhard: '⇁',
15542
+ rightharpoondown: '⇁',
15543
+ rharu: '⇀',
15544
+ rightharpoonup: '⇀',
15545
+ lsh: '↰',
15546
+ Lsh: '↰',
15547
+ rsh: '↱',
15548
+ Rsh: '↱',
15549
+ ldsh: '↲',
15550
+ rdsh: '↳',
15551
+ hookleftarrow: '↩',
15552
+ hookrightarrow: '↪',
15553
+ mapstoleft: '↤',
15554
+ mapstoup: '↥',
15555
+ map: '↦',
15556
+ mapsto: '↦',
15557
+ mapstodown: '↧',
15558
+ crarr: '↵',
15559
+ nwarrow: '↖',
15560
+ nearrow: '↗',
15561
+ searrow: '↘',
15562
+ swarrow: '↙',
15563
+ nleftarrow: '↚',
15564
+ nleftrightarrow: '↮',
15565
+ nrightarrow: '↛',
15566
+ nrarr: '↛',
15567
+ larrtl: '↢',
15568
+ rarrtl: '↣',
15569
+ leftarrowtail: '↢',
15570
+ rightarrowtail: '↣',
15571
+ twoheadleftarrow: '↞',
15572
+ twoheadrightarrow: '↠',
15573
+ Larr: '↞',
15574
+ Rarr: '↠',
15575
+ larrhk: '↩',
15576
+ rarrhk: '↪',
15577
+ larrlp: '↫',
15578
+ looparrowleft: '↫',
15579
+ rarrlp: '↬',
15580
+ looparrowright: '↬',
15581
+ harrw: '↭',
15582
+ leftrightsquigarrow: '↭',
15583
+ nrarrw: '↝̸',
15584
+ rarrw: '↝',
15585
+ rightsquigarrow: '↝',
15586
+ larrbfs: '⤟',
15587
+ rarrbfs: '⤠',
15588
+ nvHarr: '⤄',
15589
+ nvlArr: '⤂',
15590
+ nvrArr: '⤃',
15591
+ larrfs: '⤝',
15592
+ rarrfs: '⤞',
15593
+ Map: '⤅',
15594
+ larrsim: '⥳',
15595
+ rarrsim: '⥴',
15596
+ harrcir: '⥈',
15597
+ Uarrocir: '⥉',
15598
+ lurdshar: '⥊',
15599
+ ldrdhar: '⥧',
15600
+ ldrushar: '⥋',
15601
+ rdldhar: '⥩',
15602
+ lrhard: '⥭',
15603
+ rlhar: '⇌',
15604
+ uharr: '↾',
15605
+ uharl: '↿',
15606
+ dharr: '⇂',
15607
+ dharl: '⇃',
15608
+ Uarr: '↟',
15609
+ Darr: '↡',
15610
+ zigrarr: '⇝',
15611
+ nwArr: '⇖',
15612
+ neArr: '⇗',
15613
+ seArr: '⇘',
15614
+ swArr: '⇙',
15615
+ nharr: '↮',
15616
+ nhArr: '⇎',
15617
+ nlarr: '↚',
15618
+ nlArr: '⇍',
15619
+ nrarr: '↛',
15620
+ nrArr: '⇏',
15621
+ larrb: '⇤',
15622
+ LeftArrowBar: '⇤',
15623
+ rarrb: '⇥',
15624
+ RightArrowBar: '⇥'
15625
+ };
15626
+ const SHAPES = {
15627
+ square: '□',
15628
+ Square: '□',
15629
+ squ: '□',
15630
+ squf: '▪',
15631
+ squarf: '▪',
15632
+ blacksquar: '▪',
15633
+ blacksquare: '▪',
15634
+ FilledVerySmallSquare: '▪',
15635
+ blk34: '▓',
15636
+ blk12: '▒',
15637
+ blk14: '░',
15638
+ block: '█',
15639
+ srect: '▭',
15640
+ rect: '▭',
15641
+ sdot: '⋅',
15642
+ sdotb: '⊡',
15643
+ dotsquare: '⊡',
15644
+ triangle: '▵',
15645
+ tri: '▵',
15646
+ trine: '▵',
15647
+ utri: '▵',
15648
+ triangledown: '▿',
15649
+ dtri: '▿',
15650
+ tridown: '▿',
15651
+ triangleleft: '◃',
15652
+ ltri: '◃',
15653
+ triangleright: '▹',
15654
+ rtri: '▹',
15655
+ blacktriangle: '▴',
15656
+ utrif: '▴',
15657
+ blacktriangledown: '▾',
15658
+ dtrif: '▾',
15659
+ blacktriangleleft: '◂',
15660
+ ltrif: '◂',
15661
+ blacktriangleright: '▸',
15662
+ rtrif: '▸',
15663
+ loz: '◊',
15664
+ lozenge: '◊',
15665
+ blacklozenge: '⧫',
15666
+ lozf: '⧫',
15667
+ bigcirc: '◯',
15668
+ xcirc: '◯',
15669
+ circ: 'ˆ',
15670
+ Circle: '○',
15671
+ cir: '○',
15672
+ o: '○',
15673
+ bullet: '•',
15674
+ bull: '•',
15675
+ hellip: '…',
15676
+ mldr: '…',
15677
+ nldr: '‥',
15678
+ boxh: '─',
15679
+ HorizontalLine: '─',
15680
+ boxv: '│',
15681
+ boxdr: '┌',
15682
+ boxdl: '┐',
15683
+ boxur: '└',
15684
+ boxul: '┘',
15685
+ boxvr: '├',
15686
+ boxvl: '┤',
15687
+ boxhd: '┬',
15688
+ boxhu: '┴',
15689
+ boxvh: '┼',
15690
+ boxH: '═',
15691
+ boxV: '║',
15692
+ boxdR: '╒',
15693
+ boxDr: '╓',
15694
+ boxDR: '╔',
15695
+ boxDl: '╕',
15696
+ boxdL: '╖',
15697
+ boxDL: '╗',
15698
+ boxuR: '╘',
15699
+ boxUr: '╙',
15700
+ boxUR: '╚',
15701
+ boxUl: '╜',
15702
+ boxuL: '╛',
15703
+ boxUL: '╝',
15704
+ boxvR: '╞',
15705
+ boxVr: '╟',
15706
+ boxVR: '╠',
15707
+ boxVl: '╢',
15708
+ boxvL: '╡',
15709
+ boxVL: '╣',
15710
+ boxHd: '╤',
15711
+ boxhD: '╥',
15712
+ boxHD: '╦',
15713
+ boxHu: '╧',
15714
+ boxhU: '╨',
15715
+ boxHU: '╩',
15716
+ boxvH: '╪',
15717
+ boxVh: '╫',
15718
+ boxVH: '╬'
15719
+ };
15720
+ const PUNCTUATION = {
15721
+ excl: '!',
15722
+ iexcl: '¡',
15723
+ brvbar: '¦',
15724
+ sect: '§',
15725
+ uml: '¨',
15726
+ copy: '©',
15727
+ ordf: 'ª',
15728
+ laquo: '«',
15729
+ not: '¬',
15730
+ shy: '\u00ad',
15731
+ reg: '®',
15732
+ macr: '¯',
15733
+ deg: '°',
15734
+ plusmn: '±',
15735
+ sup2: '²',
15736
+ sup3: '³',
15737
+ acute: '´',
15738
+ micro: 'µ',
15739
+ para: '¶',
15740
+ middot: '·',
15741
+ cedil: '¸',
15742
+ sup1: '¹',
15743
+ ordm: 'º',
15744
+ raquo: '»',
15745
+ frac14: '¼',
15746
+ frac12: '½',
15747
+ frac34: '¾',
15748
+ iquest: '¿',
15749
+ nbsp: '\u00a0',
15750
+ comma: ',',
15751
+ period: '.',
15752
+ colon: ':',
15753
+ semi: ';',
15754
+ vert: '|',
15755
+ Verbar: '‖',
15756
+ verbar: '|',
15757
+ dblac: '˝',
15758
+ circ: 'ˆ',
15759
+ caron: 'ˇ',
15760
+ breve: '˘',
15761
+ dot: '˙',
15762
+ ring: '˚',
15763
+ ogon: '˛',
15764
+ tilde: '˜',
15765
+ DiacriticalGrave: '`',
15766
+ DiacriticalAcute: '´',
15767
+ DiacriticalTilde: '˜',
15768
+ DiacriticalDot: '˙',
15769
+ DiacriticalDoubleAcute: '˝',
15770
+ grave: '`',
15771
+ acute: '´'
15772
+ };
15773
+ const CURRENCY = {
15774
+ cent: '¢',
15775
+ pound: '£',
15776
+ curren: '¤',
15777
+ yen: '¥',
15778
+ euro: '€',
15779
+ dollar: '$',
15780
+ euro: '€',
15781
+ fnof: 'ƒ',
15782
+ inr: '₹',
15783
+ af: '؋',
15784
+ birr: 'ብር',
15785
+ peso: '₱',
15786
+ rub: '₽',
15787
+ won: '₩',
15788
+ yuan: '¥',
15789
+ cedil: '¸'
15790
+ };
15791
+ const FRACTIONS = {
15792
+ frac12: '½',
15793
+ half: '½',
15794
+ frac13: '⅓',
15795
+ frac14: '¼',
15796
+ frac15: '⅕',
15797
+ frac16: '⅙',
15798
+ frac18: '⅛',
15799
+ frac23: '⅔',
15800
+ frac25: '⅖',
15801
+ frac34: '¾',
15802
+ frac35: '⅗',
15803
+ frac38: '⅜',
15804
+ frac45: '⅘',
15805
+ frac56: '⅚',
15806
+ frac58: '⅝',
15807
+ frac78: '⅞',
15808
+ frasl: '⁄'
15809
+ };
15810
+ const MISC_SYMBOLS = {
15811
+ trade: '™',
15812
+ TRADE: '™',
15813
+ telrec: '⌕',
15814
+ target: '⌖',
15815
+ ulcorn: '⌜',
15816
+ ulcorner: '⌜',
15817
+ urcorn: '⌝',
15818
+ urcorner: '⌝',
15819
+ dlcorn: '⌞',
15820
+ llcorner: '⌞',
15821
+ drcorn: '⌟',
15822
+ lrcorner: '⌟',
15823
+ intercal: '⊺',
15824
+ intcal: '⊺',
15825
+ oplus: '⊕',
15826
+ CirclePlus: '⊕',
15827
+ ominus: '⊖',
15828
+ CircleMinus: '⊖',
15829
+ otimes: '⊗',
15830
+ CircleTimes: '⊗',
15831
+ osol: '⊘',
15832
+ odot: '⊙',
15833
+ CircleDot: '⊙',
15834
+ oast: '⊛',
15835
+ circledast: '⊛',
15836
+ odash: '⊝',
15837
+ circleddash: '⊝',
15838
+ ocirc: '⊚',
15839
+ circledcirc: '⊚',
15840
+ boxplus: '⊞',
15841
+ plusb: '⊞',
15842
+ boxminus: '⊟',
15843
+ minusb: '⊟',
15844
+ boxtimes: '⊠',
15845
+ timesb: '⊠',
15846
+ boxdot: '⊡',
15847
+ sdotb: '⊡',
15848
+ veebar: '⊻',
15849
+ vee: '∨',
15850
+ barvee: '⊽',
15851
+ and: '∧',
15852
+ wedge: '∧',
15853
+ Cap: '⋒',
15854
+ Cup: '⋓',
15855
+ Fork: '⋔',
15856
+ pitchfork: '⋔',
15857
+ epar: '⋕',
15858
+ ltlarr: '⥶',
15859
+ nvap: '≍⃒',
15860
+ nvsim: '∼⃒',
15861
+ nvge: '≥⃒',
15862
+ nvle: '≤⃒',
15863
+ nvlt: '<⃒',
15864
+ nvgt: '>⃒',
15865
+ nvltrie: '⊴⃒',
15866
+ nvrtrie: '⊵⃒',
15867
+ Vdash: '⊩',
15868
+ dashv: '⊣',
15869
+ vDash: '⊨',
15870
+ Vdash: '⊩',
15871
+ Vvdash: '⊪',
15872
+ nvdash: '⊬',
15873
+ nvDash: '⊭',
15874
+ nVdash: '⊮',
15875
+ nVDash: '⊯'
15876
+ };
15877
+ ({
15878
+ ...BASIC_LATIN,
15879
+ ...LATIN_ACCENTS,
15880
+ ...LATIN_EXTENDED,
15881
+ ...GREEK,
15882
+ ...CYRILLIC,
15883
+ ...MATH,
15884
+ ...MATH_ADVANCED,
15885
+ ...ARROWS,
15886
+ ...SHAPES,
15887
+ ...PUNCTUATION,
15888
+ ...CURRENCY,
15889
+ ...FRACTIONS,
15890
+ ...MISC_SYMBOLS
15891
+ });
15892
+ const XML = {
15893
+ amp: "&",
15894
+ apos: "'",
15895
+ gt: ">",
15896
+ lt: "<",
15897
+ quot: "\""
15898
+ };
15899
+ const COMMON_HTML = {
15900
+ nbsp: '\u00a0',
15901
+ copy: '\u00a9',
15902
+ reg: '\u00ae',
15903
+ trade: '\u2122',
15904
+ mdash: '\u2014',
15905
+ ndash: '\u2013',
15906
+ hellip: '\u2026',
15907
+ laquo: '\u00ab',
15908
+ raquo: '\u00bb',
15909
+ lsquo: '\u2018',
15910
+ rsquo: '\u2019',
15911
+ ldquo: '\u201c',
15912
+ rdquo: '\u201d',
15913
+ bull: '\u2022',
15914
+ para: '\u00b6',
15915
+ sect: '\u00a7',
15916
+ deg: '\u00b0',
15917
+ frac12: '\u00bd',
15918
+ frac14: '\u00bc',
15919
+ frac34: '\u00be'
15920
+ };
15921
+ const SPECIAL_CHARS = new Set('!?\\\\/[]$%{}^&*()<>|+');
15922
+ function EntityDecoder_validateEntityName(name) {
15923
+ if ('#' === name[0]) throw new Error(`[EntityReplacer] Invalid character '#' in entity name: "${name}"`);
15924
+ for (const ch of name)if (SPECIAL_CHARS.has(ch)) throw new Error(`[EntityReplacer] Invalid character '${ch}' in entity name: "${name}"`);
15925
+ return name;
15926
+ }
15927
+ function mergeEntityMaps(...maps) {
15928
+ const out = Object.create(null);
15929
+ for (const map of maps)if (map) for (const key of Object.keys(map)){
15930
+ const raw = map[key];
15931
+ if ('string' == typeof raw) out[key] = raw;
15932
+ else if (raw && 'object' == typeof raw && void 0 !== raw.val) {
15933
+ const val = raw.val;
15934
+ if ('string' == typeof val) out[key] = val;
15935
+ }
15936
+ }
15937
+ return out;
15938
+ }
15939
+ const LIMIT_TIER_EXTERNAL = 'external';
15940
+ const LIMIT_TIER_BASE = 'base';
15941
+ const LIMIT_TIER_ALL = 'all';
15942
+ function parseLimitTiers(raw) {
15943
+ if (!raw || raw === LIMIT_TIER_EXTERNAL) return new Set([
15944
+ LIMIT_TIER_EXTERNAL
15945
+ ]);
15946
+ if (raw === LIMIT_TIER_ALL) return new Set([
15947
+ LIMIT_TIER_ALL
15948
+ ]);
15949
+ if (raw === LIMIT_TIER_BASE) return new Set([
15950
+ LIMIT_TIER_BASE
15951
+ ]);
15952
+ if (Array.isArray(raw)) return new Set(raw);
15953
+ return new Set([
15954
+ LIMIT_TIER_EXTERNAL
15955
+ ]);
15956
+ }
15957
+ const NCR_LEVEL = Object.freeze({
15958
+ allow: 0,
15959
+ leave: 1,
15960
+ remove: 2,
15961
+ throw: 3
15962
+ });
15963
+ const XML10_ALLOWED_C0 = new Set([
15964
+ 0x09,
15965
+ 0x0A,
15966
+ 0x0D
15967
+ ]);
15968
+ function parseNCRConfig(ncr) {
15969
+ if (!ncr) return {
15970
+ xmlVersion: 1.0,
15971
+ onLevel: NCR_LEVEL.allow,
15972
+ nullLevel: NCR_LEVEL.remove
15973
+ };
15974
+ const xmlVersion = 1.1 === ncr.xmlVersion ? 1.1 : 1.0;
15975
+ const onLevel = NCR_LEVEL[ncr.onNCR] ?? NCR_LEVEL.allow;
15976
+ const nullLevel = NCR_LEVEL[ncr.nullNCR] ?? NCR_LEVEL.remove;
15977
+ const clampedNull = Math.max(nullLevel, NCR_LEVEL.remove);
15978
+ return {
15979
+ xmlVersion,
15980
+ onLevel,
15981
+ nullLevel: clampedNull
15982
+ };
15983
+ }
15984
+ class EntityDecoder {
15985
+ constructor(options = {}){
15986
+ this._limit = options.limit || {};
15987
+ this._maxTotalExpansions = this._limit.maxTotalExpansions || 0;
15988
+ this._maxExpandedLength = this._limit.maxExpandedLength || 0;
15989
+ this._postCheck = 'function' == typeof options.postCheck ? options.postCheck : (r)=>r;
15990
+ this._limitTiers = parseLimitTiers(this._limit.applyLimitsTo ?? LIMIT_TIER_EXTERNAL);
15991
+ this._numericAllowed = options.numericAllowed ?? true;
15992
+ this._baseMap = mergeEntityMaps(XML, options.namedEntities || null);
15993
+ this._externalMap = Object.create(null);
15994
+ this._inputMap = Object.create(null);
15995
+ this._totalExpansions = 0;
15996
+ this._expandedLength = 0;
15997
+ this._removeSet = new Set(options.remove && Array.isArray(options.remove) ? options.remove : []);
15998
+ this._leaveSet = new Set(options.leave && Array.isArray(options.leave) ? options.leave : []);
15999
+ const ncrCfg = parseNCRConfig(options.ncr);
16000
+ this._ncrXmlVersion = ncrCfg.xmlVersion;
16001
+ this._ncrOnLevel = ncrCfg.onLevel;
16002
+ this._ncrNullLevel = ncrCfg.nullLevel;
16003
+ }
16004
+ setExternalEntities(map) {
16005
+ if (map) for (const key of Object.keys(map))EntityDecoder_validateEntityName(key);
16006
+ this._externalMap = mergeEntityMaps(map);
16007
+ }
16008
+ addExternalEntity(key, value) {
16009
+ EntityDecoder_validateEntityName(key);
16010
+ if ('string' == typeof value && -1 === value.indexOf('&')) this._externalMap[key] = value;
16011
+ }
16012
+ addInputEntities(map) {
16013
+ this._totalExpansions = 0;
16014
+ this._expandedLength = 0;
16015
+ this._inputMap = mergeEntityMaps(map);
16016
+ }
16017
+ reset() {
16018
+ this._inputMap = Object.create(null);
16019
+ this._totalExpansions = 0;
16020
+ this._expandedLength = 0;
16021
+ return this;
16022
+ }
16023
+ setXmlVersion(version) {
16024
+ this._ncrXmlVersion = 1.1 === version ? 1.1 : 1.0;
16025
+ }
16026
+ decode(str) {
16027
+ if ('string' != typeof str || 0 === str.length) return str;
16028
+ const original = str;
16029
+ const chunks = [];
16030
+ const len = str.length;
16031
+ let last = 0;
16032
+ let i = 0;
16033
+ const limitExpansions = this._maxTotalExpansions > 0;
16034
+ const limitLength = this._maxExpandedLength > 0;
16035
+ const checkLimits = limitExpansions || limitLength;
16036
+ while(i < len){
16037
+ if (38 !== str.charCodeAt(i)) {
16038
+ i++;
16039
+ continue;
16040
+ }
16041
+ let j = i + 1;
16042
+ while(j < len && 59 !== str.charCodeAt(j) && j - i <= 32)j++;
16043
+ if (j >= len || 59 !== str.charCodeAt(j)) {
16044
+ i++;
16045
+ continue;
16046
+ }
16047
+ const token = str.slice(i + 1, j);
16048
+ if (0 === token.length) {
16049
+ i++;
16050
+ continue;
16051
+ }
16052
+ let replacement;
16053
+ let tier;
16054
+ if (this._removeSet.has(token)) {
16055
+ replacement = '';
16056
+ if (void 0 === tier) tier = LIMIT_TIER_EXTERNAL;
16057
+ } else if (this._leaveSet.has(token)) {
16058
+ i++;
16059
+ continue;
16060
+ } else if (35 === token.charCodeAt(0)) {
16061
+ const ncrResult = this._resolveNCR(token);
16062
+ if (void 0 === ncrResult) {
16063
+ i++;
16064
+ continue;
16065
+ }
16066
+ replacement = ncrResult;
16067
+ tier = LIMIT_TIER_BASE;
16068
+ } else {
16069
+ const resolved = this._resolveName(token);
16070
+ replacement = resolved?.value;
16071
+ tier = resolved?.tier;
16072
+ }
16073
+ if (void 0 === replacement) {
16074
+ i++;
16075
+ continue;
16076
+ }
16077
+ if (i > last) chunks.push(str.slice(last, i));
16078
+ chunks.push(replacement);
16079
+ last = j + 1;
16080
+ i = last;
16081
+ if (checkLimits && this._tierCounts(tier)) {
16082
+ if (limitExpansions) {
16083
+ this._totalExpansions++;
16084
+ if (this._totalExpansions > this._maxTotalExpansions) throw new Error(`[EntityReplacer] Entity expansion count limit exceeded: ${this._totalExpansions} > ${this._maxTotalExpansions}`);
16085
+ }
16086
+ if (limitLength) {
16087
+ const delta = replacement.length - (token.length + 2);
16088
+ if (delta > 0) {
16089
+ this._expandedLength += delta;
16090
+ if (this._expandedLength > this._maxExpandedLength) throw new Error(`[EntityReplacer] Expanded content length limit exceeded: ${this._expandedLength} > ${this._maxExpandedLength}`);
16091
+ }
16092
+ }
16093
+ }
16094
+ }
16095
+ if (last < len) chunks.push(str.slice(last));
16096
+ const result = 0 === chunks.length ? str : chunks.join('');
16097
+ return this._postCheck(result, original);
16098
+ }
16099
+ _tierCounts(tier) {
16100
+ if (this._limitTiers.has(LIMIT_TIER_ALL)) return true;
16101
+ return this._limitTiers.has(tier);
16102
+ }
16103
+ _resolveName(name) {
16104
+ if (name in this._inputMap) return {
16105
+ value: this._inputMap[name],
16106
+ tier: LIMIT_TIER_EXTERNAL
16107
+ };
16108
+ if (name in this._externalMap) return {
16109
+ value: this._externalMap[name],
16110
+ tier: LIMIT_TIER_EXTERNAL
16111
+ };
16112
+ if (name in this._baseMap) return {
16113
+ value: this._baseMap[name],
16114
+ tier: LIMIT_TIER_BASE
16115
+ };
16116
+ }
16117
+ _classifyNCR(cp) {
16118
+ if (0 === cp) return this._ncrNullLevel;
16119
+ if (cp >= 0xD800 && cp <= 0xDFFF) return NCR_LEVEL.remove;
16120
+ if (1.0 === this._ncrXmlVersion) {
16121
+ if (cp >= 0x01 && cp <= 0x1F && !XML10_ALLOWED_C0.has(cp)) return NCR_LEVEL.remove;
16122
+ }
16123
+ return -1;
16124
+ }
16125
+ _applyNCRAction(action, token, cp) {
16126
+ switch(action){
16127
+ case NCR_LEVEL.allow:
16128
+ return String.fromCodePoint(cp);
16129
+ case NCR_LEVEL.remove:
16130
+ return '';
16131
+ case NCR_LEVEL.leave:
16132
+ return;
16133
+ case NCR_LEVEL.throw:
16134
+ throw new Error(`[EntityDecoder] Prohibited numeric character reference &${token}; (U+${cp.toString(16).toUpperCase().padStart(4, '0')})`);
16135
+ default:
16136
+ return String.fromCodePoint(cp);
16137
+ }
16138
+ }
16139
+ _resolveNCR(token) {
16140
+ const second = token.charCodeAt(1);
16141
+ let cp;
16142
+ cp = 120 === second || 88 === second ? parseInt(token.slice(2), 16) : parseInt(token.slice(1), 10);
16143
+ if (Number.isNaN(cp) || cp < 0 || cp > 0x10FFFF) return;
16144
+ const minimum = this._classifyNCR(cp);
16145
+ if (!this._numericAllowed && minimum < NCR_LEVEL.remove) return;
16146
+ const effective = -1 === minimum ? this._ncrOnLevel : Math.max(this._ncrOnLevel, minimum);
16147
+ return this._applyNCRAction(effective, token, cp);
16148
+ }
16149
+ }
14824
16150
  function extractRawAttributes(prefixedAttrs, options) {
14825
16151
  if (!prefixedAttrs) return {};
14826
16152
  const attrs = options.attributesGroupName ? prefixedAttrs[options.attributesGroupName] : prefixedAttrs;
@@ -14841,76 +16167,10 @@
14841
16167
  }
14842
16168
  }
14843
16169
  class OrderedObjParser {
14844
- constructor(options){
16170
+ constructor(options, externalEntities){
14845
16171
  this.options = options;
14846
16172
  this.currentNode = null;
14847
16173
  this.tagsNodeStack = [];
14848
- this.docTypeEntities = {};
14849
- this.lastEntities = {
14850
- apos: {
14851
- regex: /&(apos|#39|#x27);/g,
14852
- val: "'"
14853
- },
14854
- gt: {
14855
- regex: /&(gt|#62|#x3E);/g,
14856
- val: ">"
14857
- },
14858
- lt: {
14859
- regex: /&(lt|#60|#x3C);/g,
14860
- val: "<"
14861
- },
14862
- quot: {
14863
- regex: /&(quot|#34|#x22);/g,
14864
- val: "\""
14865
- }
14866
- };
14867
- this.ampEntity = {
14868
- regex: /&(amp|#38|#x26);/g,
14869
- val: "&"
14870
- };
14871
- this.htmlEntities = {
14872
- space: {
14873
- regex: /&(nbsp|#160);/g,
14874
- val: " "
14875
- },
14876
- cent: {
14877
- regex: /&(cent|#162);/g,
14878
- val: "¢"
14879
- },
14880
- pound: {
14881
- regex: /&(pound|#163);/g,
14882
- val: "£"
14883
- },
14884
- yen: {
14885
- regex: /&(yen|#165);/g,
14886
- val: "¥"
14887
- },
14888
- euro: {
14889
- regex: /&(euro|#8364);/g,
14890
- val: "€"
14891
- },
14892
- copyright: {
14893
- regex: /&(copy|#169);/g,
14894
- val: "©"
14895
- },
14896
- reg: {
14897
- regex: /&(reg|#174);/g,
14898
- val: "®"
14899
- },
14900
- inr: {
14901
- regex: /&(inr|#8377);/g,
14902
- val: "₹"
14903
- },
14904
- num_dec: {
14905
- regex: /&#([0-9]{1,7});/g,
14906
- val: (_, str)=>fromCodePoint(str, 10, "&#")
14907
- },
14908
- num_hex: {
14909
- regex: /&#x([0-9a-fA-F]{1,6});/g,
14910
- val: (_, str)=>fromCodePoint(str, 16, "&#x")
14911
- }
14912
- };
14913
- this.addExternalEntities = addExternalEntities;
14914
16174
  this.parseXml = parseXml;
14915
16175
  this.parseTextData = parseTextData;
14916
16176
  this.resolveNameSpace = resolveNameSpace;
@@ -14923,6 +16183,29 @@
14923
16183
  this.ignoreAttributesFn = getIgnoreAttributesFn(this.options.ignoreAttributes);
14924
16184
  this.entityExpansionCount = 0;
14925
16185
  this.currentExpandedLength = 0;
16186
+ let namedEntities = {
16187
+ ...XML
16188
+ };
16189
+ if (this.options.entityDecoder) this.entityDecoder = this.options.entityDecoder;
16190
+ else {
16191
+ if ("object" == typeof this.options.htmlEntities) namedEntities = this.options.htmlEntities;
16192
+ else if (true === this.options.htmlEntities) namedEntities = {
16193
+ ...COMMON_HTML,
16194
+ ...CURRENCY
16195
+ };
16196
+ this.entityDecoder = new EntityDecoder({
16197
+ namedEntities: {
16198
+ ...namedEntities,
16199
+ ...externalEntities
16200
+ },
16201
+ numericAllowed: this.options.htmlEntities,
16202
+ limit: {
16203
+ maxTotalExpansions: this.options.processEntities.maxTotalExpansions,
16204
+ maxExpandedLength: this.options.processEntities.maxExpandedLength,
16205
+ applyLimitsTo: this.options.processEntities.appliesTo
16206
+ }
16207
+ });
16208
+ }
14926
16209
  this.matcher = new Matcher();
14927
16210
  this.readonlyMatcher = this.matcher.readOnly();
14928
16211
  this.isCurrentNodeStopNode = false;
@@ -14938,17 +16221,6 @@
14938
16221
  }
14939
16222
  }
14940
16223
  }
14941
- function addExternalEntities(externalEntities) {
14942
- const entKeys = Object.keys(externalEntities);
14943
- for(let i = 0; i < entKeys.length; i++){
14944
- const ent = entKeys[i];
14945
- const escaped = ent.replace(/[.\-+*:]/g, '\\.');
14946
- this.lastEntities[ent] = {
14947
- regex: new RegExp("&" + escaped + ";", "g"),
14948
- val: externalEntities[ent]
14949
- };
14950
- }
14951
- }
14952
16224
  function parseTextData(val, tagName, jPath, dontTrim, hasAttributes, isLeafNode, escapeEntities) {
14953
16225
  const options = this.options;
14954
16226
  if (void 0 !== val) {
@@ -14978,9 +16250,9 @@
14978
16250
  return tagname;
14979
16251
  }
14980
16252
  const attrsRegx = new RegExp('([^\\s=]+)\\s*(=\\s*([\'"])([\\s\\S]*?)\\3)?', 'gm');
14981
- function buildAttributesMap(attrStr, jPath, tagName) {
16253
+ function buildAttributesMap(attrStr, jPath, tagName, force = false) {
14982
16254
  const options = this.options;
14983
- if (true !== options.ignoreAttributes && 'string' == typeof attrStr) {
16255
+ if (true === force || true !== options.ignoreAttributes && 'string' == typeof attrStr) {
14984
16256
  const matches = getAllMatches(attrStr, attrsRegx);
14985
16257
  const len = matches.length;
14986
16258
  const attrs = {};
@@ -15023,7 +16295,7 @@
15023
16295
  }
15024
16296
  }
15025
16297
  if (!hasAttrs) return;
15026
- if (options.attributesGroupName) {
16298
+ if (options.attributesGroupName && !options.preserveOrder) {
15027
16299
  const attrCollection = {};
15028
16300
  attrCollection[options.attributesGroupName] = attrs;
15029
16301
  return attrCollection;
@@ -15037,11 +16309,9 @@
15037
16309
  let currentNode = xmlObj;
15038
16310
  let textData = "";
15039
16311
  this.matcher.reset();
16312
+ this.entityDecoder.reset();
15040
16313
  this.entityExpansionCount = 0;
15041
16314
  this.currentExpandedLength = 0;
15042
- this.docTypeEntitiesKeys = [];
15043
- this.lastEntitiesKeys = Object.keys(this.lastEntities);
15044
- this.htmlEntitiesKeys = this.options.htmlEntities ? Object.keys(this.htmlEntities) : [];
15045
16315
  const options = this.options;
15046
16316
  const docTypeReader = new DocTypeReader(options.processEntities);
15047
16317
  const xmlLen = xmlData.length;
@@ -15073,11 +16343,16 @@
15073
16343
  let tagData = readTagExp(xmlData, i, false, "?>");
15074
16344
  if (!tagData) throw new Error("Pi Tag is not closed.");
15075
16345
  textData = this.saveTextToParentTag(textData, currentNode, this.readonlyMatcher);
16346
+ const attsMap = this.buildAttributesMap(tagData.tagExp, this.matcher, tagData.tagName, true);
16347
+ if (attsMap) {
16348
+ const ver = attsMap[this.options.attributeNamePrefix + "version"];
16349
+ this.entityDecoder.setXmlVersion(Number(ver) || 1.0);
16350
+ }
15076
16351
  if (options.ignoreDeclaration && "?xml" === tagData.tagName || options.ignorePiTags) ;
15077
16352
  else {
15078
16353
  const childNode = new XmlNode(tagData.tagName);
15079
16354
  childNode.add(options.textNodeName, "");
15080
- if (tagData.tagName !== tagData.tagExp && tagData.attrExpPresent) childNode[":@"] = this.buildAttributesMap(tagData.tagExp, this.matcher, tagData.tagName);
16355
+ if (tagData.tagName !== tagData.tagExp && tagData.attrExpPresent && true !== options.ignoreAttributes) childNode[":@"] = attsMap;
15081
16356
  this.addChild(currentNode, childNode, this.readonlyMatcher, i);
15082
16357
  }
15083
16358
  i = tagData.closeIndex + 1;
@@ -15095,8 +16370,7 @@
15095
16370
  i = endIndex;
15096
16371
  } else if (33 === c1 && 68 === xmlData.charCodeAt(i + 2)) {
15097
16372
  const result = docTypeReader.readDocType(xmlData, i);
15098
- this.docTypeEntities = result.entities;
15099
- this.docTypeEntitiesKeys = Object.keys(this.docTypeEntities) || [];
16373
+ this.entityDecoder.addInputEntities(result.entities);
15100
16374
  i = result.i;
15101
16375
  } else if (33 === c1 && 91 === xmlData.charCodeAt(i + 2)) {
15102
16376
  const closeIndex = findClosingIndex(xmlData, "]]>", i, "CDATA is not closed.") - 2;
@@ -15221,42 +16495,7 @@
15221
16495
  const jPathOrMatcher = this.options.jPath ? jPath.toString() : jPath;
15222
16496
  if (!entityConfig.tagFilter(tagName, jPathOrMatcher)) return val;
15223
16497
  }
15224
- for (const entityName of this.docTypeEntitiesKeys){
15225
- const entity = this.docTypeEntities[entityName];
15226
- const matches = val.match(entity.regx);
15227
- if (matches) {
15228
- this.entityExpansionCount += matches.length;
15229
- if (entityConfig.maxTotalExpansions && this.entityExpansionCount > entityConfig.maxTotalExpansions) throw new Error(`Entity expansion limit exceeded: ${this.entityExpansionCount} > ${entityConfig.maxTotalExpansions}`);
15230
- const lengthBefore = val.length;
15231
- val = val.replace(entity.regx, entity.val);
15232
- if (entityConfig.maxExpandedLength) {
15233
- this.currentExpandedLength += val.length - lengthBefore;
15234
- if (this.currentExpandedLength > entityConfig.maxExpandedLength) throw new Error(`Total expanded content size exceeded: ${this.currentExpandedLength} > ${entityConfig.maxExpandedLength}`);
15235
- }
15236
- }
15237
- }
15238
- if (-1 === val.indexOf('&')) return val;
15239
- for (const entityName of this.lastEntitiesKeys){
15240
- const entity = this.lastEntities[entityName];
15241
- const matches = val.match(entity.regex);
15242
- if (matches) {
15243
- this.entityExpansionCount += matches.length;
15244
- if (entityConfig.maxTotalExpansions && this.entityExpansionCount > entityConfig.maxTotalExpansions) throw new Error(`Entity expansion limit exceeded: ${this.entityExpansionCount} > ${entityConfig.maxTotalExpansions}`);
15245
- }
15246
- val = val.replace(entity.regex, entity.val);
15247
- }
15248
- if (-1 === val.indexOf('&')) return val;
15249
- for (const entityName of this.htmlEntitiesKeys){
15250
- const entity = this.htmlEntities[entityName];
15251
- const matches = val.match(entity.regex);
15252
- if (matches) {
15253
- this.entityExpansionCount += matches.length;
15254
- if (entityConfig.maxTotalExpansions && this.entityExpansionCount > entityConfig.maxTotalExpansions) throw new Error(`Entity expansion limit exceeded: ${this.entityExpansionCount} > ${entityConfig.maxTotalExpansions}`);
15255
- }
15256
- val = val.replace(entity.regex, entity.val);
15257
- }
15258
- val = val.replace(this.ampEntity.regex, this.ampEntity.val);
15259
- return val;
16498
+ return this.entityDecoder.decode(val);
15260
16499
  }
15261
16500
  function saveTextToParentTag(textData, parentNode, matcher, isLeafNode) {
15262
16501
  if (textData) {
@@ -15273,29 +16512,35 @@
15273
16512
  }
15274
16513
  function tagExpWithClosingIndex(xmlData, i, closingChar = ">") {
15275
16514
  let attrBoundary = 0;
15276
- const chars = [];
15277
16515
  const len = xmlData.length;
15278
16516
  const closeCode0 = closingChar.charCodeAt(0);
15279
16517
  const closeCode1 = closingChar.length > 1 ? closingChar.charCodeAt(1) : -1;
16518
+ let result = '';
16519
+ let segmentStart = i;
15280
16520
  for(let index = i; index < len; index++){
15281
16521
  const code = xmlData.charCodeAt(index);
15282
16522
  if (attrBoundary) {
15283
16523
  if (code === attrBoundary) attrBoundary = 0;
15284
16524
  } else if (34 === code || 39 === code) attrBoundary = code;
15285
- else if (code === closeCode0) {
15286
- if (-1 === closeCode1) return {
15287
- data: String.fromCharCode(...chars),
15288
- index
15289
- };
15290
- else if (xmlData.charCodeAt(index + 1) === closeCode1) return {
15291
- data: String.fromCharCode(...chars),
16525
+ else if (code === closeCode0) if (-1 !== closeCode1) {
16526
+ if (xmlData.charCodeAt(index + 1) === closeCode1) {
16527
+ result += xmlData.substring(segmentStart, index);
16528
+ return {
16529
+ data: result,
16530
+ index
16531
+ };
16532
+ }
16533
+ } else {
16534
+ result += xmlData.substring(segmentStart, index);
16535
+ return {
16536
+ data: result,
15292
16537
  index
15293
16538
  };
15294
- } else if (9 === code) {
15295
- chars.push(32);
15296
- continue;
15297
16539
  }
15298
- chars.push(code);
16540
+ else if (9 === code && !attrBoundary) {
16541
+ result += xmlData.substring(segmentStart, index) + ' ';
16542
+ segmentStart = index + 1;
16543
+ }
15299
16544
  }
15300
16545
  }
15301
16546
  function findClosingIndex(xmlData, str, i, errMsg) {
@@ -15363,7 +16608,7 @@
15363
16608
  const closeIndex = findClosingIndex(xmlData, "]]>", i, "StopNode is not closed.") - 2;
15364
16609
  i = closeIndex;
15365
16610
  } else {
15366
- const tagData = readTagExp(xmlData, i, '>');
16611
+ const tagData = readTagExp(xmlData, i, false);
15367
16612
  if (tagData) {
15368
16613
  const openTagName = tagData && tagData.tagName;
15369
16614
  if (openTagName === tagName && "/" !== tagData.tagExp[tagData.tagExp.length - 1]) openTagCount++;
@@ -15382,11 +16627,6 @@
15382
16627
  if (isExist(val)) return val;
15383
16628
  return '';
15384
16629
  }
15385
- function fromCodePoint(str, base, prefix) {
15386
- const codePoint = Number.parseInt(str, base);
15387
- if (codePoint >= 0 && codePoint <= 0x10FFFF) return String.fromCodePoint(codePoint);
15388
- return prefix + str + ";";
15389
- }
15390
16630
  function transformTagName(fn, tagName, tagExp, options) {
15391
16631
  if (fn) {
15392
16632
  const newTagName = fn(tagName);
@@ -15434,6 +16674,7 @@
15434
16674
  else if (tagObj[property]) {
15435
16675
  let val = node2json_compress(tagObj[property], options, matcher, readonlyMatcher);
15436
16676
  const isLeaf = isLeafTag(val, options);
16677
+ if (0 === Object.keys(val).length && options.alwaysCreateTextNode) val[options.textNodeName] = "";
15437
16678
  if (tagObj[":@"]) assignAttributes(val, tagObj[":@"], readonlyMatcher, options);
15438
16679
  else if (1 !== Object.keys(val).length || void 0 === val[options.textNodeName] || options.alwaysCreateTextNode) {
15439
16680
  if (0 === Object.keys(val).length) if (options.alwaysCreateTextNode) val[options.textNodeName] = "";
@@ -15725,8 +16966,7 @@
15725
16966
  const result = validate(xmlData, validationOption);
15726
16967
  if (true !== result) throw Error(`${result.err.msg}:${result.err.line}:${result.err.col}`);
15727
16968
  }
15728
- const orderedObjParser = new OrderedObjParser(this.options);
15729
- orderedObjParser.addExternalEntities(this.externalEntities);
16969
+ const orderedObjParser = new OrderedObjParser(this.options, this.externalEntities);
15730
16970
  const orderedResult = orderedObjParser.parseXml(xmlData);
15731
16971
  if (this.options.preserveOrder || void 0 === orderedResult) return orderedResult;
15732
16972
  return prettify(orderedResult, this.options, orderedObjParser.matcher, orderedObjParser.readonlyMatcher);
@@ -15741,20 +16981,73 @@
15741
16981
  return XmlNode.getMetaDataSymbol();
15742
16982
  }
15743
16983
  }
16984
+ function safeComment(val) {
16985
+ return String(val).replace(/--/g, '- -').replace(/--/g, '- -').replace(/-$/, '- ');
16986
+ }
16987
+ function safeCdata(val) {
16988
+ return String(val).replace(/\]\]>/g, ']]]]><![CDATA[>');
16989
+ }
16990
+ function escapeAttribute(val) {
16991
+ return String(val).replace(/"/g, '&quot;').replace(/'/g, '&apos;');
16992
+ }
16993
+ const nameStartChar10 = ":A-Za-z_À-ÖØ-öø-˿Ͱ-ͽͿ-҆҈-῿‌-‍⁰-↏Ⰰ-⿯、-퟿豈-﷏ﷰ-�";
16994
+ const nameChar10 = nameStartChar10 + "\\-\\.\\d·̀-ͯ‿-⁀";
16995
+ const nameStartChar11 = ":A-Za-z_À-˿Ͱ-ͽͿ-҆҈-῿‌-‍⁰-↏Ⰰ-⿯、-퟿豈-﷏ﷰ-�𐀀-󯿿";
16996
+ const nameChar11 = nameStartChar11 + "\\-\\.\\d·̀-ͯ҇‿-⁀";
16997
+ const buildRegexes = (startChar, char, flags = '')=>{
16998
+ const ncStart = startChar.replace(':', '');
16999
+ const ncChar = char.replace(':', '');
17000
+ const ncNamePat = `[${ncStart}][${ncChar}]*`;
17001
+ return {
17002
+ name: new RegExp(`^[${startChar}][${char}]*$`, flags),
17003
+ ncName: new RegExp(`^${ncNamePat}$`, flags),
17004
+ qName: new RegExp(`^${ncNamePat}(?::${ncNamePat})?$`, flags),
17005
+ nmToken: new RegExp(`^[${char}]+$`, flags),
17006
+ nmTokens: new RegExp(`^[${char}]+(?:\\s+[${char}]+)*$`, flags)
17007
+ };
17008
+ };
17009
+ const regexes10 = buildRegexes(nameStartChar10, nameChar10);
17010
+ const regexes11 = buildRegexes(nameStartChar11, nameChar11, 'u');
17011
+ const getRegexes = (xmlVersion = '1.0')=>'1.1' === xmlVersion ? regexes11 : regexes10;
17012
+ const qName = (str, { xmlVersion = '1.0' } = {})=>getRegexes(xmlVersion).qName.test(str);
15744
17013
  const EOL = "\n";
17014
+ function detectXmlVersionFromArray(jArray, options) {
17015
+ if (!Array.isArray(jArray) || 0 === jArray.length) return '1.0';
17016
+ const first = jArray[0];
17017
+ const firstKey = orderedJs2Xml_propName(first);
17018
+ if ('?xml' === firstKey) {
17019
+ const attrs = first[':@'];
17020
+ if (attrs) {
17021
+ const versionKey = options.attributeNamePrefix + 'version';
17022
+ if (attrs[versionKey]) return attrs[versionKey];
17023
+ }
17024
+ }
17025
+ return '1.0';
17026
+ }
17027
+ function resolveTagName(name, isAttribute, options, matcher, xmlVersion) {
17028
+ if (!options.sanitizeName) return name;
17029
+ if (qName(name, {
17030
+ xmlVersion
17031
+ })) return name;
17032
+ return options.sanitizeName(name, {
17033
+ isAttribute,
17034
+ matcher: matcher.readOnly()
17035
+ });
17036
+ }
15745
17037
  function toXml(jArray, options) {
15746
17038
  let indentation = "";
15747
- if (options.format && options.indentBy.length > 0) indentation = EOL;
17039
+ if (options.format) indentation = EOL;
15748
17040
  const stopNodeExpressions = [];
15749
17041
  if (options.stopNodes && Array.isArray(options.stopNodes)) for(let i = 0; i < options.stopNodes.length; i++){
15750
17042
  const node = options.stopNodes[i];
15751
17043
  if ('string' == typeof node) stopNodeExpressions.push(new Expression(node));
15752
17044
  else if (node instanceof Expression) stopNodeExpressions.push(node);
15753
17045
  }
17046
+ const xmlVersion = detectXmlVersionFromArray(jArray, options);
15754
17047
  const matcher = new Matcher();
15755
- return arrToStr(jArray, options, indentation, matcher, stopNodeExpressions);
17048
+ return arrToStr(jArray, options, indentation, matcher, stopNodeExpressions, xmlVersion);
15756
17049
  }
15757
- function arrToStr(arr, options, indentation, matcher, stopNodeExpressions) {
17050
+ function arrToStr(arr, options, indentation, matcher, stopNodeExpressions, xmlVersion) {
15758
17051
  let xmlStr = "";
15759
17052
  let isPreviousElementTag = false;
15760
17053
  if (options.maxNestedTags && matcher.getDepth() > options.maxNestedTags) throw new Error("Maximum nested tags exceeded");
@@ -15768,13 +17061,15 @@
15768
17061
  }
15769
17062
  for(let i = 0; i < arr.length; i++){
15770
17063
  const tagObj = arr[i];
15771
- const tagName = orderedJs2Xml_propName(tagObj);
15772
- if (void 0 === tagName) continue;
17064
+ const rawTagName = orderedJs2Xml_propName(tagObj);
17065
+ if (void 0 === rawTagName) continue;
17066
+ const isSpecialName = rawTagName === options.textNodeName || rawTagName === options.cdataPropName || rawTagName === options.commentPropName || '?' === rawTagName[0];
17067
+ const tagName = isSpecialName ? rawTagName : resolveTagName(rawTagName, false, options, matcher, xmlVersion);
15773
17068
  const attrValues = extractAttributeValues(tagObj[":@"], options);
15774
17069
  matcher.push(tagName, attrValues);
15775
17070
  const isStopNode = checkStopNode(matcher, stopNodeExpressions);
15776
17071
  if (tagName === options.textNodeName) {
15777
- let tagText = tagObj[tagName];
17072
+ let tagText = tagObj[rawTagName];
15778
17073
  if (!isStopNode) {
15779
17074
  tagText = options.tagValueProcessor(tagName, tagText);
15780
17075
  tagText = orderedJs2Xml_replaceEntitiesValue(tagText, options);
@@ -15787,32 +17082,34 @@
15787
17082
  }
15788
17083
  if (tagName === options.cdataPropName) {
15789
17084
  if (isPreviousElementTag) xmlStr += indentation;
15790
- xmlStr += `<![CDATA[${tagObj[tagName][0][options.textNodeName]}]]>`;
17085
+ const val = tagObj[rawTagName][0][options.textNodeName];
17086
+ const safeVal = safeCdata(val);
17087
+ xmlStr += `<![CDATA[${safeVal}]]>`;
15791
17088
  isPreviousElementTag = false;
15792
17089
  matcher.pop();
15793
17090
  continue;
15794
17091
  }
15795
17092
  if (tagName === options.commentPropName) {
15796
- xmlStr += indentation + `<!--${tagObj[tagName][0][options.textNodeName]}-->`;
17093
+ const val = tagObj[rawTagName][0][options.textNodeName];
17094
+ const safeVal = safeComment(val);
17095
+ xmlStr += indentation + `<!--${safeVal}-->`;
15797
17096
  isPreviousElementTag = true;
15798
17097
  matcher.pop();
15799
17098
  continue;
15800
17099
  } else if ("?" === tagName[0]) {
15801
- const attStr = attr_to_str(tagObj[":@"], options, isStopNode);
17100
+ const attStr = attr_to_str(tagObj[":@"], options, isStopNode, matcher, xmlVersion);
15802
17101
  const tempInd = "?xml" === tagName ? "" : indentation;
15803
- let piTextNodeName = tagObj[tagName][0][options.textNodeName];
15804
- piTextNodeName = 0 !== piTextNodeName.length ? " " + piTextNodeName : "";
15805
- xmlStr += tempInd + `<${tagName}${piTextNodeName}${attStr}?>`;
17102
+ xmlStr += tempInd + `<${tagName}${attStr}?>`;
15806
17103
  isPreviousElementTag = true;
15807
17104
  matcher.pop();
15808
17105
  continue;
15809
17106
  }
15810
17107
  let newIdentation = indentation;
15811
17108
  if ("" !== newIdentation) newIdentation += options.indentBy;
15812
- const attStr = attr_to_str(tagObj[":@"], options, isStopNode);
17109
+ const attStr = attr_to_str(tagObj[":@"], options, isStopNode, matcher, xmlVersion);
15813
17110
  const tagStart = indentation + `<${tagName}${attStr}`;
15814
17111
  let tagValue;
15815
- tagValue = isStopNode ? getRawContent(tagObj[tagName], options) : arrToStr(tagObj[tagName], options, newIdentation, matcher, stopNodeExpressions);
17112
+ tagValue = isStopNode ? getRawContent(tagObj[rawTagName], options) : arrToStr(tagObj[rawTagName], options, newIdentation, matcher, stopNodeExpressions, xmlVersion);
15816
17113
  if (-1 !== options.unpairedTags.indexOf(tagName)) if (options.suppressUnpairedNode) xmlStr += tagStart + ">";
15817
17114
  else xmlStr += tagStart + "/>";
15818
17115
  else if ((!tagValue || 0 === tagValue.length) && options.suppressEmptyNode) xmlStr += tagStart + "/>";
@@ -15835,7 +17132,7 @@
15835
17132
  for(let attr in attrMap){
15836
17133
  if (!Object.prototype.hasOwnProperty.call(attrMap, attr)) continue;
15837
17134
  const cleanAttrName = attr.startsWith(options.attributeNamePrefix) ? attr.substr(options.attributeNamePrefix.length) : attr;
15838
- attrValues[cleanAttrName] = attrMap[attr];
17135
+ attrValues[cleanAttrName] = escapeAttribute(attrMap[attr]);
15839
17136
  hasAttrs = true;
15840
17137
  }
15841
17138
  return hasAttrs ? attrValues : null;
@@ -15868,7 +17165,7 @@
15868
17165
  if (!Object.prototype.hasOwnProperty.call(attrMap, attr)) continue;
15869
17166
  let attrVal = attrMap[attr];
15870
17167
  if (true === attrVal && options.suppressBooleanAttributes) attrStr += ` ${attr.substr(options.attributeNamePrefix.length)}`;
15871
- else attrStr += ` ${attr.substr(options.attributeNamePrefix.length)}="${attrVal}"`;
17168
+ else attrStr += ` ${attr.substr(options.attributeNamePrefix.length)}="${escapeAttribute(attrVal)}"`;
15872
17169
  }
15873
17170
  return attrStr;
15874
17171
  }
@@ -15881,18 +17178,20 @@
15881
17178
  }
15882
17179
  }
15883
17180
  }
15884
- function attr_to_str(attrMap, options, isStopNode) {
17181
+ function attr_to_str(attrMap, options, isStopNode, matcher, xmlVersion) {
15885
17182
  let attrStr = "";
15886
17183
  if (attrMap && !options.ignoreAttributes) for(let attr in attrMap){
15887
17184
  if (!Object.prototype.hasOwnProperty.call(attrMap, attr)) continue;
17185
+ const cleanAttrName = attr.substr(options.attributeNamePrefix.length);
17186
+ const resolvedAttrName = isStopNode ? cleanAttrName : resolveTagName(cleanAttrName, true, options, matcher, xmlVersion);
15888
17187
  let attrVal;
15889
17188
  if (isStopNode) attrVal = attrMap[attr];
15890
17189
  else {
15891
17190
  attrVal = options.attributeValueProcessor(attr, attrMap[attr]);
15892
17191
  attrVal = orderedJs2Xml_replaceEntitiesValue(attrVal, options);
15893
17192
  }
15894
- if (true === attrVal && options.suppressBooleanAttributes) attrStr += ` ${attr.substr(options.attributeNamePrefix.length)}`;
15895
- else attrStr += ` ${attr.substr(options.attributeNamePrefix.length)}="${attrVal}"`;
17193
+ if (true === attrVal && options.suppressBooleanAttributes) attrStr += ` ${resolvedAttrName}`;
17194
+ else attrStr += ` ${resolvedAttrName}="${escapeAttribute(attrVal)}"`;
15896
17195
  }
15897
17196
  return attrStr;
15898
17197
  }
@@ -15964,7 +17263,8 @@
15964
17263
  stopNodes: [],
15965
17264
  oneListGroup: false,
15966
17265
  maxNestedTags: 100,
15967
- jPath: true
17266
+ jPath: true,
17267
+ sanitizeName: false
15968
17268
  };
15969
17269
  function Builder(options) {
15970
17270
  this.options = Object.assign({}, fxb_defaultOptions, options);
@@ -15984,7 +17284,7 @@
15984
17284
  else {
15985
17285
  this.ignoreAttributesFn = ignoreAttributes_getIgnoreAttributesFn(this.options.ignoreAttributes);
15986
17286
  this.attrPrefixLen = this.options.attributeNamePrefix.length;
15987
- this.isAttribute = isAttribute;
17287
+ this.isAttribute = fxb_isAttribute;
15988
17288
  }
15989
17289
  this.processTextOrObjNode = processTextOrObjNode;
15990
17290
  if (this.options.format) {
@@ -15999,6 +17299,28 @@
15999
17299
  this.newLine = '';
16000
17300
  }
16001
17301
  }
17302
+ function detectXmlVersionFromObj(jObj, options) {
17303
+ const decl = jObj['?xml'];
17304
+ if (decl && 'object' == typeof decl) {
17305
+ if (options.attributesGroupName && decl[options.attributesGroupName]) {
17306
+ const v = decl[options.attributesGroupName][options.attributeNamePrefix + 'version'];
17307
+ if (v) return v;
17308
+ }
17309
+ const v = decl[options.attributeNamePrefix + 'version'];
17310
+ if (v) return v;
17311
+ }
17312
+ return '1.0';
17313
+ }
17314
+ function fxb_resolveTagName(name, isAttribute, options, matcher, xmlVersion) {
17315
+ if (!options.sanitizeName) return name;
17316
+ if (qName(name, {
17317
+ xmlVersion
17318
+ })) return name;
17319
+ return options.sanitizeName(name, {
17320
+ isAttribute,
17321
+ matcher: matcher.readOnly()
17322
+ });
17323
+ }
16002
17324
  Builder.prototype.build = function(jObj) {
16003
17325
  if (this.options.preserveOrder) return toXml(jObj, this.options);
16004
17326
  {
@@ -16006,76 +17328,87 @@
16006
17328
  [this.options.arrayNodeName]: jObj
16007
17329
  };
16008
17330
  const matcher = new Matcher();
16009
- return this.j2x(jObj, 0, matcher).val;
17331
+ const xmlVersion = detectXmlVersionFromObj(jObj, this.options);
17332
+ return this.j2x(jObj, 0, matcher, xmlVersion).val;
16010
17333
  }
16011
17334
  };
16012
- Builder.prototype.j2x = function(jObj, level, matcher) {
17335
+ Builder.prototype.j2x = function(jObj, level, matcher, xmlVersion) {
16013
17336
  let attrStr = '';
16014
17337
  let val = '';
16015
17338
  if (this.options.maxNestedTags && matcher.getDepth() >= this.options.maxNestedTags) throw new Error("Maximum nested tags exceeded");
16016
17339
  const jPath = this.options.jPath ? matcher.toString() : matcher;
16017
17340
  const isCurrentStopNode = this.checkStopNode(matcher);
16018
- for(let key in jObj)if (Object.prototype.hasOwnProperty.call(jObj, key)) if (void 0 === jObj[key]) {
16019
- if (this.isAttribute(key)) val += '';
16020
- } else if (null === jObj[key]) if (this.isAttribute(key)) val += '';
16021
- else if (key === this.options.cdataPropName) val += '';
16022
- else if ('?' === key[0]) val += this.indentate(level) + '<' + key + '?' + this.tagEndChar;
16023
- else val += this.indentate(level) + '<' + key + '/' + this.tagEndChar;
16024
- else if (jObj[key] instanceof Date) val += this.buildTextValNode(jObj[key], key, '', level, matcher);
16025
- else if ('object' != typeof jObj[key]) {
16026
- const attr = this.isAttribute(key);
16027
- if (attr && !this.ignoreAttributesFn(attr, jPath)) attrStr += this.buildAttrPairStr(attr, '' + jObj[key], isCurrentStopNode);
16028
- else if (!attr) if (key === this.options.textNodeName) {
16029
- let newval = this.options.tagValueProcessor(key, '' + jObj[key]);
16030
- val += this.replaceEntitiesValue(newval);
16031
- } else {
16032
- matcher.push(key);
16033
- const isStopNode = this.checkStopNode(matcher);
16034
- matcher.pop();
16035
- if (isStopNode) {
16036
- const textValue = '' + jObj[key];
16037
- if ('' === textValue) val += this.indentate(level) + '<' + key + this.closeTag(key) + this.tagEndChar;
16038
- else val += this.indentate(level) + '<' + key + '>' + textValue + '</' + key + this.tagEndChar;
16039
- } else val += this.buildTextValNode(jObj[key], key, '', level, matcher);
16040
- }
16041
- } else if (Array.isArray(jObj[key])) {
16042
- const arrLen = jObj[key].length;
16043
- let listTagVal = "";
16044
- let listTagAttr = "";
16045
- for(let j = 0; j < arrLen; j++){
16046
- const item = jObj[key][j];
16047
- if (void 0 === item) ;
16048
- else if (null === item) if ("?" === key[0]) val += this.indentate(level) + '<' + key + '?' + this.tagEndChar;
16049
- else val += this.indentate(level) + '<' + key + '/' + this.tagEndChar;
16050
- else if ('object' == typeof item) if (this.options.oneListGroup) {
16051
- matcher.push(key);
16052
- const result = this.j2x(item, level + 1, matcher);
16053
- matcher.pop();
16054
- listTagVal += result.val;
16055
- if (this.options.attributesGroupName && item.hasOwnProperty(this.options.attributesGroupName)) listTagAttr += result.attrStr;
16056
- } else listTagVal += this.processTextOrObjNode(item, key, level, matcher);
16057
- else if (this.options.oneListGroup) {
16058
- let textValue = this.options.tagValueProcessor(key, item);
16059
- textValue = this.replaceEntitiesValue(textValue);
16060
- listTagVal += textValue;
17341
+ for(let key in jObj){
17342
+ if (!Object.prototype.hasOwnProperty.call(jObj, key)) continue;
17343
+ const isSpecialKey = key === this.options.textNodeName || key === this.options.cdataPropName || key === this.options.commentPropName || this.options.attributesGroupName && key === this.options.attributesGroupName || this.isAttribute(key) || '?' === key[0];
17344
+ const resolvedKey = isSpecialKey ? key : fxb_resolveTagName(key, false, this.options, matcher, xmlVersion);
17345
+ if (void 0 === jObj[key]) {
17346
+ if (this.isAttribute(key)) val += '';
17347
+ } else if (null === jObj[key]) if (this.isAttribute(key)) val += '';
17348
+ else if (resolvedKey === this.options.cdataPropName || resolvedKey === this.options.commentPropName) val += '';
17349
+ else if ('?' === resolvedKey[0]) val += this.indentate(level) + '<' + resolvedKey + '?' + this.tagEndChar;
17350
+ else val += this.indentate(level) + '<' + resolvedKey + '/' + this.tagEndChar;
17351
+ else if (jObj[key] instanceof Date) val += this.buildTextValNode(jObj[key], resolvedKey, '', level, matcher);
17352
+ else if ('object' != typeof jObj[key]) {
17353
+ const attr = this.isAttribute(key);
17354
+ if (attr && !this.ignoreAttributesFn(attr, jPath)) {
17355
+ const resolvedAttr = fxb_resolveTagName(attr, true, this.options, matcher, xmlVersion);
17356
+ attrStr += this.buildAttrPairStr(resolvedAttr, '' + jObj[key], isCurrentStopNode);
17357
+ } else if (!attr) if (key === this.options.textNodeName) {
17358
+ let newval = this.options.tagValueProcessor(key, '' + jObj[key]);
17359
+ val += this.replaceEntitiesValue(newval);
16061
17360
  } else {
16062
- matcher.push(key);
17361
+ matcher.push(resolvedKey);
16063
17362
  const isStopNode = this.checkStopNode(matcher);
16064
17363
  matcher.pop();
16065
17364
  if (isStopNode) {
16066
- const textValue = '' + item;
16067
- if ('' === textValue) listTagVal += this.indentate(level) + '<' + key + this.closeTag(key) + this.tagEndChar;
16068
- else listTagVal += this.indentate(level) + '<' + key + '>' + textValue + '</' + key + this.tagEndChar;
16069
- } else listTagVal += this.buildTextValNode(item, key, '', level, matcher);
16070
- }
16071
- }
16072
- if (this.options.oneListGroup) listTagVal = this.buildObjectNode(listTagVal, key, listTagAttr, level);
16073
- val += listTagVal;
16074
- } else if (this.options.attributesGroupName && key === this.options.attributesGroupName) {
16075
- const Ks = Object.keys(jObj[key]);
16076
- const L = Ks.length;
16077
- for(let j = 0; j < L; j++)attrStr += this.buildAttrPairStr(Ks[j], '' + jObj[key][Ks[j]], isCurrentStopNode);
16078
- } else val += this.processTextOrObjNode(jObj[key], key, level, matcher);
17365
+ const textValue = '' + jObj[key];
17366
+ if ('' === textValue) val += this.indentate(level) + '<' + resolvedKey + this.closeTag(resolvedKey) + this.tagEndChar;
17367
+ else val += this.indentate(level) + '<' + resolvedKey + '>' + textValue + '</' + resolvedKey + this.tagEndChar;
17368
+ } else val += this.buildTextValNode(jObj[key], resolvedKey, '', level, matcher);
17369
+ }
17370
+ } else if (Array.isArray(jObj[key])) {
17371
+ const arrLen = jObj[key].length;
17372
+ let listTagVal = "";
17373
+ let listTagAttr = "";
17374
+ for(let j = 0; j < arrLen; j++){
17375
+ const item = jObj[key][j];
17376
+ if (void 0 === item) ;
17377
+ else if (null === item) if ("?" === resolvedKey[0]) val += this.indentate(level) + '<' + resolvedKey + '?' + this.tagEndChar;
17378
+ else val += this.indentate(level) + '<' + resolvedKey + '/' + this.tagEndChar;
17379
+ else if ('object' == typeof item) if (this.options.oneListGroup) {
17380
+ matcher.push(resolvedKey);
17381
+ const result = this.j2x(item, level + 1, matcher, xmlVersion);
17382
+ matcher.pop();
17383
+ listTagVal += result.val;
17384
+ if (this.options.attributesGroupName && item.hasOwnProperty(this.options.attributesGroupName)) listTagAttr += result.attrStr;
17385
+ } else listTagVal += this.processTextOrObjNode(item, resolvedKey, level, matcher, xmlVersion);
17386
+ else if (this.options.oneListGroup) {
17387
+ let textValue = this.options.tagValueProcessor(resolvedKey, item);
17388
+ textValue = this.replaceEntitiesValue(textValue);
17389
+ listTagVal += textValue;
17390
+ } else {
17391
+ matcher.push(resolvedKey);
17392
+ const isStopNode = this.checkStopNode(matcher);
17393
+ matcher.pop();
17394
+ if (isStopNode) {
17395
+ const textValue = '' + item;
17396
+ if ('' === textValue) listTagVal += this.indentate(level) + '<' + resolvedKey + this.closeTag(resolvedKey) + this.tagEndChar;
17397
+ else listTagVal += this.indentate(level) + '<' + resolvedKey + '>' + textValue + '</' + resolvedKey + this.tagEndChar;
17398
+ } else listTagVal += this.buildTextValNode(item, resolvedKey, '', level, matcher);
17399
+ }
17400
+ }
17401
+ if (this.options.oneListGroup) listTagVal = this.buildObjectNode(listTagVal, resolvedKey, listTagAttr, level);
17402
+ val += listTagVal;
17403
+ } else if (this.options.attributesGroupName && key === this.options.attributesGroupName) {
17404
+ const Ks = Object.keys(jObj[key]);
17405
+ const L = Ks.length;
17406
+ for(let j = 0; j < L; j++){
17407
+ const resolvedAttr = fxb_resolveTagName(Ks[j], true, this.options, matcher, xmlVersion);
17408
+ attrStr += this.buildAttrPairStr(resolvedAttr, '' + jObj[key][Ks[j]], isCurrentStopNode);
17409
+ }
17410
+ } else val += this.processTextOrObjNode(jObj[key], resolvedKey, level, matcher, xmlVersion);
17411
+ }
16079
17412
  return {
16080
17413
  attrStr: attrStr,
16081
17414
  val: val
@@ -16087,9 +17420,9 @@
16087
17420
  val = this.replaceEntitiesValue(val);
16088
17421
  }
16089
17422
  if (this.options.suppressBooleanAttributes && "true" === val) return ' ' + attrName;
16090
- return ' ' + attrName + '="' + val + '"';
17423
+ return ' ' + attrName + '="' + escapeAttribute(val) + '"';
16091
17424
  };
16092
- function processTextOrObjNode(object, key, level, matcher) {
17425
+ function processTextOrObjNode(object, key, level, matcher, xmlVersion) {
16093
17426
  const attrValues = this.extractAttributes(object);
16094
17427
  matcher.push(key, attrValues);
16095
17428
  const isStopNode = this.checkStopNode(matcher);
@@ -16099,8 +17432,9 @@
16099
17432
  matcher.pop();
16100
17433
  return this.buildObjectNode(rawContent, key, attrStr, level);
16101
17434
  }
16102
- const result = this.j2x(object, level + 1, matcher);
17435
+ const result = this.j2x(object, level + 1, matcher, xmlVersion);
16103
17436
  matcher.pop();
17437
+ if ('?' === key[0]) return this.buildTextValNode('', key, result.attrStr, level, matcher);
16104
17438
  if (void 0 !== object[this.options.textNodeName] && 1 === Object.keys(object).length) return this.buildTextValNode(object[this.options.textNodeName], key, result.attrStr, level, matcher);
16105
17439
  return this.buildObjectNode(result.val, key, result.attrStr, level);
16106
17440
  }
@@ -16113,14 +17447,14 @@
16113
17447
  for(let attrKey in attrGroup){
16114
17448
  if (!Object.prototype.hasOwnProperty.call(attrGroup, attrKey)) continue;
16115
17449
  const cleanKey = attrKey.startsWith(this.options.attributeNamePrefix) ? attrKey.substring(this.options.attributeNamePrefix.length) : attrKey;
16116
- attrValues[cleanKey] = attrGroup[attrKey];
17450
+ attrValues[cleanKey] = escapeAttribute(attrGroup[attrKey]);
16117
17451
  hasAttrs = true;
16118
17452
  }
16119
17453
  } else for(let key in obj){
16120
17454
  if (!Object.prototype.hasOwnProperty.call(obj, key)) continue;
16121
17455
  const attr = this.isAttribute(key);
16122
17456
  if (attr) {
16123
- attrValues[attr] = obj[key];
17457
+ attrValues[attr] = escapeAttribute(obj[key]);
16124
17458
  hasAttrs = true;
16125
17459
  }
16126
17460
  }
@@ -16181,6 +17515,7 @@
16181
17515
  if ("" === val) if ("?" === key[0]) return this.indentate(level) + '<' + key + attrStr + '?' + this.tagEndChar;
16182
17516
  else return this.indentate(level) + '<' + key + attrStr + this.closeTag(key) + this.tagEndChar;
16183
17517
  {
17518
+ if ("?" === key[0]) return this.indentate(level) + '<' + key + attrStr + '?' + this.tagEndChar;
16184
17519
  let tagEndExp = '</' + key + this.tagEndChar;
16185
17520
  let piClosingChar = "";
16186
17521
  if ("?" === key[0]) {
@@ -16205,9 +17540,15 @@
16205
17540
  return false;
16206
17541
  };
16207
17542
  Builder.prototype.buildTextValNode = function(val, key, attrStr, level, matcher) {
16208
- if (false !== this.options.cdataPropName && key === this.options.cdataPropName) return this.indentate(level) + `<![CDATA[${val}]]>` + this.newLine;
17543
+ if (false !== this.options.cdataPropName && key === this.options.cdataPropName) {
17544
+ const safeVal = safeCdata(val);
17545
+ return this.indentate(level) + `<![CDATA[${safeVal}]]>` + this.newLine;
17546
+ }
17547
+ if (false !== this.options.commentPropName && key === this.options.commentPropName) {
17548
+ const safeVal = safeComment(val);
17549
+ return this.indentate(level) + `<!--${safeVal}-->` + this.newLine;
17550
+ }
16209
17551
  {
16210
- if (false !== this.options.commentPropName && key === this.options.commentPropName) return this.indentate(level) + `<!--${val}-->` + this.newLine;
16211
17552
  if ("?" === key[0]) return this.indentate(level) + '<' + key + attrStr + '?' + this.tagEndChar;
16212
17553
  let textValue = this.options.tagValueProcessor(key, val);
16213
17554
  textValue = this.replaceEntitiesValue(textValue);
@@ -16225,7 +17566,7 @@
16225
17566
  function indentate(level) {
16226
17567
  return this.options.indentBy.repeat(level);
16227
17568
  }
16228
- function isAttribute(name) {
17569
+ function fxb_isAttribute(name) {
16229
17570
  if (name.startsWith(this.options.attributeNamePrefix) && name !== this.options.textNodeName) return name.substr(this.attrPrefixLen);
16230
17571
  return false;
16231
17572
  }
@@ -16656,11 +17997,18 @@
16656
17997
  if (void 0 == globalThis[symbol]) {
16657
17998
  const te = new globalThis.TextEncoder();
16658
17999
  const td = new globalThis.TextDecoder();
18000
+ let tdStrict;
16659
18001
  globalThis[symbol] = {
16660
18002
  encodeUtf8 (text) {
16661
18003
  return te.encode(text);
16662
18004
  },
16663
- decodeUtf8 (bytes) {
18005
+ decodeUtf8 (bytes, strict) {
18006
+ if (strict) {
18007
+ if (void 0 === tdStrict) tdStrict = new globalThis.TextDecoder("utf-8", {
18008
+ fatal: true
18009
+ });
18010
+ return tdStrict.decode(bytes);
18011
+ }
16664
18012
  return td.decode(bytes);
16665
18013
  },
16666
18014
  checkUtf8 (text) {
@@ -16836,8 +18184,13 @@
16836
18184
  this.view = new DataView(buf.buffer, buf.byteOffset, buf.byteLength);
16837
18185
  }
16838
18186
  tag() {
16839
- let tag = this.uint32(), fieldNo = tag >>> 3, wireType = 7 & tag;
16840
- if (fieldNo <= 0 || wireType < 0 || wireType > 5) throw new Error("illegal tag: field no " + fieldNo + " wire type " + wireType);
18187
+ const start = this.pos;
18188
+ const tag = this.uint32();
18189
+ const bytesRead = this.pos - start;
18190
+ if (bytesRead > 5 || 5 == bytesRead && this.buf[this.pos - 1] > 0x0f) throw new Error("illegal tag: varint overflows uint32");
18191
+ const fieldNo = tag >>> 3;
18192
+ const wireType = 7 & tag;
18193
+ if (fieldNo <= 0 || wireType > 5) throw new Error("illegal tag: field no " + fieldNo + " wire type " + wireType);
16841
18194
  return [
16842
18195
  fieldNo,
16843
18196
  wireType
@@ -16925,8 +18278,8 @@
16925
18278
  this.assertBounds();
16926
18279
  return this.buf.subarray(start, start + len);
16927
18280
  }
16928
- string() {
16929
- return this.decodeUtf8(this.bytes());
18281
+ string(strict) {
18282
+ return this.decodeUtf8(this.bytes(), strict);
16930
18283
  }
16931
18284
  }
16932
18285
  function assertInt32(arg) {
@@ -17676,7 +19029,7 @@
17676
19029
  var _a;
17677
19030
  switch(field.fieldKind){
17678
19031
  case "scalar":
17679
- message.set(field, readScalar(reader, field.scalar));
19032
+ message.set(field, readScalar(reader, field.scalar, field.utf8Validation));
17680
19033
  break;
17681
19034
  case "enum":
17682
19035
  const val = readScalar(reader, descriptors_ScalarType.INT32);
@@ -17718,12 +19071,12 @@
17718
19071
  const [fieldNo] = reader.tag();
17719
19072
  switch(fieldNo){
17720
19073
  case 1:
17721
- key = readScalar(reader, field.mapKey);
19074
+ key = readScalar(reader, field.mapKey, field.utf8Validation);
17722
19075
  break;
17723
19076
  case 2:
17724
19077
  switch(field.mapKind){
17725
19078
  case "scalar":
17726
- val = readScalar(reader, field.scalar);
19079
+ val = readScalar(reader, field.scalar, field.utf8Validation);
17727
19080
  break;
17728
19081
  case "enum":
17729
19082
  val = reader.int32();
@@ -17755,9 +19108,9 @@
17755
19108
  if ("message" === field.listKind) return void list.add(readMessageField(reader, options, field));
17756
19109
  const scalarType = null != (_a = field.scalar) ? _a : descriptors_ScalarType.INT32;
17757
19110
  const packed = wireType == binary_encoding_WireType.LengthDelimited && scalarType != descriptors_ScalarType.STRING && scalarType != descriptors_ScalarType.BYTES;
17758
- if (!packed) return void list.add(readScalar(reader, scalarType));
19111
+ if (!packed) return void list.add(readScalar(reader, scalarType, field.utf8Validation));
17759
19112
  const e = reader.uint32() + reader.pos;
17760
- while(reader.pos < e)list.add(readScalar(reader, scalarType));
19113
+ while(reader.pos < e)list.add(readScalar(reader, scalarType, field.utf8Validation));
17761
19114
  }
17762
19115
  function readMessageField(reader, options, field, mergeMessage) {
17763
19116
  const delimited = field.delimitedEncoding;
@@ -17765,10 +19118,10 @@
17765
19118
  readMessage(message, reader, options, delimited, delimited ? field.number : reader.uint32());
17766
19119
  return message;
17767
19120
  }
17768
- function readScalar(reader, type) {
19121
+ function readScalar(reader, type, validateUtf8 = false) {
17769
19122
  switch(type){
17770
19123
  case descriptors_ScalarType.STRING:
17771
- return reader.string();
19124
+ return reader.string(validateUtf8);
17772
19125
  case descriptors_ScalarType.BOOL:
17773
19126
  return reader.bool();
17774
19127
  case descriptors_ScalarType.DOUBLE:
@@ -18316,6 +19669,7 @@
18316
19669
  }
18317
19670
  const registry_EDITION_PROTO2 = 998;
18318
19671
  const registry_EDITION_PROTO3 = 999;
19672
+ const EDITION_UNSTABLE = 9999;
18319
19673
  const TYPE_STRING = 9;
18320
19674
  const TYPE_GROUP = 10;
18321
19675
  const TYPE_MESSAGE = 11;
@@ -18331,6 +19685,8 @@
18331
19685
  const PACKED = 1;
18332
19686
  const DELIMITED = 2;
18333
19687
  const OPEN = 1;
19688
+ const VERIFY = 2;
19689
+ const maximumEdition = 1001;
18334
19690
  const featureDefaults = {
18335
19691
  998: {
18336
19692
  fieldPresence: 1,
@@ -18593,6 +19949,7 @@
18593
19949
  message: void 0,
18594
19950
  enum: void 0,
18595
19951
  presence: getFieldPresence(proto, oneof, isExtension, parentOrFile),
19952
+ utf8Validation: isUtf8Validated(proto, parentOrFile),
18596
19953
  listKind: void 0,
18597
19954
  mapKind: void 0,
18598
19955
  mapKey: void 0,
@@ -18698,6 +20055,7 @@
18698
20055
  case "proto3":
18699
20056
  return registry_EDITION_PROTO3;
18700
20057
  case "editions":
20058
+ if (proto.edition === EDITION_UNSTABLE) return maximumEdition;
18701
20059
  if (proto.edition in featureDefaults) return proto.edition;
18702
20060
  throw new Error(`${proto.name}: unsupported edition`);
18703
20061
  default:
@@ -18790,6 +20148,12 @@
18790
20148
  parent
18791
20149
  });
18792
20150
  }
20151
+ function isUtf8Validated(proto, parent) {
20152
+ return VERIFY == resolveFeature("utf8Validation", {
20153
+ proto,
20154
+ parent
20155
+ });
20156
+ }
18793
20157
  function resolveFeature(name, ref) {
18794
20158
  var _a, _b;
18795
20159
  const featureSet = null == (_a = ref.proto.options) ? void 0 : _a.features;
@@ -19612,7 +20976,8 @@
19612
20976
  number: 10,
19613
20977
  type: 8,
19614
20978
  label: 1,
19615
- defaultValue: "false"
20979
+ defaultValue: "false",
20980
+ options: {}
19616
20981
  },
19617
20982
  {
19618
20983
  name: "java_generate_equals_and_hash",
@@ -19977,6 +21342,12 @@
19977
21342
  type: 14,
19978
21343
  label: 1,
19979
21344
  typeName: ".google.protobuf.Edition"
21345
+ },
21346
+ {
21347
+ name: "removal_error",
21348
+ number: 5,
21349
+ type: 9,
21350
+ label: 1
19980
21351
  }
19981
21352
  ]
19982
21353
  }
@@ -21186,7 +22557,7 @@
21186
22557
  function timestamp_timestampMs(timestamp) {
21187
22558
  return 1000 * Number(timestamp.seconds) + Math.round(timestamp.nanos / 1000000);
21188
22559
  }
21189
- var package_namespaceObject = JSON.parse('{"UU":"@dan-uni/dan-any","rE":"1.4.4","TB":"https://github.com/ani-uni/danuni/tree/master/packages/dan-any#readme"}');
22560
+ var package_namespaceObject = JSON.parse('{"UU":"@dan-uni/dan-any","rE":"1.4.6","TB":"https://github.com/ani-uni/danuni/tree/master/packages/dan-any#readme"}');
21190
22561
  const color_pad = (s)=>s.length < 2 ? `0${s}` : s;
21191
22562
  const decimalToHex = (n)=>color_pad(n.toString(16));
21192
22563
  const isDarkColor = ({ r, g, b })=>0.299 * r + 0.587 * g + 0.114 * b < 0x30;
@@ -25102,7 +26473,11 @@
25102
26473
  }
25103
26474
  static fromBiliXML(xml, options) {
25104
26475
  const parser = new XMLParser({
25105
- ignoreAttributes: false
26476
+ ignoreAttributes: false,
26477
+ isArray: (_name, jpath, _isLeafNode, _isAttribute)=>{
26478
+ if ('i.d' === jpath) return true;
26479
+ return false;
26480
+ }
25106
26481
  });
25107
26482
  const oriData = parser.parse(xml);
25108
26483
  const dans = oriData.i.d;