index.js 64 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100
  1. /*!
  2. * @esri/arcgis-html-sanitizer - v3.0.1 - Tue Nov 15 2022 09:46:54 GMT-0800 (Pacific Standard Time)
  3. * Copyright (c) 2022 - Environmental Systems Research Institute, Inc.
  4. * Apache-2.0
  5. *
  6. * js-xss
  7. * Copyright (c) 2012-2018 Zongmin Lei(雷宗民) <leizongmin@gmail.com>
  8. * http://ucdok.com
  9. * MIT License, see https://github.com/leizongmin/js-xss/blob/master/LICENSE for details
  10. */
  11. /**
  12. * Determine if the value is a plain object.
  13. * @param {*} value The value to check.
  14. * @returns {boolean} Returns `true` if `value` is a plain object, else `false`.
  15. */
  16. var isPlainObject = function (value) {
  17. if (typeof value !== "object" || value === null) {
  18. return false;
  19. }
  20. if (Object.prototype.toString.call(value) !== "[object Object]") {
  21. return false;
  22. }
  23. var proto = Object.getPrototypeOf(value);
  24. if (proto === null) {
  25. return true;
  26. }
  27. while (Object.getPrototypeOf(proto) !== null) {
  28. proto = Object.getPrototypeOf(proto);
  29. }
  30. return Object.getPrototypeOf(value) === proto;
  31. };
  32. var lib$1 = {exports: {}};
  33. var _default$1 = {};
  34. var lib = {exports: {}};
  35. var _default = {};
  36. /**
  37. * cssfilter
  38. *
  39. * @author 老雷<leizongmin@gmail.com>
  40. */
  41. function getDefaultWhiteList$1 () {
  42. // 白名单值说明:
  43. // true: 允许该属性
  44. // Function: function (val) { } 返回true表示允许该属性,其他值均表示不允许
  45. // RegExp: regexp.test(val) 返回true表示允许该属性,其他值均表示不允许
  46. // 除上面列出的值外均表示不允许
  47. var whiteList = {};
  48. whiteList['align-content'] = false; // default: auto
  49. whiteList['align-items'] = false; // default: auto
  50. whiteList['align-self'] = false; // default: auto
  51. whiteList['alignment-adjust'] = false; // default: auto
  52. whiteList['alignment-baseline'] = false; // default: baseline
  53. whiteList['all'] = false; // default: depending on individual properties
  54. whiteList['anchor-point'] = false; // default: none
  55. whiteList['animation'] = false; // default: depending on individual properties
  56. whiteList['animation-delay'] = false; // default: 0
  57. whiteList['animation-direction'] = false; // default: normal
  58. whiteList['animation-duration'] = false; // default: 0
  59. whiteList['animation-fill-mode'] = false; // default: none
  60. whiteList['animation-iteration-count'] = false; // default: 1
  61. whiteList['animation-name'] = false; // default: none
  62. whiteList['animation-play-state'] = false; // default: running
  63. whiteList['animation-timing-function'] = false; // default: ease
  64. whiteList['azimuth'] = false; // default: center
  65. whiteList['backface-visibility'] = false; // default: visible
  66. whiteList['background'] = true; // default: depending on individual properties
  67. whiteList['background-attachment'] = true; // default: scroll
  68. whiteList['background-clip'] = true; // default: border-box
  69. whiteList['background-color'] = true; // default: transparent
  70. whiteList['background-image'] = true; // default: none
  71. whiteList['background-origin'] = true; // default: padding-box
  72. whiteList['background-position'] = true; // default: 0% 0%
  73. whiteList['background-repeat'] = true; // default: repeat
  74. whiteList['background-size'] = true; // default: auto
  75. whiteList['baseline-shift'] = false; // default: baseline
  76. whiteList['binding'] = false; // default: none
  77. whiteList['bleed'] = false; // default: 6pt
  78. whiteList['bookmark-label'] = false; // default: content()
  79. whiteList['bookmark-level'] = false; // default: none
  80. whiteList['bookmark-state'] = false; // default: open
  81. whiteList['border'] = true; // default: depending on individual properties
  82. whiteList['border-bottom'] = true; // default: depending on individual properties
  83. whiteList['border-bottom-color'] = true; // default: current color
  84. whiteList['border-bottom-left-radius'] = true; // default: 0
  85. whiteList['border-bottom-right-radius'] = true; // default: 0
  86. whiteList['border-bottom-style'] = true; // default: none
  87. whiteList['border-bottom-width'] = true; // default: medium
  88. whiteList['border-collapse'] = true; // default: separate
  89. whiteList['border-color'] = true; // default: depending on individual properties
  90. whiteList['border-image'] = true; // default: none
  91. whiteList['border-image-outset'] = true; // default: 0
  92. whiteList['border-image-repeat'] = true; // default: stretch
  93. whiteList['border-image-slice'] = true; // default: 100%
  94. whiteList['border-image-source'] = true; // default: none
  95. whiteList['border-image-width'] = true; // default: 1
  96. whiteList['border-left'] = true; // default: depending on individual properties
  97. whiteList['border-left-color'] = true; // default: current color
  98. whiteList['border-left-style'] = true; // default: none
  99. whiteList['border-left-width'] = true; // default: medium
  100. whiteList['border-radius'] = true; // default: 0
  101. whiteList['border-right'] = true; // default: depending on individual properties
  102. whiteList['border-right-color'] = true; // default: current color
  103. whiteList['border-right-style'] = true; // default: none
  104. whiteList['border-right-width'] = true; // default: medium
  105. whiteList['border-spacing'] = true; // default: 0
  106. whiteList['border-style'] = true; // default: depending on individual properties
  107. whiteList['border-top'] = true; // default: depending on individual properties
  108. whiteList['border-top-color'] = true; // default: current color
  109. whiteList['border-top-left-radius'] = true; // default: 0
  110. whiteList['border-top-right-radius'] = true; // default: 0
  111. whiteList['border-top-style'] = true; // default: none
  112. whiteList['border-top-width'] = true; // default: medium
  113. whiteList['border-width'] = true; // default: depending on individual properties
  114. whiteList['bottom'] = false; // default: auto
  115. whiteList['box-decoration-break'] = true; // default: slice
  116. whiteList['box-shadow'] = true; // default: none
  117. whiteList['box-sizing'] = true; // default: content-box
  118. whiteList['box-snap'] = true; // default: none
  119. whiteList['box-suppress'] = true; // default: show
  120. whiteList['break-after'] = true; // default: auto
  121. whiteList['break-before'] = true; // default: auto
  122. whiteList['break-inside'] = true; // default: auto
  123. whiteList['caption-side'] = false; // default: top
  124. whiteList['chains'] = false; // default: none
  125. whiteList['clear'] = true; // default: none
  126. whiteList['clip'] = false; // default: auto
  127. whiteList['clip-path'] = false; // default: none
  128. whiteList['clip-rule'] = false; // default: nonzero
  129. whiteList['color'] = true; // default: implementation dependent
  130. whiteList['color-interpolation-filters'] = true; // default: auto
  131. whiteList['column-count'] = false; // default: auto
  132. whiteList['column-fill'] = false; // default: balance
  133. whiteList['column-gap'] = false; // default: normal
  134. whiteList['column-rule'] = false; // default: depending on individual properties
  135. whiteList['column-rule-color'] = false; // default: current color
  136. whiteList['column-rule-style'] = false; // default: medium
  137. whiteList['column-rule-width'] = false; // default: medium
  138. whiteList['column-span'] = false; // default: none
  139. whiteList['column-width'] = false; // default: auto
  140. whiteList['columns'] = false; // default: depending on individual properties
  141. whiteList['contain'] = false; // default: none
  142. whiteList['content'] = false; // default: normal
  143. whiteList['counter-increment'] = false; // default: none
  144. whiteList['counter-reset'] = false; // default: none
  145. whiteList['counter-set'] = false; // default: none
  146. whiteList['crop'] = false; // default: auto
  147. whiteList['cue'] = false; // default: depending on individual properties
  148. whiteList['cue-after'] = false; // default: none
  149. whiteList['cue-before'] = false; // default: none
  150. whiteList['cursor'] = false; // default: auto
  151. whiteList['direction'] = false; // default: ltr
  152. whiteList['display'] = true; // default: depending on individual properties
  153. whiteList['display-inside'] = true; // default: auto
  154. whiteList['display-list'] = true; // default: none
  155. whiteList['display-outside'] = true; // default: inline-level
  156. whiteList['dominant-baseline'] = false; // default: auto
  157. whiteList['elevation'] = false; // default: level
  158. whiteList['empty-cells'] = false; // default: show
  159. whiteList['filter'] = false; // default: none
  160. whiteList['flex'] = false; // default: depending on individual properties
  161. whiteList['flex-basis'] = false; // default: auto
  162. whiteList['flex-direction'] = false; // default: row
  163. whiteList['flex-flow'] = false; // default: depending on individual properties
  164. whiteList['flex-grow'] = false; // default: 0
  165. whiteList['flex-shrink'] = false; // default: 1
  166. whiteList['flex-wrap'] = false; // default: nowrap
  167. whiteList['float'] = false; // default: none
  168. whiteList['float-offset'] = false; // default: 0 0
  169. whiteList['flood-color'] = false; // default: black
  170. whiteList['flood-opacity'] = false; // default: 1
  171. whiteList['flow-from'] = false; // default: none
  172. whiteList['flow-into'] = false; // default: none
  173. whiteList['font'] = true; // default: depending on individual properties
  174. whiteList['font-family'] = true; // default: implementation dependent
  175. whiteList['font-feature-settings'] = true; // default: normal
  176. whiteList['font-kerning'] = true; // default: auto
  177. whiteList['font-language-override'] = true; // default: normal
  178. whiteList['font-size'] = true; // default: medium
  179. whiteList['font-size-adjust'] = true; // default: none
  180. whiteList['font-stretch'] = true; // default: normal
  181. whiteList['font-style'] = true; // default: normal
  182. whiteList['font-synthesis'] = true; // default: weight style
  183. whiteList['font-variant'] = true; // default: normal
  184. whiteList['font-variant-alternates'] = true; // default: normal
  185. whiteList['font-variant-caps'] = true; // default: normal
  186. whiteList['font-variant-east-asian'] = true; // default: normal
  187. whiteList['font-variant-ligatures'] = true; // default: normal
  188. whiteList['font-variant-numeric'] = true; // default: normal
  189. whiteList['font-variant-position'] = true; // default: normal
  190. whiteList['font-weight'] = true; // default: normal
  191. whiteList['grid'] = false; // default: depending on individual properties
  192. whiteList['grid-area'] = false; // default: depending on individual properties
  193. whiteList['grid-auto-columns'] = false; // default: auto
  194. whiteList['grid-auto-flow'] = false; // default: none
  195. whiteList['grid-auto-rows'] = false; // default: auto
  196. whiteList['grid-column'] = false; // default: depending on individual properties
  197. whiteList['grid-column-end'] = false; // default: auto
  198. whiteList['grid-column-start'] = false; // default: auto
  199. whiteList['grid-row'] = false; // default: depending on individual properties
  200. whiteList['grid-row-end'] = false; // default: auto
  201. whiteList['grid-row-start'] = false; // default: auto
  202. whiteList['grid-template'] = false; // default: depending on individual properties
  203. whiteList['grid-template-areas'] = false; // default: none
  204. whiteList['grid-template-columns'] = false; // default: none
  205. whiteList['grid-template-rows'] = false; // default: none
  206. whiteList['hanging-punctuation'] = false; // default: none
  207. whiteList['height'] = true; // default: auto
  208. whiteList['hyphens'] = false; // default: manual
  209. whiteList['icon'] = false; // default: auto
  210. whiteList['image-orientation'] = false; // default: auto
  211. whiteList['image-resolution'] = false; // default: normal
  212. whiteList['ime-mode'] = false; // default: auto
  213. whiteList['initial-letters'] = false; // default: normal
  214. whiteList['inline-box-align'] = false; // default: last
  215. whiteList['justify-content'] = false; // default: auto
  216. whiteList['justify-items'] = false; // default: auto
  217. whiteList['justify-self'] = false; // default: auto
  218. whiteList['left'] = false; // default: auto
  219. whiteList['letter-spacing'] = true; // default: normal
  220. whiteList['lighting-color'] = true; // default: white
  221. whiteList['line-box-contain'] = false; // default: block inline replaced
  222. whiteList['line-break'] = false; // default: auto
  223. whiteList['line-grid'] = false; // default: match-parent
  224. whiteList['line-height'] = false; // default: normal
  225. whiteList['line-snap'] = false; // default: none
  226. whiteList['line-stacking'] = false; // default: depending on individual properties
  227. whiteList['line-stacking-ruby'] = false; // default: exclude-ruby
  228. whiteList['line-stacking-shift'] = false; // default: consider-shifts
  229. whiteList['line-stacking-strategy'] = false; // default: inline-line-height
  230. whiteList['list-style'] = true; // default: depending on individual properties
  231. whiteList['list-style-image'] = true; // default: none
  232. whiteList['list-style-position'] = true; // default: outside
  233. whiteList['list-style-type'] = true; // default: disc
  234. whiteList['margin'] = true; // default: depending on individual properties
  235. whiteList['margin-bottom'] = true; // default: 0
  236. whiteList['margin-left'] = true; // default: 0
  237. whiteList['margin-right'] = true; // default: 0
  238. whiteList['margin-top'] = true; // default: 0
  239. whiteList['marker-offset'] = false; // default: auto
  240. whiteList['marker-side'] = false; // default: list-item
  241. whiteList['marks'] = false; // default: none
  242. whiteList['mask'] = false; // default: border-box
  243. whiteList['mask-box'] = false; // default: see individual properties
  244. whiteList['mask-box-outset'] = false; // default: 0
  245. whiteList['mask-box-repeat'] = false; // default: stretch
  246. whiteList['mask-box-slice'] = false; // default: 0 fill
  247. whiteList['mask-box-source'] = false; // default: none
  248. whiteList['mask-box-width'] = false; // default: auto
  249. whiteList['mask-clip'] = false; // default: border-box
  250. whiteList['mask-image'] = false; // default: none
  251. whiteList['mask-origin'] = false; // default: border-box
  252. whiteList['mask-position'] = false; // default: center
  253. whiteList['mask-repeat'] = false; // default: no-repeat
  254. whiteList['mask-size'] = false; // default: border-box
  255. whiteList['mask-source-type'] = false; // default: auto
  256. whiteList['mask-type'] = false; // default: luminance
  257. whiteList['max-height'] = true; // default: none
  258. whiteList['max-lines'] = false; // default: none
  259. whiteList['max-width'] = true; // default: none
  260. whiteList['min-height'] = true; // default: 0
  261. whiteList['min-width'] = true; // default: 0
  262. whiteList['move-to'] = false; // default: normal
  263. whiteList['nav-down'] = false; // default: auto
  264. whiteList['nav-index'] = false; // default: auto
  265. whiteList['nav-left'] = false; // default: auto
  266. whiteList['nav-right'] = false; // default: auto
  267. whiteList['nav-up'] = false; // default: auto
  268. whiteList['object-fit'] = false; // default: fill
  269. whiteList['object-position'] = false; // default: 50% 50%
  270. whiteList['opacity'] = false; // default: 1
  271. whiteList['order'] = false; // default: 0
  272. whiteList['orphans'] = false; // default: 2
  273. whiteList['outline'] = false; // default: depending on individual properties
  274. whiteList['outline-color'] = false; // default: invert
  275. whiteList['outline-offset'] = false; // default: 0
  276. whiteList['outline-style'] = false; // default: none
  277. whiteList['outline-width'] = false; // default: medium
  278. whiteList['overflow'] = false; // default: depending on individual properties
  279. whiteList['overflow-wrap'] = false; // default: normal
  280. whiteList['overflow-x'] = false; // default: visible
  281. whiteList['overflow-y'] = false; // default: visible
  282. whiteList['padding'] = true; // default: depending on individual properties
  283. whiteList['padding-bottom'] = true; // default: 0
  284. whiteList['padding-left'] = true; // default: 0
  285. whiteList['padding-right'] = true; // default: 0
  286. whiteList['padding-top'] = true; // default: 0
  287. whiteList['page'] = false; // default: auto
  288. whiteList['page-break-after'] = false; // default: auto
  289. whiteList['page-break-before'] = false; // default: auto
  290. whiteList['page-break-inside'] = false; // default: auto
  291. whiteList['page-policy'] = false; // default: start
  292. whiteList['pause'] = false; // default: implementation dependent
  293. whiteList['pause-after'] = false; // default: implementation dependent
  294. whiteList['pause-before'] = false; // default: implementation dependent
  295. whiteList['perspective'] = false; // default: none
  296. whiteList['perspective-origin'] = false; // default: 50% 50%
  297. whiteList['pitch'] = false; // default: medium
  298. whiteList['pitch-range'] = false; // default: 50
  299. whiteList['play-during'] = false; // default: auto
  300. whiteList['position'] = false; // default: static
  301. whiteList['presentation-level'] = false; // default: 0
  302. whiteList['quotes'] = false; // default: text
  303. whiteList['region-fragment'] = false; // default: auto
  304. whiteList['resize'] = false; // default: none
  305. whiteList['rest'] = false; // default: depending on individual properties
  306. whiteList['rest-after'] = false; // default: none
  307. whiteList['rest-before'] = false; // default: none
  308. whiteList['richness'] = false; // default: 50
  309. whiteList['right'] = false; // default: auto
  310. whiteList['rotation'] = false; // default: 0
  311. whiteList['rotation-point'] = false; // default: 50% 50%
  312. whiteList['ruby-align'] = false; // default: auto
  313. whiteList['ruby-merge'] = false; // default: separate
  314. whiteList['ruby-position'] = false; // default: before
  315. whiteList['shape-image-threshold'] = false; // default: 0.0
  316. whiteList['shape-outside'] = false; // default: none
  317. whiteList['shape-margin'] = false; // default: 0
  318. whiteList['size'] = false; // default: auto
  319. whiteList['speak'] = false; // default: auto
  320. whiteList['speak-as'] = false; // default: normal
  321. whiteList['speak-header'] = false; // default: once
  322. whiteList['speak-numeral'] = false; // default: continuous
  323. whiteList['speak-punctuation'] = false; // default: none
  324. whiteList['speech-rate'] = false; // default: medium
  325. whiteList['stress'] = false; // default: 50
  326. whiteList['string-set'] = false; // default: none
  327. whiteList['tab-size'] = false; // default: 8
  328. whiteList['table-layout'] = false; // default: auto
  329. whiteList['text-align'] = true; // default: start
  330. whiteList['text-align-last'] = true; // default: auto
  331. whiteList['text-combine-upright'] = true; // default: none
  332. whiteList['text-decoration'] = true; // default: none
  333. whiteList['text-decoration-color'] = true; // default: currentColor
  334. whiteList['text-decoration-line'] = true; // default: none
  335. whiteList['text-decoration-skip'] = true; // default: objects
  336. whiteList['text-decoration-style'] = true; // default: solid
  337. whiteList['text-emphasis'] = true; // default: depending on individual properties
  338. whiteList['text-emphasis-color'] = true; // default: currentColor
  339. whiteList['text-emphasis-position'] = true; // default: over right
  340. whiteList['text-emphasis-style'] = true; // default: none
  341. whiteList['text-height'] = true; // default: auto
  342. whiteList['text-indent'] = true; // default: 0
  343. whiteList['text-justify'] = true; // default: auto
  344. whiteList['text-orientation'] = true; // default: mixed
  345. whiteList['text-overflow'] = true; // default: clip
  346. whiteList['text-shadow'] = true; // default: none
  347. whiteList['text-space-collapse'] = true; // default: collapse
  348. whiteList['text-transform'] = true; // default: none
  349. whiteList['text-underline-position'] = true; // default: auto
  350. whiteList['text-wrap'] = true; // default: normal
  351. whiteList['top'] = false; // default: auto
  352. whiteList['transform'] = false; // default: none
  353. whiteList['transform-origin'] = false; // default: 50% 50% 0
  354. whiteList['transform-style'] = false; // default: flat
  355. whiteList['transition'] = false; // default: depending on individual properties
  356. whiteList['transition-delay'] = false; // default: 0s
  357. whiteList['transition-duration'] = false; // default: 0s
  358. whiteList['transition-property'] = false; // default: all
  359. whiteList['transition-timing-function'] = false; // default: ease
  360. whiteList['unicode-bidi'] = false; // default: normal
  361. whiteList['vertical-align'] = false; // default: baseline
  362. whiteList['visibility'] = false; // default: visible
  363. whiteList['voice-balance'] = false; // default: center
  364. whiteList['voice-duration'] = false; // default: auto
  365. whiteList['voice-family'] = false; // default: implementation dependent
  366. whiteList['voice-pitch'] = false; // default: medium
  367. whiteList['voice-range'] = false; // default: medium
  368. whiteList['voice-rate'] = false; // default: normal
  369. whiteList['voice-stress'] = false; // default: normal
  370. whiteList['voice-volume'] = false; // default: medium
  371. whiteList['volume'] = false; // default: medium
  372. whiteList['white-space'] = false; // default: normal
  373. whiteList['widows'] = false; // default: 2
  374. whiteList['width'] = true; // default: auto
  375. whiteList['will-change'] = false; // default: auto
  376. whiteList['word-break'] = true; // default: normal
  377. whiteList['word-spacing'] = true; // default: normal
  378. whiteList['word-wrap'] = true; // default: normal
  379. whiteList['wrap-flow'] = false; // default: auto
  380. whiteList['wrap-through'] = false; // default: wrap
  381. whiteList['writing-mode'] = false; // default: horizontal-tb
  382. whiteList['z-index'] = false; // default: auto
  383. return whiteList;
  384. }
  385. /**
  386. * 匹配到白名单上的一个属性时
  387. *
  388. * @param {String} name
  389. * @param {String} value
  390. * @param {Object} options
  391. * @return {String}
  392. */
  393. function onAttr (name, value, options) {
  394. // do nothing
  395. }
  396. /**
  397. * 匹配到不在白名单上的一个属性时
  398. *
  399. * @param {String} name
  400. * @param {String} value
  401. * @param {Object} options
  402. * @return {String}
  403. */
  404. function onIgnoreAttr (name, value, options) {
  405. // do nothing
  406. }
  407. var REGEXP_URL_JAVASCRIPT = /javascript\s*\:/img;
  408. /**
  409. * 过滤属性值
  410. *
  411. * @param {String} name
  412. * @param {String} value
  413. * @return {String}
  414. */
  415. function safeAttrValue$1(name, value) {
  416. if (REGEXP_URL_JAVASCRIPT.test(value)) return '';
  417. return value;
  418. }
  419. _default.whiteList = getDefaultWhiteList$1();
  420. _default.getDefaultWhiteList = getDefaultWhiteList$1;
  421. _default.onAttr = onAttr;
  422. _default.onIgnoreAttr = onIgnoreAttr;
  423. _default.safeAttrValue = safeAttrValue$1;
  424. var util$1 = {
  425. indexOf: function (arr, item) {
  426. var i, j;
  427. if (Array.prototype.indexOf) {
  428. return arr.indexOf(item);
  429. }
  430. for (i = 0, j = arr.length; i < j; i++) {
  431. if (arr[i] === item) {
  432. return i;
  433. }
  434. }
  435. return -1;
  436. },
  437. forEach: function (arr, fn, scope) {
  438. var i, j;
  439. if (Array.prototype.forEach) {
  440. return arr.forEach(fn, scope);
  441. }
  442. for (i = 0, j = arr.length; i < j; i++) {
  443. fn.call(scope, arr[i], i, arr);
  444. }
  445. },
  446. trim: function (str) {
  447. if (String.prototype.trim) {
  448. return str.trim();
  449. }
  450. return str.replace(/(^\s*)|(\s*$)/g, '');
  451. },
  452. trimRight: function (str) {
  453. if (String.prototype.trimRight) {
  454. return str.trimRight();
  455. }
  456. return str.replace(/(\s*$)/g, '');
  457. }
  458. };
  459. /**
  460. * cssfilter
  461. *
  462. * @author 老雷<leizongmin@gmail.com>
  463. */
  464. var _$3 = util$1;
  465. /**
  466. * 解析style
  467. *
  468. * @param {String} css
  469. * @param {Function} onAttr 处理属性的函数
  470. * 参数格式: function (sourcePosition, position, name, value, source)
  471. * @return {String}
  472. */
  473. function parseStyle$1 (css, onAttr) {
  474. css = _$3.trimRight(css);
  475. if (css[css.length - 1] !== ';') css += ';';
  476. var cssLength = css.length;
  477. var isParenthesisOpen = false;
  478. var lastPos = 0;
  479. var i = 0;
  480. var retCSS = '';
  481. function addNewAttr () {
  482. // 如果没有正常的闭合圆括号,则直接忽略当前属性
  483. if (!isParenthesisOpen) {
  484. var source = _$3.trim(css.slice(lastPos, i));
  485. var j = source.indexOf(':');
  486. if (j !== -1) {
  487. var name = _$3.trim(source.slice(0, j));
  488. var value = _$3.trim(source.slice(j + 1));
  489. // 必须有属性名称
  490. if (name) {
  491. var ret = onAttr(lastPos, retCSS.length, name, value, source);
  492. if (ret) retCSS += ret + '; ';
  493. }
  494. }
  495. }
  496. lastPos = i + 1;
  497. }
  498. for (; i < cssLength; i++) {
  499. var c = css[i];
  500. if (c === '/' && css[i + 1] === '*') {
  501. // 备注开始
  502. var j = css.indexOf('*/', i + 2);
  503. // 如果没有正常的备注结束,则后面的部分全部跳过
  504. if (j === -1) break;
  505. // 直接将当前位置调到备注结尾,并且初始化状态
  506. i = j + 1;
  507. lastPos = i + 1;
  508. isParenthesisOpen = false;
  509. } else if (c === '(') {
  510. isParenthesisOpen = true;
  511. } else if (c === ')') {
  512. isParenthesisOpen = false;
  513. } else if (c === ';') {
  514. if (isParenthesisOpen) ; else {
  515. addNewAttr();
  516. }
  517. } else if (c === '\n') {
  518. addNewAttr();
  519. }
  520. }
  521. return _$3.trim(retCSS);
  522. }
  523. var parser$2 = parseStyle$1;
  524. /**
  525. * cssfilter
  526. *
  527. * @author 老雷<leizongmin@gmail.com>
  528. */
  529. var DEFAULT$1 = _default;
  530. var parseStyle = parser$2;
  531. /**
  532. * 返回值是否为空
  533. *
  534. * @param {Object} obj
  535. * @return {Boolean}
  536. */
  537. function isNull$1 (obj) {
  538. return (obj === undefined || obj === null);
  539. }
  540. /**
  541. * 浅拷贝对象
  542. *
  543. * @param {Object} obj
  544. * @return {Object}
  545. */
  546. function shallowCopyObject$1 (obj) {
  547. var ret = {};
  548. for (var i in obj) {
  549. ret[i] = obj[i];
  550. }
  551. return ret;
  552. }
  553. /**
  554. * 创建CSS过滤器
  555. *
  556. * @param {Object} options
  557. * - {Object} whiteList
  558. * - {Function} onAttr
  559. * - {Function} onIgnoreAttr
  560. * - {Function} safeAttrValue
  561. */
  562. function FilterCSS$2 (options) {
  563. options = shallowCopyObject$1(options || {});
  564. options.whiteList = options.whiteList || DEFAULT$1.whiteList;
  565. options.onAttr = options.onAttr || DEFAULT$1.onAttr;
  566. options.onIgnoreAttr = options.onIgnoreAttr || DEFAULT$1.onIgnoreAttr;
  567. options.safeAttrValue = options.safeAttrValue || DEFAULT$1.safeAttrValue;
  568. this.options = options;
  569. }
  570. FilterCSS$2.prototype.process = function (css) {
  571. // 兼容各种奇葩输入
  572. css = css || '';
  573. css = css.toString();
  574. if (!css) return '';
  575. var me = this;
  576. var options = me.options;
  577. var whiteList = options.whiteList;
  578. var onAttr = options.onAttr;
  579. var onIgnoreAttr = options.onIgnoreAttr;
  580. var safeAttrValue = options.safeAttrValue;
  581. var retCSS = parseStyle(css, function (sourcePosition, position, name, value, source) {
  582. var check = whiteList[name];
  583. var isWhite = false;
  584. if (check === true) isWhite = check;
  585. else if (typeof check === 'function') isWhite = check(value);
  586. else if (check instanceof RegExp) isWhite = check.test(value);
  587. if (isWhite !== true) isWhite = false;
  588. // 如果过滤后 value 为空则直接忽略
  589. value = safeAttrValue(name, value);
  590. if (!value) return;
  591. var opts = {
  592. position: position,
  593. sourcePosition: sourcePosition,
  594. source: source,
  595. isWhite: isWhite
  596. };
  597. if (isWhite) {
  598. var ret = onAttr(name, value, opts);
  599. if (isNull$1(ret)) {
  600. return name + ':' + value;
  601. } else {
  602. return ret;
  603. }
  604. } else {
  605. var ret = onIgnoreAttr(name, value, opts);
  606. if (!isNull$1(ret)) {
  607. return ret;
  608. }
  609. }
  610. });
  611. return retCSS;
  612. };
  613. var css = FilterCSS$2;
  614. /**
  615. * cssfilter
  616. *
  617. * @author 老雷<leizongmin@gmail.com>
  618. */
  619. (function (module, exports) {
  620. var DEFAULT = _default;
  621. var FilterCSS = css;
  622. /**
  623. * XSS过滤
  624. *
  625. * @param {String} css 要过滤的CSS代码
  626. * @param {Object} options 选项:whiteList, onAttr, onIgnoreAttr
  627. * @return {String}
  628. */
  629. function filterCSS (html, options) {
  630. var xss = new FilterCSS(options);
  631. return xss.process(html);
  632. }
  633. // 输出
  634. exports = module.exports = filterCSS;
  635. exports.FilterCSS = FilterCSS;
  636. for (var i in DEFAULT) exports[i] = DEFAULT[i];
  637. } (lib, lib.exports));
  638. var util = {
  639. indexOf: function (arr, item) {
  640. var i, j;
  641. if (Array.prototype.indexOf) {
  642. return arr.indexOf(item);
  643. }
  644. for (i = 0, j = arr.length; i < j; i++) {
  645. if (arr[i] === item) {
  646. return i;
  647. }
  648. }
  649. return -1;
  650. },
  651. forEach: function (arr, fn, scope) {
  652. var i, j;
  653. if (Array.prototype.forEach) {
  654. return arr.forEach(fn, scope);
  655. }
  656. for (i = 0, j = arr.length; i < j; i++) {
  657. fn.call(scope, arr[i], i, arr);
  658. }
  659. },
  660. trim: function (str) {
  661. if (String.prototype.trim) {
  662. return str.trim();
  663. }
  664. return str.replace(/(^\s*)|(\s*$)/g, "");
  665. },
  666. spaceIndex: function (str) {
  667. var reg = /\s|\n|\t/;
  668. var match = reg.exec(str);
  669. return match ? match.index : -1;
  670. },
  671. };
  672. /**
  673. * default settings
  674. *
  675. * @author Zongmin Lei<leizongmin@gmail.com>
  676. */
  677. var FilterCSS$1 = lib.exports.FilterCSS;
  678. var getDefaultCSSWhiteList = lib.exports.getDefaultWhiteList;
  679. var _$2 = util;
  680. function getDefaultWhiteList() {
  681. return {
  682. a: ["target", "href", "title"],
  683. abbr: ["title"],
  684. address: [],
  685. area: ["shape", "coords", "href", "alt"],
  686. article: [],
  687. aside: [],
  688. audio: [
  689. "autoplay",
  690. "controls",
  691. "crossorigin",
  692. "loop",
  693. "muted",
  694. "preload",
  695. "src",
  696. ],
  697. b: [],
  698. bdi: ["dir"],
  699. bdo: ["dir"],
  700. big: [],
  701. blockquote: ["cite"],
  702. br: [],
  703. caption: [],
  704. center: [],
  705. cite: [],
  706. code: [],
  707. col: ["align", "valign", "span", "width"],
  708. colgroup: ["align", "valign", "span", "width"],
  709. dd: [],
  710. del: ["datetime"],
  711. details: ["open"],
  712. div: [],
  713. dl: [],
  714. dt: [],
  715. em: [],
  716. figcaption: [],
  717. figure: [],
  718. font: ["color", "size", "face"],
  719. footer: [],
  720. h1: [],
  721. h2: [],
  722. h3: [],
  723. h4: [],
  724. h5: [],
  725. h6: [],
  726. header: [],
  727. hr: [],
  728. i: [],
  729. img: ["src", "alt", "title", "width", "height"],
  730. ins: ["datetime"],
  731. li: [],
  732. mark: [],
  733. nav: [],
  734. ol: [],
  735. p: [],
  736. pre: [],
  737. s: [],
  738. section: [],
  739. small: [],
  740. span: [],
  741. sub: [],
  742. summary: [],
  743. sup: [],
  744. strong: [],
  745. strike: [],
  746. table: ["width", "border", "align", "valign"],
  747. tbody: ["align", "valign"],
  748. td: ["width", "rowspan", "colspan", "align", "valign"],
  749. tfoot: ["align", "valign"],
  750. th: ["width", "rowspan", "colspan", "align", "valign"],
  751. thead: ["align", "valign"],
  752. tr: ["rowspan", "align", "valign"],
  753. tt: [],
  754. u: [],
  755. ul: [],
  756. video: [
  757. "autoplay",
  758. "controls",
  759. "crossorigin",
  760. "loop",
  761. "muted",
  762. "playsinline",
  763. "poster",
  764. "preload",
  765. "src",
  766. "height",
  767. "width",
  768. ],
  769. };
  770. }
  771. var defaultCSSFilter = new FilterCSS$1();
  772. /**
  773. * default onTag function
  774. *
  775. * @param {String} tag
  776. * @param {String} html
  777. * @param {Object} options
  778. * @return {String}
  779. */
  780. function onTag(tag, html, options) {
  781. // do nothing
  782. }
  783. /**
  784. * default onIgnoreTag function
  785. *
  786. * @param {String} tag
  787. * @param {String} html
  788. * @param {Object} options
  789. * @return {String}
  790. */
  791. function onIgnoreTag(tag, html, options) {
  792. // do nothing
  793. }
  794. /**
  795. * default onTagAttr function
  796. *
  797. * @param {String} tag
  798. * @param {String} name
  799. * @param {String} value
  800. * @return {String}
  801. */
  802. function onTagAttr(tag, name, value) {
  803. // do nothing
  804. }
  805. /**
  806. * default onIgnoreTagAttr function
  807. *
  808. * @param {String} tag
  809. * @param {String} name
  810. * @param {String} value
  811. * @return {String}
  812. */
  813. function onIgnoreTagAttr(tag, name, value) {
  814. // do nothing
  815. }
  816. /**
  817. * default escapeHtml function
  818. *
  819. * @param {String} html
  820. */
  821. function escapeHtml(html) {
  822. return html.replace(REGEXP_LT, "&lt;").replace(REGEXP_GT, "&gt;");
  823. }
  824. /**
  825. * default safeAttrValue function
  826. *
  827. * @param {String} tag
  828. * @param {String} name
  829. * @param {String} value
  830. * @param {Object} cssFilter
  831. * @return {String}
  832. */
  833. function safeAttrValue(tag, name, value, cssFilter) {
  834. // unescape attribute value firstly
  835. value = friendlyAttrValue(value);
  836. if (name === "href" || name === "src") {
  837. // filter `href` and `src` attribute
  838. // only allow the value that starts with `http://` | `https://` | `mailto:` | `/` | `#`
  839. value = _$2.trim(value);
  840. if (value === "#") return "#";
  841. if (
  842. !(
  843. value.substr(0, 7) === "http://" ||
  844. value.substr(0, 8) === "https://" ||
  845. value.substr(0, 7) === "mailto:" ||
  846. value.substr(0, 4) === "tel:" ||
  847. value.substr(0, 11) === "data:image/" ||
  848. value.substr(0, 6) === "ftp://" ||
  849. value.substr(0, 2) === "./" ||
  850. value.substr(0, 3) === "../" ||
  851. value[0] === "#" ||
  852. value[0] === "/"
  853. )
  854. ) {
  855. return "";
  856. }
  857. } else if (name === "background") {
  858. // filter `background` attribute (maybe no use)
  859. // `javascript:`
  860. REGEXP_DEFAULT_ON_TAG_ATTR_4.lastIndex = 0;
  861. if (REGEXP_DEFAULT_ON_TAG_ATTR_4.test(value)) {
  862. return "";
  863. }
  864. } else if (name === "style") {
  865. // `expression()`
  866. REGEXP_DEFAULT_ON_TAG_ATTR_7.lastIndex = 0;
  867. if (REGEXP_DEFAULT_ON_TAG_ATTR_7.test(value)) {
  868. return "";
  869. }
  870. // `url()`
  871. REGEXP_DEFAULT_ON_TAG_ATTR_8.lastIndex = 0;
  872. if (REGEXP_DEFAULT_ON_TAG_ATTR_8.test(value)) {
  873. REGEXP_DEFAULT_ON_TAG_ATTR_4.lastIndex = 0;
  874. if (REGEXP_DEFAULT_ON_TAG_ATTR_4.test(value)) {
  875. return "";
  876. }
  877. }
  878. if (cssFilter !== false) {
  879. cssFilter = cssFilter || defaultCSSFilter;
  880. value = cssFilter.process(value);
  881. }
  882. }
  883. // escape `<>"` before returns
  884. value = escapeAttrValue(value);
  885. return value;
  886. }
  887. // RegExp list
  888. var REGEXP_LT = /</g;
  889. var REGEXP_GT = />/g;
  890. var REGEXP_QUOTE = /"/g;
  891. var REGEXP_QUOTE_2 = /&quot;/g;
  892. var REGEXP_ATTR_VALUE_1 = /&#([a-zA-Z0-9]*);?/gim;
  893. var REGEXP_ATTR_VALUE_COLON = /&colon;?/gim;
  894. var REGEXP_ATTR_VALUE_NEWLINE = /&newline;?/gim;
  895. // var REGEXP_DEFAULT_ON_TAG_ATTR_3 = /\/\*|\*\//gm;
  896. var REGEXP_DEFAULT_ON_TAG_ATTR_4 =
  897. /((j\s*a\s*v\s*a|v\s*b|l\s*i\s*v\s*e)\s*s\s*c\s*r\s*i\s*p\s*t\s*|m\s*o\s*c\s*h\s*a):/gi;
  898. // var REGEXP_DEFAULT_ON_TAG_ATTR_5 = /^[\s"'`]*(d\s*a\s*t\s*a\s*)\:/gi;
  899. // var REGEXP_DEFAULT_ON_TAG_ATTR_6 = /^[\s"'`]*(d\s*a\s*t\s*a\s*)\:\s*image\//gi;
  900. var REGEXP_DEFAULT_ON_TAG_ATTR_7 =
  901. /e\s*x\s*p\s*r\s*e\s*s\s*s\s*i\s*o\s*n\s*\(.*/gi;
  902. var REGEXP_DEFAULT_ON_TAG_ATTR_8 = /u\s*r\s*l\s*\(.*/gi;
  903. /**
  904. * escape double quote
  905. *
  906. * @param {String} str
  907. * @return {String} str
  908. */
  909. function escapeQuote(str) {
  910. return str.replace(REGEXP_QUOTE, "&quot;");
  911. }
  912. /**
  913. * unescape double quote
  914. *
  915. * @param {String} str
  916. * @return {String} str
  917. */
  918. function unescapeQuote(str) {
  919. return str.replace(REGEXP_QUOTE_2, '"');
  920. }
  921. /**
  922. * escape html entities
  923. *
  924. * @param {String} str
  925. * @return {String}
  926. */
  927. function escapeHtmlEntities(str) {
  928. return str.replace(REGEXP_ATTR_VALUE_1, function replaceUnicode(str, code) {
  929. return code[0] === "x" || code[0] === "X"
  930. ? String.fromCharCode(parseInt(code.substr(1), 16))
  931. : String.fromCharCode(parseInt(code, 10));
  932. });
  933. }
  934. /**
  935. * escape html5 new danger entities
  936. *
  937. * @param {String} str
  938. * @return {String}
  939. */
  940. function escapeDangerHtml5Entities(str) {
  941. return str
  942. .replace(REGEXP_ATTR_VALUE_COLON, ":")
  943. .replace(REGEXP_ATTR_VALUE_NEWLINE, " ");
  944. }
  945. /**
  946. * clear nonprintable characters
  947. *
  948. * @param {String} str
  949. * @return {String}
  950. */
  951. function clearNonPrintableCharacter(str) {
  952. var str2 = "";
  953. for (var i = 0, len = str.length; i < len; i++) {
  954. str2 += str.charCodeAt(i) < 32 ? " " : str.charAt(i);
  955. }
  956. return _$2.trim(str2);
  957. }
  958. /**
  959. * get friendly attribute value
  960. *
  961. * @param {String} str
  962. * @return {String}
  963. */
  964. function friendlyAttrValue(str) {
  965. str = unescapeQuote(str);
  966. str = escapeHtmlEntities(str);
  967. str = escapeDangerHtml5Entities(str);
  968. str = clearNonPrintableCharacter(str);
  969. return str;
  970. }
  971. /**
  972. * unescape attribute value
  973. *
  974. * @param {String} str
  975. * @return {String}
  976. */
  977. function escapeAttrValue(str) {
  978. str = escapeQuote(str);
  979. str = escapeHtml(str);
  980. return str;
  981. }
  982. /**
  983. * `onIgnoreTag` function for removing all the tags that are not in whitelist
  984. */
  985. function onIgnoreTagStripAll() {
  986. return "";
  987. }
  988. /**
  989. * remove tag body
  990. * specify a `tags` list, if the tag is not in the `tags` list then process by the specify function (optional)
  991. *
  992. * @param {array} tags
  993. * @param {function} next
  994. */
  995. function StripTagBody(tags, next) {
  996. if (typeof next !== "function") {
  997. next = function () {};
  998. }
  999. var isRemoveAllTag = !Array.isArray(tags);
  1000. function isRemoveTag(tag) {
  1001. if (isRemoveAllTag) return true;
  1002. return _$2.indexOf(tags, tag) !== -1;
  1003. }
  1004. var removeList = [];
  1005. var posStart = false;
  1006. return {
  1007. onIgnoreTag: function (tag, html, options) {
  1008. if (isRemoveTag(tag)) {
  1009. if (options.isClosing) {
  1010. var ret = "[/removed]";
  1011. var end = options.position + ret.length;
  1012. removeList.push([
  1013. posStart !== false ? posStart : options.position,
  1014. end,
  1015. ]);
  1016. posStart = false;
  1017. return ret;
  1018. } else {
  1019. if (!posStart) {
  1020. posStart = options.position;
  1021. }
  1022. return "[removed]";
  1023. }
  1024. } else {
  1025. return next(tag, html, options);
  1026. }
  1027. },
  1028. remove: function (html) {
  1029. var rethtml = "";
  1030. var lastPos = 0;
  1031. _$2.forEach(removeList, function (pos) {
  1032. rethtml += html.slice(lastPos, pos[0]);
  1033. lastPos = pos[1];
  1034. });
  1035. rethtml += html.slice(lastPos);
  1036. return rethtml;
  1037. },
  1038. };
  1039. }
  1040. /**
  1041. * remove html comments
  1042. *
  1043. * @param {String} html
  1044. * @return {String}
  1045. */
  1046. function stripCommentTag(html) {
  1047. var retHtml = "";
  1048. var lastPos = 0;
  1049. while (lastPos < html.length) {
  1050. var i = html.indexOf("<!--", lastPos);
  1051. if (i === -1) {
  1052. retHtml += html.slice(lastPos);
  1053. break;
  1054. }
  1055. retHtml += html.slice(lastPos, i);
  1056. var j = html.indexOf("-->", i);
  1057. if (j === -1) {
  1058. break;
  1059. }
  1060. lastPos = j + 3;
  1061. }
  1062. return retHtml;
  1063. }
  1064. /**
  1065. * remove invisible characters
  1066. *
  1067. * @param {String} html
  1068. * @return {String}
  1069. */
  1070. function stripBlankChar(html) {
  1071. var chars = html.split("");
  1072. chars = chars.filter(function (char) {
  1073. var c = char.charCodeAt(0);
  1074. if (c === 127) return false;
  1075. if (c <= 31) {
  1076. if (c === 10 || c === 13) return true;
  1077. return false;
  1078. }
  1079. return true;
  1080. });
  1081. return chars.join("");
  1082. }
  1083. _default$1.whiteList = getDefaultWhiteList();
  1084. _default$1.getDefaultWhiteList = getDefaultWhiteList;
  1085. _default$1.onTag = onTag;
  1086. _default$1.onIgnoreTag = onIgnoreTag;
  1087. _default$1.onTagAttr = onTagAttr;
  1088. _default$1.onIgnoreTagAttr = onIgnoreTagAttr;
  1089. _default$1.safeAttrValue = safeAttrValue;
  1090. _default$1.escapeHtml = escapeHtml;
  1091. _default$1.escapeQuote = escapeQuote;
  1092. _default$1.unescapeQuote = unescapeQuote;
  1093. _default$1.escapeHtmlEntities = escapeHtmlEntities;
  1094. _default$1.escapeDangerHtml5Entities = escapeDangerHtml5Entities;
  1095. _default$1.clearNonPrintableCharacter = clearNonPrintableCharacter;
  1096. _default$1.friendlyAttrValue = friendlyAttrValue;
  1097. _default$1.escapeAttrValue = escapeAttrValue;
  1098. _default$1.onIgnoreTagStripAll = onIgnoreTagStripAll;
  1099. _default$1.StripTagBody = StripTagBody;
  1100. _default$1.stripCommentTag = stripCommentTag;
  1101. _default$1.stripBlankChar = stripBlankChar;
  1102. _default$1.cssFilter = defaultCSSFilter;
  1103. _default$1.getDefaultCSSWhiteList = getDefaultCSSWhiteList;
  1104. var parser$1 = {};
  1105. /**
  1106. * Simple HTML Parser
  1107. *
  1108. * @author Zongmin Lei<leizongmin@gmail.com>
  1109. */
  1110. var _$1 = util;
  1111. /**
  1112. * get tag name
  1113. *
  1114. * @param {String} html e.g. '<a hef="#">'
  1115. * @return {String}
  1116. */
  1117. function getTagName(html) {
  1118. var i = _$1.spaceIndex(html);
  1119. var tagName;
  1120. if (i === -1) {
  1121. tagName = html.slice(1, -1);
  1122. } else {
  1123. tagName = html.slice(1, i + 1);
  1124. }
  1125. tagName = _$1.trim(tagName).toLowerCase();
  1126. if (tagName.slice(0, 1) === "/") tagName = tagName.slice(1);
  1127. if (tagName.slice(-1) === "/") tagName = tagName.slice(0, -1);
  1128. return tagName;
  1129. }
  1130. /**
  1131. * is close tag?
  1132. *
  1133. * @param {String} html 如:'<a hef="#">'
  1134. * @return {Boolean}
  1135. */
  1136. function isClosing(html) {
  1137. return html.slice(0, 2) === "</";
  1138. }
  1139. /**
  1140. * parse input html and returns processed html
  1141. *
  1142. * @param {String} html
  1143. * @param {Function} onTag e.g. function (sourcePosition, position, tag, html, isClosing)
  1144. * @param {Function} escapeHtml
  1145. * @return {String}
  1146. */
  1147. function parseTag$1(html, onTag, escapeHtml) {
  1148. var rethtml = "";
  1149. var lastPos = 0;
  1150. var tagStart = false;
  1151. var quoteStart = false;
  1152. var currentPos = 0;
  1153. var len = html.length;
  1154. var currentTagName = "";
  1155. var currentHtml = "";
  1156. chariterator: for (currentPos = 0; currentPos < len; currentPos++) {
  1157. var c = html.charAt(currentPos);
  1158. if (tagStart === false) {
  1159. if (c === "<") {
  1160. tagStart = currentPos;
  1161. continue;
  1162. }
  1163. } else {
  1164. if (quoteStart === false) {
  1165. if (c === "<") {
  1166. rethtml += escapeHtml(html.slice(lastPos, currentPos));
  1167. tagStart = currentPos;
  1168. lastPos = currentPos;
  1169. continue;
  1170. }
  1171. if (c === ">") {
  1172. rethtml += escapeHtml(html.slice(lastPos, tagStart));
  1173. currentHtml = html.slice(tagStart, currentPos + 1);
  1174. currentTagName = getTagName(currentHtml);
  1175. rethtml += onTag(
  1176. tagStart,
  1177. rethtml.length,
  1178. currentTagName,
  1179. currentHtml,
  1180. isClosing(currentHtml)
  1181. );
  1182. lastPos = currentPos + 1;
  1183. tagStart = false;
  1184. continue;
  1185. }
  1186. if (c === '"' || c === "'") {
  1187. var i = 1;
  1188. var ic = html.charAt(currentPos - i);
  1189. while (ic.trim() === "" || ic === "=") {
  1190. if (ic === "=") {
  1191. quoteStart = c;
  1192. continue chariterator;
  1193. }
  1194. ic = html.charAt(currentPos - ++i);
  1195. }
  1196. }
  1197. } else {
  1198. if (c === quoteStart) {
  1199. quoteStart = false;
  1200. continue;
  1201. }
  1202. }
  1203. }
  1204. }
  1205. if (lastPos < html.length) {
  1206. rethtml += escapeHtml(html.substr(lastPos));
  1207. }
  1208. return rethtml;
  1209. }
  1210. var REGEXP_ILLEGAL_ATTR_NAME = /[^a-zA-Z0-9\\_:.-]/gim;
  1211. /**
  1212. * parse input attributes and returns processed attributes
  1213. *
  1214. * @param {String} html e.g. `href="#" target="_blank"`
  1215. * @param {Function} onAttr e.g. `function (name, value)`
  1216. * @return {String}
  1217. */
  1218. function parseAttr$1(html, onAttr) {
  1219. var lastPos = 0;
  1220. var lastMarkPos = 0;
  1221. var retAttrs = [];
  1222. var tmpName = false;
  1223. var len = html.length;
  1224. function addAttr(name, value) {
  1225. name = _$1.trim(name);
  1226. name = name.replace(REGEXP_ILLEGAL_ATTR_NAME, "").toLowerCase();
  1227. if (name.length < 1) return;
  1228. var ret = onAttr(name, value || "");
  1229. if (ret) retAttrs.push(ret);
  1230. }
  1231. // 逐个分析字符
  1232. for (var i = 0; i < len; i++) {
  1233. var c = html.charAt(i);
  1234. var v, j;
  1235. if (tmpName === false && c === "=") {
  1236. tmpName = html.slice(lastPos, i);
  1237. lastPos = i + 1;
  1238. lastMarkPos = html.charAt(lastPos) === '"' || html.charAt(lastPos) === "'" ? lastPos : findNextQuotationMark(html, i + 1);
  1239. continue;
  1240. }
  1241. if (tmpName !== false) {
  1242. if (
  1243. i === lastMarkPos
  1244. ) {
  1245. j = html.indexOf(c, i + 1);
  1246. if (j === -1) {
  1247. break;
  1248. } else {
  1249. v = _$1.trim(html.slice(lastMarkPos + 1, j));
  1250. addAttr(tmpName, v);
  1251. tmpName = false;
  1252. i = j;
  1253. lastPos = i + 1;
  1254. continue;
  1255. }
  1256. }
  1257. }
  1258. if (/\s|\n|\t/.test(c)) {
  1259. html = html.replace(/\s|\n|\t/g, " ");
  1260. if (tmpName === false) {
  1261. j = findNextEqual(html, i);
  1262. if (j === -1) {
  1263. v = _$1.trim(html.slice(lastPos, i));
  1264. addAttr(v);
  1265. tmpName = false;
  1266. lastPos = i + 1;
  1267. continue;
  1268. } else {
  1269. i = j - 1;
  1270. continue;
  1271. }
  1272. } else {
  1273. j = findBeforeEqual(html, i - 1);
  1274. if (j === -1) {
  1275. v = _$1.trim(html.slice(lastPos, i));
  1276. v = stripQuoteWrap(v);
  1277. addAttr(tmpName, v);
  1278. tmpName = false;
  1279. lastPos = i + 1;
  1280. continue;
  1281. } else {
  1282. continue;
  1283. }
  1284. }
  1285. }
  1286. }
  1287. if (lastPos < html.length) {
  1288. if (tmpName === false) {
  1289. addAttr(html.slice(lastPos));
  1290. } else {
  1291. addAttr(tmpName, stripQuoteWrap(_$1.trim(html.slice(lastPos))));
  1292. }
  1293. }
  1294. return _$1.trim(retAttrs.join(" "));
  1295. }
  1296. function findNextEqual(str, i) {
  1297. for (; i < str.length; i++) {
  1298. var c = str[i];
  1299. if (c === " ") continue;
  1300. if (c === "=") return i;
  1301. return -1;
  1302. }
  1303. }
  1304. function findNextQuotationMark(str, i) {
  1305. for (; i < str.length; i++) {
  1306. var c = str[i];
  1307. if (c === " ") continue;
  1308. if (c === "'" || c === '"') return i;
  1309. return -1;
  1310. }
  1311. }
  1312. function findBeforeEqual(str, i) {
  1313. for (; i > 0; i--) {
  1314. var c = str[i];
  1315. if (c === " ") continue;
  1316. if (c === "=") return i;
  1317. return -1;
  1318. }
  1319. }
  1320. function isQuoteWrapString(text) {
  1321. if (
  1322. (text[0] === '"' && text[text.length - 1] === '"') ||
  1323. (text[0] === "'" && text[text.length - 1] === "'")
  1324. ) {
  1325. return true;
  1326. } else {
  1327. return false;
  1328. }
  1329. }
  1330. function stripQuoteWrap(text) {
  1331. if (isQuoteWrapString(text)) {
  1332. return text.substr(1, text.length - 2);
  1333. } else {
  1334. return text;
  1335. }
  1336. }
  1337. parser$1.parseTag = parseTag$1;
  1338. parser$1.parseAttr = parseAttr$1;
  1339. /**
  1340. * filter xss
  1341. *
  1342. * @author Zongmin Lei<leizongmin@gmail.com>
  1343. */
  1344. var FilterCSS = lib.exports.FilterCSS;
  1345. var DEFAULT = _default$1;
  1346. var parser = parser$1;
  1347. var parseTag = parser.parseTag;
  1348. var parseAttr = parser.parseAttr;
  1349. var _ = util;
  1350. /**
  1351. * returns `true` if the input value is `undefined` or `null`
  1352. *
  1353. * @param {Object} obj
  1354. * @return {Boolean}
  1355. */
  1356. function isNull(obj) {
  1357. return obj === undefined || obj === null;
  1358. }
  1359. /**
  1360. * get attributes for a tag
  1361. *
  1362. * @param {String} html
  1363. * @return {Object}
  1364. * - {String} html
  1365. * - {Boolean} closing
  1366. */
  1367. function getAttrs(html) {
  1368. var i = _.spaceIndex(html);
  1369. if (i === -1) {
  1370. return {
  1371. html: "",
  1372. closing: html[html.length - 2] === "/",
  1373. };
  1374. }
  1375. html = _.trim(html.slice(i + 1, -1));
  1376. var isClosing = html[html.length - 1] === "/";
  1377. if (isClosing) html = _.trim(html.slice(0, -1));
  1378. return {
  1379. html: html,
  1380. closing: isClosing,
  1381. };
  1382. }
  1383. /**
  1384. * shallow copy
  1385. *
  1386. * @param {Object} obj
  1387. * @return {Object}
  1388. */
  1389. function shallowCopyObject(obj) {
  1390. var ret = {};
  1391. for (var i in obj) {
  1392. ret[i] = obj[i];
  1393. }
  1394. return ret;
  1395. }
  1396. function keysToLowerCase(obj) {
  1397. var ret = {};
  1398. for (var i in obj) {
  1399. if (Array.isArray(obj[i])) {
  1400. ret[i.toLowerCase()] = obj[i].map(function (item) {
  1401. return item.toLowerCase();
  1402. });
  1403. } else {
  1404. ret[i.toLowerCase()] = obj[i];
  1405. }
  1406. }
  1407. return ret;
  1408. }
  1409. /**
  1410. * FilterXSS class
  1411. *
  1412. * @param {Object} options
  1413. * whiteList (or allowList), onTag, onTagAttr, onIgnoreTag,
  1414. * onIgnoreTagAttr, safeAttrValue, escapeHtml
  1415. * stripIgnoreTagBody, allowCommentTag, stripBlankChar
  1416. * css{whiteList, onAttr, onIgnoreAttr} `css=false` means don't use `cssfilter`
  1417. */
  1418. function FilterXSS(options) {
  1419. options = shallowCopyObject(options || {});
  1420. if (options.stripIgnoreTag) {
  1421. if (options.onIgnoreTag) {
  1422. console.error(
  1423. 'Notes: cannot use these two options "stripIgnoreTag" and "onIgnoreTag" at the same time'
  1424. );
  1425. }
  1426. options.onIgnoreTag = DEFAULT.onIgnoreTagStripAll;
  1427. }
  1428. if (options.whiteList || options.allowList) {
  1429. options.whiteList = keysToLowerCase(options.whiteList || options.allowList);
  1430. } else {
  1431. options.whiteList = DEFAULT.whiteList;
  1432. }
  1433. options.onTag = options.onTag || DEFAULT.onTag;
  1434. options.onTagAttr = options.onTagAttr || DEFAULT.onTagAttr;
  1435. options.onIgnoreTag = options.onIgnoreTag || DEFAULT.onIgnoreTag;
  1436. options.onIgnoreTagAttr = options.onIgnoreTagAttr || DEFAULT.onIgnoreTagAttr;
  1437. options.safeAttrValue = options.safeAttrValue || DEFAULT.safeAttrValue;
  1438. options.escapeHtml = options.escapeHtml || DEFAULT.escapeHtml;
  1439. this.options = options;
  1440. if (options.css === false) {
  1441. this.cssFilter = false;
  1442. } else {
  1443. options.css = options.css || {};
  1444. this.cssFilter = new FilterCSS(options.css);
  1445. }
  1446. }
  1447. /**
  1448. * start process and returns result
  1449. *
  1450. * @param {String} html
  1451. * @return {String}
  1452. */
  1453. FilterXSS.prototype.process = function (html) {
  1454. // compatible with the input
  1455. html = html || "";
  1456. html = html.toString();
  1457. if (!html) return "";
  1458. var me = this;
  1459. var options = me.options;
  1460. var whiteList = options.whiteList;
  1461. var onTag = options.onTag;
  1462. var onIgnoreTag = options.onIgnoreTag;
  1463. var onTagAttr = options.onTagAttr;
  1464. var onIgnoreTagAttr = options.onIgnoreTagAttr;
  1465. var safeAttrValue = options.safeAttrValue;
  1466. var escapeHtml = options.escapeHtml;
  1467. var cssFilter = me.cssFilter;
  1468. // remove invisible characters
  1469. if (options.stripBlankChar) {
  1470. html = DEFAULT.stripBlankChar(html);
  1471. }
  1472. // remove html comments
  1473. if (!options.allowCommentTag) {
  1474. html = DEFAULT.stripCommentTag(html);
  1475. }
  1476. // if enable stripIgnoreTagBody
  1477. var stripIgnoreTagBody = false;
  1478. if (options.stripIgnoreTagBody) {
  1479. stripIgnoreTagBody = DEFAULT.StripTagBody(
  1480. options.stripIgnoreTagBody,
  1481. onIgnoreTag
  1482. );
  1483. onIgnoreTag = stripIgnoreTagBody.onIgnoreTag;
  1484. }
  1485. var retHtml = parseTag(
  1486. html,
  1487. function (sourcePosition, position, tag, html, isClosing) {
  1488. var info = {
  1489. sourcePosition: sourcePosition,
  1490. position: position,
  1491. isClosing: isClosing,
  1492. isWhite: Object.prototype.hasOwnProperty.call(whiteList, tag),
  1493. };
  1494. // call `onTag()`
  1495. var ret = onTag(tag, html, info);
  1496. if (!isNull(ret)) return ret;
  1497. if (info.isWhite) {
  1498. if (info.isClosing) {
  1499. return "</" + tag + ">";
  1500. }
  1501. var attrs = getAttrs(html);
  1502. var whiteAttrList = whiteList[tag];
  1503. var attrsHtml = parseAttr(attrs.html, function (name, value) {
  1504. // call `onTagAttr()`
  1505. var isWhiteAttr = _.indexOf(whiteAttrList, name) !== -1;
  1506. var ret = onTagAttr(tag, name, value, isWhiteAttr);
  1507. if (!isNull(ret)) return ret;
  1508. if (isWhiteAttr) {
  1509. // call `safeAttrValue()`
  1510. value = safeAttrValue(tag, name, value, cssFilter);
  1511. if (value) {
  1512. return name + '="' + value + '"';
  1513. } else {
  1514. return name;
  1515. }
  1516. } else {
  1517. // call `onIgnoreTagAttr()`
  1518. ret = onIgnoreTagAttr(tag, name, value, isWhiteAttr);
  1519. if (!isNull(ret)) return ret;
  1520. return;
  1521. }
  1522. });
  1523. // build new tag html
  1524. html = "<" + tag;
  1525. if (attrsHtml) html += " " + attrsHtml;
  1526. if (attrs.closing) html += " /";
  1527. html += ">";
  1528. return html;
  1529. } else {
  1530. // call `onIgnoreTag()`
  1531. ret = onIgnoreTag(tag, html, info);
  1532. if (!isNull(ret)) return ret;
  1533. return escapeHtml(html);
  1534. }
  1535. },
  1536. escapeHtml
  1537. );
  1538. // if enable stripIgnoreTagBody
  1539. if (stripIgnoreTagBody) {
  1540. retHtml = stripIgnoreTagBody.remove(retHtml);
  1541. }
  1542. return retHtml;
  1543. };
  1544. var xss = FilterXSS;
  1545. /**
  1546. * xss
  1547. *
  1548. * @author Zongmin Lei<leizongmin@gmail.com>
  1549. */
  1550. (function (module, exports) {
  1551. var DEFAULT = _default$1;
  1552. var parser = parser$1;
  1553. var FilterXSS = xss;
  1554. /**
  1555. * filter xss function
  1556. *
  1557. * @param {String} html
  1558. * @param {Object} options { whiteList, onTag, onTagAttr, onIgnoreTag, onIgnoreTagAttr, safeAttrValue, escapeHtml }
  1559. * @return {String}
  1560. */
  1561. function filterXSS(html, options) {
  1562. var xss = new FilterXSS(options);
  1563. return xss.process(html);
  1564. }
  1565. exports = module.exports = filterXSS;
  1566. exports.filterXSS = filterXSS;
  1567. exports.FilterXSS = FilterXSS;
  1568. (function () {
  1569. for (var i in DEFAULT) {
  1570. exports[i] = DEFAULT[i];
  1571. }
  1572. for (var j in parser) {
  1573. exports[j] = parser[j];
  1574. }
  1575. })();
  1576. // using `xss` on the WebWorker, output `filterXSS` to the globals
  1577. function isWorkerEnv() {
  1578. return (
  1579. typeof self !== "undefined" &&
  1580. typeof DedicatedWorkerGlobalScope !== "undefined" &&
  1581. self instanceof DedicatedWorkerGlobalScope
  1582. );
  1583. }
  1584. if (isWorkerEnv()) {
  1585. self.filterXSS = module.exports;
  1586. }
  1587. } (lib$1, lib$1.exports));
  1588. /* Copyright (c) 2020 Environmental Systems Research Institute, Inc.
  1589. * Apache-2.0
  1590. *
  1591. * js-xss
  1592. * Copyright (c) 2012-2018 Zongmin Lei(雷宗民) <leizongmin@gmail.com>
  1593. * http://ucdok.com
  1594. * The MIT License, see
  1595. * https://github.com/leizongmin/js-xss/blob/master/LICENSE for details
  1596. * */
  1597. /**
  1598. * The Sanitizer Class
  1599. *
  1600. * @export
  1601. * @class Sanitizer
  1602. */
  1603. var Sanitizer = /** @class */ (function () {
  1604. function Sanitizer(filterOptions, extendDefaults) {
  1605. var _this = this;
  1606. // Supported HTML Spec: https://doc.arcgis.com/en/arcgis-online/reference/supported-html.htm
  1607. this.arcgisWhiteList = {
  1608. a: ["href", "style", "target"],
  1609. abbr: ["title"],
  1610. audio: ["autoplay", "controls", "loop", "muted", "preload"],
  1611. b: [],
  1612. br: [],
  1613. dd: ["style"],
  1614. div: ["align", "style"],
  1615. dl: ["style"],
  1616. dt: ["style"],
  1617. em: [],
  1618. figcaption: ["style"],
  1619. figure: ["style"],
  1620. font: ["color", "face", "size", "style"],
  1621. h1: ["style"],
  1622. h2: ["style"],
  1623. h3: ["style"],
  1624. h4: ["style"],
  1625. h5: ["style"],
  1626. h6: ["style"],
  1627. hr: [],
  1628. i: [],
  1629. img: ["alt", "border", "height", "src", "style", "width"],
  1630. li: [],
  1631. ol: [],
  1632. p: ["style"],
  1633. source: ["media", "src", "type"],
  1634. span: ["style"],
  1635. strong: [],
  1636. sub: ["style"],
  1637. sup: ["style"],
  1638. table: ["border", "cellpadding", "cellspacing", "height", "style", "width"],
  1639. tbody: [],
  1640. tr: ["align", "height", "style", "valign"],
  1641. td: [
  1642. "align",
  1643. "colspan",
  1644. "height",
  1645. "nowrap",
  1646. "rowspan",
  1647. "style",
  1648. "valign",
  1649. "width",
  1650. ],
  1651. th: [
  1652. "align",
  1653. "colspan",
  1654. "height",
  1655. "nowrap",
  1656. "rowspan",
  1657. "style",
  1658. "valign",
  1659. "width",
  1660. ],
  1661. u: [],
  1662. ul: [],
  1663. video: [
  1664. "autoplay",
  1665. "controls",
  1666. "height",
  1667. "loop",
  1668. "muted",
  1669. "poster",
  1670. "preload",
  1671. "width",
  1672. ],
  1673. };
  1674. this.allowedProtocols = [
  1675. "http",
  1676. "https",
  1677. "mailto",
  1678. "iform",
  1679. "tel",
  1680. "flow",
  1681. "lfmobile",
  1682. "arcgis-navigator",
  1683. "arcgis-appstudio-player",
  1684. "arcgis-survey123",
  1685. "arcgis-collector",
  1686. "arcgis-workforce",
  1687. "arcgis-explorer",
  1688. "arcgis-trek2there",
  1689. "arcgis-quickcapture",
  1690. "mspbi",
  1691. "comgooglemaps",
  1692. "pdfefile",
  1693. "pdfehttp",
  1694. "pdfehttps",
  1695. "boxapp",
  1696. "boxemm",
  1697. "awb",
  1698. "awbs",
  1699. "gropen",
  1700. "radarscope",
  1701. ];
  1702. this.arcgisFilterOptions = {
  1703. allowCommentTag: true,
  1704. safeAttrValue: function (tag, name, value, cssFilter) {
  1705. // Take over safe attribute filtering for `a` `href`, `img` `src`,
  1706. // and `source` `src` attributes, otherwise pass onto the
  1707. // default `XSS.safeAttrValue` method.
  1708. if ((tag === "a" && name === "href") ||
  1709. ((tag === "img" || tag === "source") && name === "src")) {
  1710. return _this.sanitizeUrl(value);
  1711. }
  1712. return lib$1.exports.safeAttrValue(tag, name, value, cssFilter);
  1713. },
  1714. };
  1715. this._entityMap = {
  1716. "&": "&#x38;",
  1717. "<": "&#x3C;",
  1718. ">": "&#x3E;",
  1719. '"': "&#x22;",
  1720. "'": "&#x27;",
  1721. "/": "&#x2F;",
  1722. };
  1723. var xssFilterOptions;
  1724. if (filterOptions && !extendDefaults) {
  1725. // Override the defaults
  1726. xssFilterOptions = filterOptions;
  1727. }
  1728. else if (filterOptions && extendDefaults) {
  1729. // Extend the defaults
  1730. xssFilterOptions = Object.create(this.arcgisFilterOptions);
  1731. Object.keys(filterOptions).forEach(function (key) {
  1732. if (key === "whiteList") {
  1733. // Extend the whitelist by concatenating arrays
  1734. xssFilterOptions.whiteList = _this._extendObjectOfArrays([
  1735. _this.arcgisWhiteList,
  1736. filterOptions.whiteList || {},
  1737. ]);
  1738. }
  1739. else {
  1740. xssFilterOptions[key] = filterOptions[key];
  1741. }
  1742. });
  1743. }
  1744. else {
  1745. // Only use the defaults
  1746. xssFilterOptions = Object.create(this.arcgisFilterOptions);
  1747. xssFilterOptions.whiteList = this.arcgisWhiteList;
  1748. }
  1749. this.xssFilterOptions = xssFilterOptions;
  1750. // Make this readable to tests
  1751. this._xssFilter = new lib$1.exports.FilterXSS(xssFilterOptions);
  1752. }
  1753. /**
  1754. * Sanitizes value to remove invalid HTML tags.
  1755. *
  1756. * Note: If the value passed does not contain a valid JSON data type (String,
  1757. * Number, JSON Object, Array, Boolean, or null), the value will be nullified.
  1758. *
  1759. * @param {any} value The value to sanitize.
  1760. * @returns {any} The sanitized value.
  1761. * @memberof Sanitizer
  1762. */
  1763. Sanitizer.prototype.sanitize = function (value, options) {
  1764. if (options === void 0) { options = {}; }
  1765. switch (typeof value) {
  1766. case "number":
  1767. if (isNaN(value) || !isFinite(value)) {
  1768. return null;
  1769. }
  1770. return value;
  1771. case "boolean":
  1772. return value;
  1773. case "string":
  1774. return this._xssFilter.process(value);
  1775. case "object":
  1776. return this._iterateOverObject(value, options);
  1777. default:
  1778. if (options.allowUndefined && typeof value === "undefined") {
  1779. return;
  1780. }
  1781. return null;
  1782. }
  1783. };
  1784. /**
  1785. * Sanitizes a URL string following the allowed protocols and sanitization rules.
  1786. *
  1787. * @param {string} value The URL to sanitize.
  1788. * @param {{ isProtocolRequired: boolean }} options Configuration options for URL checking.
  1789. * @returns {string} The sanitized URL if it's valid, or an empty string if the URL is invalid.
  1790. */
  1791. Sanitizer.prototype.sanitizeUrl = function (value, options) {
  1792. var _a = (options !== null && options !== void 0 ? options : {}).isProtocolRequired, isProtocolRequired = _a === void 0 ? true : _a;
  1793. var protocol = this._trim(value.substring(0, value.indexOf(":")));
  1794. var isRootUrl = value === '/';
  1795. var isUrlFragment = /^#/.test(value);
  1796. var isValidProtocol = protocol && this.allowedProtocols.indexOf(protocol.toLowerCase()) > -1;
  1797. if (isRootUrl || isUrlFragment || isValidProtocol) {
  1798. return lib$1.exports.escapeAttrValue(value);
  1799. }
  1800. if (!protocol && !isProtocolRequired) {
  1801. return lib$1.exports.escapeAttrValue("https://".concat(value));
  1802. }
  1803. return "";
  1804. };
  1805. /**
  1806. * Sanitizes an HTML attribute value.
  1807. *
  1808. * @param {string} tag The tagname of the HTML element.
  1809. * @param {string} attribute The attribute name of the HTML element.
  1810. * @param {string} value The raw value to be used for the HTML attribute value.
  1811. * @param {XSS.ICSSFilter} [cssFilter] The CSS filter to be used.
  1812. * @returns {string} The sanitized attribute value.
  1813. * @memberof Sanitizer
  1814. */
  1815. Sanitizer.prototype.sanitizeHTMLAttribute = function (tag, attribute, value, cssFilter) {
  1816. // use the custom safeAttrValue function if provided
  1817. if (typeof this.xssFilterOptions.safeAttrValue === "function") {
  1818. return this.xssFilterOptions.safeAttrValue(tag, attribute, value,
  1819. // @ts-expect-error safeAttrValue does handle undefined cssFilter
  1820. cssFilter);
  1821. }
  1822. // otherwise use the default
  1823. // @ts-ignore safeAttrValue does handle undefined cssFilter
  1824. return lib$1.exports.safeAttrValue(tag, attribute, value, cssFilter);
  1825. };
  1826. /**
  1827. * Checks if a value only contains valid HTML.
  1828. *
  1829. * @param {any} value The value to validate.
  1830. * @returns {boolean}
  1831. * @memberof Sanitizer
  1832. */
  1833. Sanitizer.prototype.validate = function (value, options) {
  1834. if (options === void 0) { options = {}; }
  1835. var sanitized = this.sanitize(value, options);
  1836. return {
  1837. isValid: value === sanitized,
  1838. sanitized: sanitized,
  1839. };
  1840. };
  1841. /**
  1842. * Encodes the following characters, `& < > \" ' /` to their hexadecimal HTML entity code.
  1843. * Example: "&middot;" => "&#x38;middot;"
  1844. *
  1845. * @param {string} value The value to encode.
  1846. * @returns {string} The encoded string value.
  1847. * @memberof Sanitizer
  1848. */
  1849. Sanitizer.prototype.encodeHTML = function (value) {
  1850. var _this = this;
  1851. return String(value).replace(/[&<>"'\/]/g, function (s) {
  1852. return _this._entityMap[s];
  1853. });
  1854. };
  1855. /**
  1856. * Encodes all non-alphanumeric ASCII characters to their hexadecimal HTML entity codes.
  1857. * Example: "alert(document.cookie)" => "alert&#x28;document&#x2e;cookie&#x29;"
  1858. *
  1859. * @param {string} value The value to encode.
  1860. * @returns {string} The encoded string value.
  1861. * @memberof Sanitizer
  1862. */
  1863. Sanitizer.prototype.encodeAttrValue = function (value) {
  1864. var alphanumericRE = /^[a-zA-Z0-9]$/;
  1865. return String(value).replace(/[\x00-\xFF]/g, function (c, idx) {
  1866. return !alphanumericRE.test(c)
  1867. ? "&#x".concat(Number(value.charCodeAt(idx)).toString(16), ";")
  1868. : c;
  1869. });
  1870. };
  1871. /**
  1872. * Extends an object of arrays by by concatenating arrays of the same object
  1873. * keys. If the if the previous key's value is not an array, the next key's
  1874. * value will replace the previous key. This method is used for extending the
  1875. * whiteList in the XSS filter options.
  1876. *
  1877. * @private
  1878. * @param {Array<{}>} objects An array of objects.
  1879. * @returns {{}} The extended object.
  1880. * @memberof Sanitizer
  1881. */
  1882. Sanitizer.prototype._extendObjectOfArrays = function (objects) {
  1883. var finalObj = {};
  1884. objects.forEach(function (obj) {
  1885. Object.keys(obj).forEach(function (key) {
  1886. if (Array.isArray(obj[key]) && Array.isArray(finalObj[key])) {
  1887. finalObj[key] = finalObj[key].concat(obj[key]);
  1888. }
  1889. else {
  1890. finalObj[key] = obj[key];
  1891. }
  1892. });
  1893. });
  1894. return finalObj;
  1895. };
  1896. /**
  1897. * Iterate over a plain object or array to deeply sanitize each value.
  1898. *
  1899. * @private
  1900. * @param {object} obj The object to iterate over.
  1901. * @returns {(object | null)} The sanitized object.
  1902. * @memberof Sanitizer
  1903. */
  1904. Sanitizer.prototype._iterateOverObject = function (obj, options) {
  1905. var _this = this;
  1906. if (options === void 0) { options = {}; }
  1907. try {
  1908. var hasChanged_1 = false;
  1909. var changedObj = void 0;
  1910. if (Array.isArray(obj)) {
  1911. changedObj = obj.reduce(function (prev, value) {
  1912. var validation = _this.validate(value, options);
  1913. if (validation.isValid) {
  1914. return prev.concat([value]);
  1915. }
  1916. else {
  1917. hasChanged_1 = true;
  1918. return prev.concat([validation.sanitized]);
  1919. }
  1920. }, []);
  1921. }
  1922. else if (!isPlainObject(obj)) {
  1923. if (options.allowUndefined && typeof obj === "undefined") {
  1924. return;
  1925. }
  1926. return null;
  1927. }
  1928. else {
  1929. var keys = Object.keys(obj);
  1930. changedObj = keys.reduce(function (prev, key) {
  1931. var value = obj[key];
  1932. var validation = _this.validate(value, options);
  1933. if (validation.isValid) {
  1934. prev[key] = value;
  1935. }
  1936. else {
  1937. hasChanged_1 = true;
  1938. prev[key] = validation.sanitized;
  1939. }
  1940. return prev;
  1941. }, {});
  1942. }
  1943. if (hasChanged_1) {
  1944. return changedObj;
  1945. }
  1946. return obj;
  1947. }
  1948. catch (err) {
  1949. return null;
  1950. }
  1951. };
  1952. /**
  1953. * Trim whitespace from the start and ends of a string.
  1954. * @param {string} val The string to trim.
  1955. * @returns {string} The trimmed string.
  1956. */
  1957. Sanitizer.prototype._trim = function (val) {
  1958. // @ts-ignore This is used by Jest,
  1959. // but TypeScript errors since it assumes `trim` is always available.
  1960. return String.prototype.trim
  1961. ? val.trim()
  1962. : val.replace(/(^\s*)|(\s*$)/g, "");
  1963. };
  1964. return Sanitizer;
  1965. }());
  1966. export { Sanitizer, Sanitizer as default };