UNPKG

40.7 kBPlain TextView Raw
1/* eslint-disable camelcase */
2// Copyright (c) Jupyter Development Team.
3// Distributed under the terms of the Modified BSD License.
4
5import sanitize from 'sanitize-html';
6import { IRenderMime } from '@jupyterlab/rendermime-interfaces';
7
8/**
9 * Helper class that contains regular expressions for inline CSS style validation.
10 *
11 * Which properties (and values) to allow is largely based on the Google Caja project:
12 * https://github.com/google/caja
13 *
14 * The regular expressions are largly based on the syntax definition found at
15 * https://developer.mozilla.org/en-US/docs/Web/CSS.
16 */
17class CssProp {
18 static reg(r: string): RegExp {
19 return new RegExp('^' + r + '$', 'i');
20 }
21
22 /*
23 * Numeric base expressions used to help build more complex regular expressions
24 */
25 private static readonly N = {
26 integer: `[+-]?[0-9]+`,
27 integer_pos: `[+]?[0-9]+`,
28 integer_zero_ff: `([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])`,
29 number: `[+-]?([0-9]*[.])?[0-9]+(e-?[0-9]*)?`,
30 number_pos: `[+]?([0-9]*[.])?[0-9]+(e-?[0-9]*)?`,
31 number_zero_hundred: `[+]?(([0-9]|[1-9][0-9])([.][0-9]+)?|100)`,
32 number_zero_one: `[+]?(1([.][0]+)?|0?([.][0-9]+)?)`
33 };
34
35 /*
36 * Base expressions of common CSS syntax elements
37 */
38 private static readonly B = {
39 angle: `(${CssProp.N.number}(deg|rad|grad|turn)|0)`,
40 frequency: `${CssProp.N.number}(Hz|kHz)`,
41 ident: String.raw`-?([_a-z]|[\xA0-\xFF]|\\[0-9a-f]{1,6}(\r\n|[ \t\r\n\f])?|\\[^\r\n\f0-9a-f])([_a-z0-9-]|[\xA0-\xFF]|\\[0-9a-f]{1,6}(\r\n|[ \t\r\n\f])?|\\[^\r\n\f0-9a-f])*`,
42 len_or_perc: `(0|${CssProp.N.number}(px|em|rem|ex|in|cm|mm|pt|pc|%))`,
43 length: `(${CssProp.N.number}(px|em|rem|ex|in|cm|mm|pt|pc)|0)`,
44 length_pos: `(${CssProp.N.number_pos}(px|em|rem|ex|in|cm|mm|pt|pc)|0)`,
45 percentage: `${CssProp.N.number}%`,
46 percentage_pos: `${CssProp.N.number_pos}%`,
47 percentage_zero_hundred: `${CssProp.N.number_zero_hundred}%`,
48 string: String.raw`(\"([^\n\r\f\\"]|\\\n|\r\n|\r|\f|\\[0-9a-f]{1,6}(\r\n|[ \t\r\n\f])?|\\[^\r\n\f0-9a-f])*\")|(\'([^\n\r\f\\']|\\\n|\r\n|\r|\f|\\[0-9a-f]{1,6}(\r\n|[ \t\r\n\f])?|\\[^\r\n\f0-9a-f])*\')`,
49 time: `${CssProp.N.number}(s|ms)`,
50 url: `url\\(.*?\\)`,
51 z_index: `[+-]?[0-9]{1,7}`
52 };
53
54 /*
55 * Atomic (i.e. not dependant on other regular expressions) sub RegEx segments
56 */
57 private static readonly A = {
58 absolute_size: `xx-small|x-small|small|medium|large|x-large|xx-large`,
59 attachment: `scroll|fixed|local`,
60 bg_origin: `border-box|padding-box|content-box`,
61 border_style: `none|hidden|dotted|dashed|solid|double|groove|ridge|inset|outset`,
62 box: `border-box|padding-box|content-box`,
63 display_inside: `auto|block|table|flex|grid`,
64 display_outside: `block-level|inline-level|none|table-row-group|table-header-group|table-footer-group|table-row|table-cell|table-column-group|table-column|table-caption`,
65 ending_shape: `circle|ellipse`,
66 generic_family: `serif|sans-serif|cursive|fantasy|monospace`,
67 generic_voice: `male|female|child`,
68 relative_size: `smaller|larger`,
69 repeat_style: `repeat-x|repeat-y|((?:repeat|space|round|no-repeat)(?:\\s*(?:repeat|space|round|no-repeat))?)`,
70 side_or_corner: `(left|right)?\\s*(top|bottom)?`,
71 single_animation_direction: `normal|reverse|alternate|alternate-reverse`,
72 single_animation_fill_mode: `none|forwards|backwards|both`,
73 single_animation_play_state: `running|paused`
74 };
75
76 /*
77 * Color definition sub expressions
78 */
79 private static readonly _COLOR = {
80 hex: `\\#(0x)?[0-9a-f]+`,
81 name: `aliceblue|antiquewhite|aqua|aquamarine|azure|beige|bisque|black|blanchedalmond|blue|blueviolet|brown|burlywood|cadetblue|chartreuse|chocolate|coral|cornflowerblue|cornsilk|crimson|cyan|darkblue|darkcyan|darkgoldenrod|darkgray|darkgreen|darkkhaki|darkmagenta|darkolivegreen|darkorange|darkorchid|darkred|darksalmon|darkseagreen|darkslateblue|darkslategray|darkturquoise|darkviolet|deeppink|deepskyblue|dimgray|dodgerblue|firebrick|floralwhite|forestgreen|fuchsia|gainsboro|ghostwhite|gold|goldenrod|gray|green|greenyellow|honeydew|hotpink|indianred|indigo|ivory|khaki|lavender|lavenderblush|lawngreen|lemonchiffon|lightblue|lightcoral|lightcyan|lightgoldenrodyellow|lightgreen|lightgrey|lightpink|lightsalmon|lightseagreen|lightskyblue|lightslategray|lightsteelblue|lightyellow|lime|limegreen|linen|magenta|maroon|mediumaquamarine|mediumblue|mediumorchid|mediumpurple|mediumseagreen|mediumslateblue|mediumspringgreen|mediumturquoise|mediumvioletred|midnightblue|mintcream|mistyrose|moccasin|navajowhite|navy|oldlace|olive|olivedrab|orange|orangered|orchid|palegoldenrod|palegreen|paleturquoise|palevioletred|papayawhip|peachpuff|peru|pink|plum|powderblue|purple|red|rosybrown|royalblue|saddlebrown|salmon|sandybrown|seagreen|seashell|sienna|silver|skyblue|slateblue|slategray|snow|springgreen|steelblue|tan|teal|thistle|tomato|turquoise|transparent|violet|wheat|white|whitesmoke|yellow|yellowgreen`,
82 rgb: String.raw`rgb\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*\)`,
83 rgba: String.raw`rgba\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(${CssProp.N.integer_zero_ff}|${CssProp.N.number_zero_one}|${CssProp.B.percentage_zero_hundred})\s*\)`
84 };
85
86 /*
87 * Compound (i.e. dependant on other (sub) regular expressions) sub RegEx segments
88 */
89 private static readonly _C = {
90 alpha: `${CssProp.N.integer_zero_ff}|${CssProp.N.number_zero_one}|${CssProp.B.percentage_zero_hundred}`,
91 alphavalue: CssProp.N.number_zero_one,
92 bg_position: `((${CssProp.B.len_or_perc}|left|center|right|top|bottom)\\s*){1,4}`,
93 bg_size: `(${CssProp.B.length_pos}|${CssProp.B.percentage}|auto){1,2}|cover|contain`,
94 border_width: `thin|medium|thick|${CssProp.B.length}`,
95 bottom: `${CssProp.B.length}|auto`,
96 color: `${CssProp._COLOR.hex}|${CssProp._COLOR.rgb}|${CssProp._COLOR.rgba}|${CssProp._COLOR.name}`,
97 color_stop_length: `(${CssProp.B.len_or_perc}\\s*){1,2}`,
98 linear_color_hint: `${CssProp.B.len_or_perc}`,
99 family_name: `${CssProp.B.string}|(${CssProp.B.ident}\\s*)+`,
100 image_decl: CssProp.B.url,
101 left: `${CssProp.B.length}|auto`,
102 loose_quotable_words: `(${CssProp.B.ident})+`,
103 margin_width: `${CssProp.B.len_or_perc}|auto`,
104 padding_width: `${CssProp.B.length_pos}|${CssProp.B.percentage_pos}`,
105 page_url: CssProp.B.url,
106 position: `((${CssProp.B.len_or_perc}|left|center|right|top|bottom)\\s*){1,4}`,
107 right: `${CssProp.B.length}|auto`,
108 shadow: '',
109 size: `closest-side|farthest-side|closest-corner|farthest-corner|${CssProp.B.length}|(${CssProp.B.len_or_perc})\\s+(${CssProp.B.len_or_perc})`,
110 top: `${CssProp.B.length}|auto`
111 };
112
113 private static readonly _C1 = {
114 image_list: `image\\(\\s*(${CssProp.B.url})*\\s*(${CssProp.B.url}|${CssProp._C.color})\\s*\\)`,
115 linear_color_stop: `(${CssProp._C.color})(\\s*${CssProp._C.color_stop_length})?`,
116 shadow: `((${CssProp._C.color})\\s+((${CssProp.B.length})\\s*){2,4}(\s+inset)?)|((inset\\s+)?((${CssProp.B.length})\\s*){2,4}\\s*(${CssProp._C.color})?)`
117 };
118
119 private static readonly _C2 = {
120 color_stop_list: `((${CssProp._C1.linear_color_stop})(\\s*(${CssProp._C.linear_color_hint}))?\\s*,\\s*)+(${CssProp._C1.linear_color_stop})`,
121 shape: `rect\\(\\s*(${CssProp._C.top})\\s*,\\s*(${CssProp._C.right})\\s*,\\s*(${CssProp._C.bottom})\\s*,\\s*(${CssProp._C.left})\\s*\\)`
122 };
123
124 private static readonly _C3 = {
125 linear_gradient: `linear-gradient\\((((${CssProp.B.angle})|to\\s+(${CssProp.A.side_or_corner}))\\s*,\\s*)?\\s*(${CssProp._C2.color_stop_list})\\s*\\)`,
126 radial_gradient: `radial-gradient\\(((((${CssProp.A.ending_shape})|(${CssProp._C.size}))\\s*)*\\s*(at\\s+${CssProp._C.position})?\\s*,\\s*)?\\s*(${CssProp._C2.color_stop_list})\\s*\\)`
127 };
128
129 private static readonly _C4 = {
130 image: `${CssProp.B.url}|${CssProp._C3.linear_gradient}|${CssProp._C3.radial_gradient}|${CssProp._C1.image_list}`,
131 bg_image: `(${CssProp.B.url}|${CssProp._C3.linear_gradient}|${CssProp._C3.radial_gradient}|${CssProp._C1.image_list})|none`
132 };
133
134 private static readonly C = {
135 ...CssProp._C,
136 ...CssProp._C1,
137 ...CssProp._C2,
138 ...CssProp._C3,
139 ...CssProp._C4
140 };
141
142 /*
143 * Property value regular expressions not dependant on other sub expressions
144 */
145 private static readonly AP = {
146 border_collapse: `collapse|separate`,
147 box: `normal|none|contents`,
148 box_sizing: `content-box|padding-box|border-box`,
149 caption_side: `top|bottom`,
150 clear: `none|left|right|both`,
151 direction: `ltr|rtl`,
152 empty_cells: `show|hide`,
153 float: `left|right|none`,
154 font_stretch: `normal|wider|narrower|ultra-condensed|extra-condensed|condensed|semi-condensed|semi-expanded|expanded|extra-expanded|ultra-expanded`,
155 font_style: `normal|italic|oblique`,
156 font_variant: `normal|small-caps`,
157 font_weight: `normal|bold|bolder|lighter|100|200|300|400|500|600|700|800|900`,
158 list_style_position: `inside|outside`,
159 list_style_type: `disc|circle|square|decimal|decimal-leading-zero|lower-roman|upper-roman|lower-greek|lower-latin|upper-latin|armenian|georgian|lower-alpha|upper-alpha|none`,
160 overflow: `visible|hidden|scroll|auto`,
161 overflow_wrap: `normal|break-word`,
162 overflow_x: `visible|hidden|scroll|auto|no-display|no-content`,
163 page_break_after: `auto|always|avoid|left|right`,
164 page_break_before: `auto|always|avoid|left|right`,
165 page_break_inside: `avoid|auto`,
166 position: `static|relative|absolute`,
167 resize: `none|both|horizontal|vertical`,
168 speak: `normal|none|spell-out`,
169 speak_header: `once|always`,
170 speak_numeral: `digits|continuous`,
171 speak_punctuation: `code|none`,
172 table_layout: `auto|fixed`,
173 text_align: `left|right|center|justify`,
174 text_decoration: `none|((underline|overline|line-through|blink)\\s*)+`,
175 text_transform: `capitalize|uppercase|lowercase|none`,
176 text_wrap: `normal|unrestricted|none|suppress`,
177 unicode_bidi: `normal|embed|bidi-override`,
178 visibility: `visible|hidden|collapse`,
179 white_space: `normal|pre|nowrap|pre-wrap|pre-line`,
180 word_break: `normal|keep-all|break-all`
181 };
182
183 /*
184 * Compound propertiy value regular expressions (i.e. dependant on other sub expressions)
185 */
186 private static readonly _CP = {
187 background_attachment: `${CssProp.A.attachment}(,\\s*${CssProp.A.attachment})*`,
188 background_color: CssProp.C.color,
189 background_origin: `${CssProp.A.box}(,\\s*${CssProp.A.box})*`,
190 background_repeat: `${CssProp.A.repeat_style}(,\\s*${CssProp.A.repeat_style})*`,
191 border: `((${CssProp.C.border_width}|${CssProp.A.border_style}|${CssProp.C.color})\\s*){1,3}`,
192 border_radius: `((${CssProp.B.len_or_perc})\\s*){1,4}(\\/\\s*((${CssProp.B.len_or_perc})\\s*){1,4})?`,
193 border_spacing: `${CssProp.B.length}\\s*(${CssProp.B.length})?`,
194 border_top_color: CssProp.C.color,
195 border_top_style: CssProp.A.border_style,
196 border_width: `((${CssProp.C.border_width})\\s*){1,4}`,
197 color: CssProp.C.color,
198 cursor: `(${CssProp.B.url}(\\s*,\\s*)?)*(auto|crosshair|default|pointer|move|e-resize|ne-resize|nw-resize|n-resize|se-resize|sw-resize|s-resize|w-resize|text|wait|help|progress|all-scroll|col-resize|hand|no-drop|not-allowed|row-resize|vertical-text)`,
199 display: `inline|block|list-item|run-in|inline-list-item|inline-block|table|inline-table|table-cell|table-caption|flex|inline-flex|grid|inline-grid|${CssProp.A.display_inside}|${CssProp.A.display_outside}|inherit|inline-box|inline-stack`,
200 display_outside: CssProp.A.display_outside,
201 elevation: `${CssProp.B.angle}|below|level|above|higher|lower`,
202 font_family: `(${CssProp.C.family_name}|${CssProp.A.generic_family})(,\\s*(${CssProp.C.family_name}|${CssProp.A.generic_family}))*`,
203 height: `${CssProp.B.length}|${CssProp.B.percentage}|auto`,
204 letter_spacing: `normal|${CssProp.B.length}`,
205 list_style_image: `${CssProp.C.image}|none`,
206 margin_right: CssProp.C.margin_width,
207 max_height: `${CssProp.B.length_pos}|${CssProp.B.percentage_pos}|none|auto`,
208 min_height: `${CssProp.B.length_pos}|${CssProp.B.percentage_pos}|auto`,
209 opacity: CssProp.C.alphavalue,
210 outline_color: `${CssProp.C.color}|invert`,
211 outline_width: CssProp.C.border_width,
212 padding: `((${CssProp.C.padding_width})\\s*){1,4}`,
213 padding_top: CssProp.C.padding_width,
214 pitch_range: CssProp.N.number,
215 right: `${CssProp.B.length}|${CssProp.B.percentage}|auto`,
216 stress: CssProp.N.number,
217 text_indent: `${CssProp.B.length}|${CssProp.B.percentage}`,
218 text_shadow: `none|${CssProp.C.shadow}(,\\s*(${CssProp.C.shadow}))*`,
219 volume: `${CssProp.N.number_pos}|${CssProp.B.percentage_pos}|silent|x-soft|soft|medium|loud|x-loud`,
220 word_wrap: CssProp.AP.overflow_wrap,
221 zoom: `normal|${CssProp.N.number_pos}|${CssProp.B.percentage_pos}`,
222 backface_visibility: CssProp.AP.visibility,
223 background_clip: `${CssProp.A.box}(,\\s*(${CssProp.A.box}))*`,
224 background_position: `${CssProp.C.bg_position}(,\\s*(${CssProp.C.bg_position}))*`,
225 border_bottom_color: CssProp.C.color,
226 border_bottom_style: CssProp.A.border_style,
227 border_color: `((${CssProp.C.color})\\s*){1,4}`,
228 border_left_color: CssProp.C.color,
229 border_right_color: CssProp.C.color,
230 border_style: `((${CssProp.A.border_style})\\s*){1,4}`,
231 border_top_left_radius: `(${CssProp.B.length}|${CssProp.B.percentage})(\\s*(${CssProp.B.length}|${CssProp.B.percentage}))?`,
232 border_top_width: CssProp.C.border_width,
233 box_shadow: `none|${CssProp.C.shadow}(,\\s*(${CssProp.C.shadow}))*`,
234 clip: `${CssProp.C.shape}|auto`,
235 display_inside: CssProp.A.display_inside,
236 font_size: `${CssProp.A.absolute_size}|${CssProp.A.relative_size}|${CssProp.B.length_pos}|${CssProp.B.percentage_pos}`,
237 line_height: `normal|${CssProp.N.number_pos}|${CssProp.B.length_pos}|${CssProp.B.percentage_pos}`,
238 margin_left: CssProp.C.margin_width,
239 max_width: `${CssProp.B.length_pos}|${CssProp.B.percentage_pos}|none|auto`,
240 outline_style: CssProp.A.border_style,
241 padding_bottom: CssProp.C.padding_width,
242 padding_right: CssProp.C.padding_width,
243 perspective: `none|${CssProp.B.length}`,
244 richness: CssProp.N.number,
245 text_overflow: `((clip|ellipsis|${CssProp.B.string})\\s*){1,2}`,
246 top: `${CssProp.B.length}|${CssProp.B.percentage}|auto`,
247 width: `${CssProp.B.length_pos}|${CssProp.B.percentage_pos}|auto`,
248 z_index: `auto|${CssProp.B.z_index}`,
249 // Simplified background
250 background: `(((${CssProp.C.bg_position}\\s*(\\/\\s*${CssProp.C.bg_size})?)|(${CssProp.A.repeat_style})|(${CssProp.A.attachment})|(${CssProp.A.bg_origin})|(${CssProp.C.bg_image})|(${CssProp.C.color}))\\s*)+`,
251 background_size: `${CssProp.C.bg_size}(,\\s*${CssProp.C.bg_size})*`,
252 border_bottom_left_radius: `(${CssProp.B.length}|${CssProp.B.percentage})(\\s*(${CssProp.B.length}|${CssProp.B.percentage}))?`,
253 border_bottom_width: CssProp.C.border_width,
254 border_left_style: CssProp.A.border_style,
255 border_right_style: CssProp.A.border_style,
256 border_top: `((${CssProp.C.border_width}|${CssProp.A.border_style}|${CssProp.C.color})\\s*){1,3}`,
257 bottom: `${CssProp.B.len_or_perc}|auto`,
258 list_style: `((${CssProp.AP.list_style_type}|${CssProp.AP.list_style_position}|${CssProp.C.image}|none})\\s*){1,3}`,
259 margin_top: CssProp.C.margin_width,
260 outline: `((${CssProp.C.color}|invert|${CssProp.A.border_style}|${CssProp.C.border_width})\\s*){1,3}`,
261 overflow_y: CssProp.AP.overflow_x,
262 pitch: `${CssProp.B.frequency}|x-low|low|medium|high|x-high`,
263 vertical_align: `baseline|sub|super|top|text-top|middle|bottom|text-bottom|${CssProp.B.len_or_perc}`,
264 word_spacing: `normal|${CssProp.B.length}`,
265 background_image: `${CssProp.C.bg_image}(,\\s*${CssProp.C.bg_image})*`,
266 border_bottom_right_radius: `(${CssProp.B.length}|${CssProp.B.percentage})(\\s*(${CssProp.B.length}|${CssProp.B.percentage}))?`,
267 border_left_width: CssProp.C.border_width,
268 border_right_width: CssProp.C.border_width,
269 left: `${CssProp.B.len_or_perc}|auto`,
270 margin_bottom: CssProp.C.margin_width,
271 pause_after: `${CssProp.B.time}|${CssProp.B.percentage}`,
272 speech_rate: `${CssProp.N.number}|x-slow|slow|medium|fast|x-fast|faster|slower`,
273 transition_duration: `${CssProp.B.time}(,\\s*${CssProp.B.time})*`,
274 border_bottom: `((${CssProp.C.border_width}|${CssProp.A.border_style}|${CssProp.C.color})\\s*){1,3}`,
275 border_right: `((${CssProp.C.border_width}|${CssProp.A.border_style}|${CssProp.C.color})\\s*){1,3}`,
276 margin: `((${CssProp.C.margin_width})\\s*){1,4}`,
277 padding_left: CssProp.C.padding_width,
278 border_left: `((${CssProp.C.border_width}|${CssProp.A.border_style}|${CssProp.C.color})\\s*){1,3}`,
279 quotes: `(${CssProp.B.string}\\s*${CssProp.B.string})+|none`,
280 border_top_right_radius: `(${CssProp.B.length}|${CssProp.B.percentage})(\\s*(${CssProp.B.length}|${CssProp.B.percentage}))?`,
281 min_width: `${CssProp.B.length_pos}|${CssProp.B.percentage_pos}|auto`
282 };
283
284 private static readonly _CP1 = {
285 font: `(((((${CssProp.AP.font_style}|${CssProp.AP.font_variant}|${CssProp.AP.font_weight})\\s*){1,3})?\\s*(${CssProp._CP.font_size})\\s*(\\/\\s*(${CssProp._CP.line_height}))?\\s+(${CssProp._CP.font_family}))|caption|icon|menu|message-box|small-caption|status-bar)`
286 };
287
288 private static readonly CP = { ...CssProp._CP, ...CssProp._CP1 };
289
290 // CSS Property value validation regular expressions for use with sanitize-html
291
292 static BORDER_COLLAPSE = CssProp.reg(CssProp.AP.border_collapse);
293 static BOX = CssProp.reg(CssProp.AP.box);
294 static BOX_SIZING = CssProp.reg(CssProp.AP.box_sizing);
295 static CAPTION_SIDE = CssProp.reg(CssProp.AP.caption_side);
296 static CLEAR = CssProp.reg(CssProp.AP.clear);
297 static DIRECTION = CssProp.reg(CssProp.AP.direction);
298 static EMPTY_CELLS = CssProp.reg(CssProp.AP.empty_cells);
299 static FLOAT = CssProp.reg(CssProp.AP.float);
300 static FONT_STRETCH = CssProp.reg(CssProp.AP.font_stretch);
301 static FONT_STYLE = CssProp.reg(CssProp.AP.font_style);
302 static FONT_VARIANT = CssProp.reg(CssProp.AP.font_variant);
303 static FONT_WEIGHT = CssProp.reg(CssProp.AP.font_weight);
304 static LIST_STYLE_POSITION = CssProp.reg(CssProp.AP.list_style_position);
305 static LIST_STYLE_TYPE = CssProp.reg(CssProp.AP.list_style_type);
306 static OVERFLOW = CssProp.reg(CssProp.AP.overflow);
307 static OVERFLOW_WRAP = CssProp.reg(CssProp.AP.overflow_wrap);
308 static OVERFLOW_X = CssProp.reg(CssProp.AP.overflow_x);
309 static PAGE_BREAK_AFTER = CssProp.reg(CssProp.AP.page_break_after);
310 static PAGE_BREAK_BEFORE = CssProp.reg(CssProp.AP.page_break_before);
311 static PAGE_BREAK_INSIDE = CssProp.reg(CssProp.AP.page_break_inside);
312 static POSITION = CssProp.reg(CssProp.AP.position);
313 static RESIZE = CssProp.reg(CssProp.AP.resize);
314 static SPEAK = CssProp.reg(CssProp.AP.speak);
315 static SPEAK_HEADER = CssProp.reg(CssProp.AP.speak_header);
316 static SPEAK_NUMERAL = CssProp.reg(CssProp.AP.speak_numeral);
317 static SPEAK_PUNCTUATION = CssProp.reg(CssProp.AP.speak_punctuation);
318 static TABLE_LAYOUT = CssProp.reg(CssProp.AP.table_layout);
319 static TEXT_ALIGN = CssProp.reg(CssProp.AP.text_align);
320 static TEXT_DECORATION = CssProp.reg(CssProp.AP.text_decoration);
321 static TEXT_TRANSFORM = CssProp.reg(CssProp.AP.text_transform);
322 static TEXT_WRAP = CssProp.reg(CssProp.AP.text_wrap);
323 static UNICODE_BIDI = CssProp.reg(CssProp.AP.unicode_bidi);
324 static VISIBILITY = CssProp.reg(CssProp.AP.visibility);
325 static WHITE_SPACE = CssProp.reg(CssProp.AP.white_space);
326 static WORD_BREAK = CssProp.reg(CssProp.AP.word_break);
327
328 static BACKGROUND_ATTACHMENT = CssProp.reg(CssProp.CP.background_attachment);
329 static BACKGROUND_COLOR = CssProp.reg(CssProp.CP.background_color);
330 static BACKGROUND_ORIGIN = CssProp.reg(CssProp.CP.background_origin);
331 static BACKGROUND_REPEAT = CssProp.reg(CssProp.CP.background_repeat);
332 static BORDER = CssProp.reg(CssProp.CP.border);
333 static BORDER_RADIUS = CssProp.reg(CssProp.CP.border_radius);
334 static BORDER_SPACING = CssProp.reg(CssProp.CP.border_spacing);
335 static BORDER_TOP_COLOR = CssProp.reg(CssProp.CP.border_top_color);
336 static BORDER_TOP_STYLE = CssProp.reg(CssProp.CP.border_top_style);
337 static BORDER_WIDTH = CssProp.reg(CssProp.CP.border_width);
338 static COLOR = CssProp.reg(CssProp.CP.color);
339 static CURSOR = CssProp.reg(CssProp.CP.cursor);
340 static DISPLAY = CssProp.reg(CssProp.CP.display);
341 static DISPLAY_OUTSIDE = CssProp.reg(CssProp.CP.display_outside);
342 static ELEVATION = CssProp.reg(CssProp.CP.elevation);
343 static FONT_FAMILY = CssProp.reg(CssProp.CP.font_family);
344 static HEIGHT = CssProp.reg(CssProp.CP.height);
345 static LETTER_SPACING = CssProp.reg(CssProp.CP.letter_spacing);
346 static LIST_STYLE_IMAGE = CssProp.reg(CssProp.CP.list_style_image);
347 static MARGIN_RIGHT = CssProp.reg(CssProp.CP.margin_right);
348 static MAX_HEIGHT = CssProp.reg(CssProp.CP.max_height);
349 static MIN_HEIGHT = CssProp.reg(CssProp.CP.min_height);
350 static OPACITY = CssProp.reg(CssProp.CP.opacity);
351 static OUTLINE_COLOR = CssProp.reg(CssProp.CP.outline_color);
352 static OUTLINE_WIDTH = CssProp.reg(CssProp.CP.outline_width);
353 static PADDING = CssProp.reg(CssProp.CP.padding);
354 static PADDING_TOP = CssProp.reg(CssProp.CP.padding_top);
355 static PITCH_RANGE = CssProp.reg(CssProp.CP.pitch_range);
356 static RIGHT = CssProp.reg(CssProp.CP.right);
357 static STRESS = CssProp.reg(CssProp.CP.stress);
358 static TEXT_INDENT = CssProp.reg(CssProp.CP.text_indent);
359 static TEXT_SHADOW = CssProp.reg(CssProp.CP.text_shadow);
360 static VOLUME = CssProp.reg(CssProp.CP.volume);
361 static WORD_WRAP = CssProp.reg(CssProp.CP.word_wrap);
362 static ZOOM = CssProp.reg(CssProp.CP.zoom);
363 static BACKFACE_VISIBILITY = CssProp.reg(CssProp.CP.backface_visibility);
364 static BACKGROUND_CLIP = CssProp.reg(CssProp.CP.background_clip);
365 static BACKGROUND_POSITION = CssProp.reg(CssProp.CP.background_position);
366 static BORDER_BOTTOM_COLOR = CssProp.reg(CssProp.CP.border_bottom_color);
367 static BORDER_BOTTOM_STYLE = CssProp.reg(CssProp.CP.border_bottom_style);
368 static BORDER_COLOR = CssProp.reg(CssProp.CP.border_color);
369 static BORDER_LEFT_COLOR = CssProp.reg(CssProp.CP.border_left_color);
370 static BORDER_RIGHT_COLOR = CssProp.reg(CssProp.CP.border_right_color);
371 static BORDER_STYLE = CssProp.reg(CssProp.CP.border_style);
372 static BORDER_TOP_LEFT_RADIUS = CssProp.reg(
373 CssProp.CP.border_top_left_radius
374 );
375 static BORDER_TOP_WIDTH = CssProp.reg(CssProp.CP.border_top_width);
376 static BOX_SHADOW = CssProp.reg(CssProp.CP.box_shadow);
377 static CLIP = CssProp.reg(CssProp.CP.clip);
378 static DISPLAY_INSIDE = CssProp.reg(CssProp.CP.display_inside);
379 static FONT_SIZE = CssProp.reg(CssProp.CP.font_size);
380 static LINE_HEIGHT = CssProp.reg(CssProp.CP.line_height);
381 static MARGIN_LEFT = CssProp.reg(CssProp.CP.margin_left);
382 static MAX_WIDTH = CssProp.reg(CssProp.CP.max_width);
383 static OUTLINE_STYLE = CssProp.reg(CssProp.CP.outline_style);
384 static PADDING_BOTTOM = CssProp.reg(CssProp.CP.padding_bottom);
385 static PADDING_RIGHT = CssProp.reg(CssProp.CP.padding_right);
386 static PERSPECTIVE = CssProp.reg(CssProp.CP.perspective);
387 static RICHNESS = CssProp.reg(CssProp.CP.richness);
388 static TEXT_OVERFLOW = CssProp.reg(CssProp.CP.text_overflow);
389 static TOP = CssProp.reg(CssProp.CP.top);
390 static WIDTH = CssProp.reg(CssProp.CP.width);
391 static Z_INDEX = CssProp.reg(CssProp.CP.z_index);
392 static BACKGROUND = CssProp.reg(CssProp.CP.background);
393 static BACKGROUND_SIZE = CssProp.reg(CssProp.CP.background_size);
394 static BORDER_BOTTOM_LEFT_RADIUS = CssProp.reg(
395 CssProp.CP.border_bottom_left_radius
396 );
397 static BORDER_BOTTOM_WIDTH = CssProp.reg(CssProp.CP.border_bottom_width);
398 static BORDER_LEFT_STYLE = CssProp.reg(CssProp.CP.border_left_style);
399 static BORDER_RIGHT_STYLE = CssProp.reg(CssProp.CP.border_right_style);
400 static BORDER_TOP = CssProp.reg(CssProp.CP.border_top);
401 static BOTTOM = CssProp.reg(CssProp.CP.bottom);
402 static LIST_STYLE = CssProp.reg(CssProp.CP.list_style);
403 static MARGIN_TOP = CssProp.reg(CssProp.CP.margin_top);
404 static OUTLINE = CssProp.reg(CssProp.CP.outline);
405 static OVERFLOW_Y = CssProp.reg(CssProp.CP.overflow_y);
406 static PITCH = CssProp.reg(CssProp.CP.pitch);
407 static VERTICAL_ALIGN = CssProp.reg(CssProp.CP.vertical_align);
408 static WORD_SPACING = CssProp.reg(CssProp.CP.word_spacing);
409 static BACKGROUND_IMAGE = CssProp.reg(CssProp.CP.background_image);
410 static BORDER_BOTTOM_RIGHT_RADIUS = CssProp.reg(
411 CssProp.CP.border_bottom_right_radius
412 );
413 static BORDER_LEFT_WIDTH = CssProp.reg(CssProp.CP.border_left_width);
414 static BORDER_RIGHT_WIDTH = CssProp.reg(CssProp.CP.border_right_width);
415 static LEFT = CssProp.reg(CssProp.CP.left);
416 static MARGIN_BOTTOM = CssProp.reg(CssProp.CP.margin_bottom);
417 static PAUSE_AFTER = CssProp.reg(CssProp.CP.pause_after);
418 static SPEECH_RATE = CssProp.reg(CssProp.CP.speech_rate);
419 static TRANSITION_DURATION = CssProp.reg(CssProp.CP.transition_duration);
420 static BORDER_BOTTOM = CssProp.reg(CssProp.CP.border_bottom);
421 static BORDER_RIGHT = CssProp.reg(CssProp.CP.border_right);
422 static MARGIN = CssProp.reg(CssProp.CP.margin);
423 static PADDING_LEFT = CssProp.reg(CssProp.CP.padding_left);
424 static BORDER_LEFT = CssProp.reg(CssProp.CP.border_left);
425 static FONT = CssProp.reg(CssProp.CP.font);
426 static QUOTES = CssProp.reg(CssProp.CP.quotes);
427 static BORDER_TOP_RIGHT_RADIUS = CssProp.reg(
428 CssProp.CP.border_top_right_radius
429 );
430 static MIN_WIDTH = CssProp.reg(CssProp.CP.min_width);
431}
432
433/**
434 * A class to sanitize HTML strings.
435 */
436export class Sanitizer implements IRenderMime.ISanitizer {
437 /**
438 * Sanitize an HTML string.
439 *
440 * @param dirty - The dirty text.
441 *
442 * @param options - The optional sanitization options.
443 *
444 * @returns The sanitized string.
445 */
446 sanitize(dirty: string, options?: IRenderMime.ISanitizerOptions): string {
447 return sanitize(dirty, { ...this._options, ...(options || {}) });
448 }
449
450 /**
451 * @returns Whether to replace URLs by HTML anchors.
452 */
453 getAutolink(): boolean {
454 return this._autolink;
455 }
456
457 /**
458 * Set the allowed schemes
459 *
460 * @param scheme Allowed schemes
461 */
462 setAllowedSchemes(scheme: Array<string>): void {
463 // Force copy of `scheme`
464 this._options.allowedSchemes = [...scheme];
465 }
466
467 /**
468 * Set the URL replacement boolean.
469 *
470 * @param autolink URL replacement boolean.
471 */
472 setAutolink(autolink: boolean): void {
473 this._autolink = autolink;
474 }
475
476 private _autolink: boolean = true;
477
478 private _options: sanitize.IOptions = {
479 // HTML tags that are allowed to be used. Tags were extracted from Google Caja
480 allowedTags: [
481 'a',
482 'abbr',
483 'acronym',
484 'address',
485 'area',
486 'article',
487 'aside',
488 'audio',
489 'b',
490 'bdi',
491 'bdo',
492 'big',
493 'blockquote',
494 'br',
495 'button',
496 'canvas',
497 'caption',
498 'center',
499 'cite',
500 'code',
501 'col',
502 'colgroup',
503 'colspan',
504 'command',
505 'data',
506 'datalist',
507 'dd',
508 'del',
509 'details',
510 'dfn',
511 'dir',
512 'div',
513 'dl',
514 'dt',
515 'em',
516 'fieldset',
517 'figcaption',
518 'figure',
519 'font',
520 'footer',
521 'form',
522 'h1',
523 'h2',
524 'h3',
525 'h4',
526 'h5',
527 'h6',
528 'header',
529 'hgroup',
530 'hr',
531 'i',
532 // 'iframe' is allowed by Google Caja, but disallowed by default by sanitize-html
533 // , 'iframe'
534 'img',
535 'input',
536 'ins',
537 'kbd',
538 'label',
539 'legend',
540 'li',
541 'map',
542 'mark',
543 'menu',
544 'meter',
545 'nav',
546 'nobr',
547 'ol',
548 'optgroup',
549 'option',
550 'output',
551 'p',
552 'pre',
553 'progress',
554 'q',
555 'rowspan',
556 's',
557 'samp',
558 'section',
559 'select',
560 'small',
561 'source',
562 'span',
563 'strike',
564 'strong',
565 'sub',
566 'summary',
567 'sup',
568 'table',
569 'tbody',
570 'td',
571 'textarea',
572 'tfoot',
573 'th',
574 'thead',
575 'time',
576 'tr',
577 'track',
578 'tt',
579 'u',
580 'ul',
581 'var',
582 'video',
583 'wbr'
584 ],
585 // Attributes that HTML tags are allowed to have, extracted from Google Caja.
586 // See https://github.com/jupyterlab/jupyterlab/issues/1812#issuecomment-285848435
587 allowedAttributes: {
588 '*': [
589 'class',
590 'dir',
591 'draggable',
592 'hidden',
593 'id',
594 'inert',
595 'itemprop',
596 'itemref',
597 'itemscope',
598 'lang',
599 'spellcheck',
600 'style',
601 'title',
602 'translate'
603 ],
604 // 'rel' and 'target' were *not* allowed by Google Caja
605 a: [
606 'accesskey',
607 'coords',
608 'href',
609 'hreflang',
610 'name',
611 'rel',
612 'shape',
613 'tabindex',
614 'target',
615 'type'
616 ],
617 area: [
618 'accesskey',
619 'alt',
620 'coords',
621 'href',
622 'nohref',
623 'shape',
624 'tabindex'
625 ],
626 // 'autoplay' was *not* allowed by Google Caja
627 audio: [
628 'autoplay',
629 'controls',
630 'loop',
631 'mediagroup',
632 'muted',
633 'preload',
634 'src'
635 ],
636 bdo: ['dir'],
637 blockquote: ['cite'],
638 br: ['clear'],
639 button: [
640 'accesskey',
641 'data-commandlinker-args',
642 'data-commandlinker-command',
643 'disabled',
644 'name',
645 'tabindex',
646 'type',
647 'value'
648 ],
649 canvas: ['height', 'width'],
650 caption: ['align'],
651 col: ['align', 'char', 'charoff', 'span', 'valign', 'width'],
652 colgroup: ['align', 'char', 'charoff', 'span', 'valign', 'width'],
653 command: [
654 'checked',
655 'command',
656 'disabled',
657 'icon',
658 'label',
659 'radiogroup',
660 'type'
661 ],
662 data: ['value'],
663 del: ['cite', 'datetime'],
664 details: ['open'],
665 dir: ['compact'],
666 div: ['align'],
667 dl: ['compact'],
668 fieldset: ['disabled'],
669 font: ['color', 'face', 'size'],
670 form: [
671 'accept',
672 'autocomplete',
673 'enctype',
674 'method',
675 'name',
676 'novalidate'
677 ],
678 h1: ['align'],
679 h2: ['align'],
680 h3: ['align'],
681 h4: ['align'],
682 h5: ['align'],
683 h6: ['align'],
684 hr: ['align', 'noshade', 'size', 'width'],
685 iframe: [
686 'align',
687 'frameborder',
688 'height',
689 'marginheight',
690 'marginwidth',
691 'width'
692 ],
693 img: [
694 'align',
695 'alt',
696 'border',
697 'height',
698 'hspace',
699 'ismap',
700 'name',
701 'src',
702 'usemap',
703 'vspace',
704 'width'
705 ],
706 input: [
707 'accept',
708 'accesskey',
709 'align',
710 'alt',
711 'autocomplete',
712 'checked',
713 'disabled',
714 'inputmode',
715 'ismap',
716 'list',
717 'max',
718 'maxlength',
719 'min',
720 'multiple',
721 'name',
722 'placeholder',
723 'readonly',
724 'required',
725 'size',
726 'src',
727 'step',
728 'tabindex',
729 'type',
730 'usemap',
731 'value'
732 ],
733 ins: ['cite', 'datetime'],
734 label: ['accesskey', 'for'],
735 legend: ['accesskey', 'align'],
736 li: ['type', 'value'],
737 map: ['name'],
738 menu: ['compact', 'label', 'type'],
739 meter: ['high', 'low', 'max', 'min', 'value'],
740 ol: ['compact', 'reversed', 'start', 'type'],
741 optgroup: ['disabled', 'label'],
742 option: ['disabled', 'label', 'selected', 'value'],
743 output: ['for', 'name'],
744 p: ['align'],
745 pre: ['width'],
746 progress: ['max', 'min', 'value'],
747 q: ['cite'],
748 select: [
749 'autocomplete',
750 'disabled',
751 'multiple',
752 'name',
753 'required',
754 'size',
755 'tabindex'
756 ],
757 source: ['type'],
758 table: [
759 'align',
760 'bgcolor',
761 'border',
762 'cellpadding',
763 'cellspacing',
764 'frame',
765 'rules',
766 'summary',
767 'width'
768 ],
769 tbody: ['align', 'char', 'charoff', 'valign'],
770 td: [
771 'abbr',
772 'align',
773 'axis',
774 'bgcolor',
775 'char',
776 'charoff',
777 'colspan',
778 'headers',
779 'height',
780 'nowrap',
781 'rowspan',
782 'scope',
783 'valign',
784 'width'
785 ],
786 textarea: [
787 'accesskey',
788 'autocomplete',
789 'cols',
790 'disabled',
791 'inputmode',
792 'name',
793 'placeholder',
794 'readonly',
795 'required',
796 'rows',
797 'tabindex',
798 'wrap'
799 ],
800 tfoot: ['align', 'char', 'charoff', 'valign'],
801 th: [
802 'abbr',
803 'align',
804 'axis',
805 'bgcolor',
806 'char',
807 'charoff',
808 'colspan',
809 'headers',
810 'height',
811 'nowrap',
812 'rowspan',
813 'scope',
814 'valign',
815 'width'
816 ],
817 thead: ['align', 'char', 'charoff', 'valign'],
818 tr: ['align', 'bgcolor', 'char', 'charoff', 'valign'],
819 track: ['default', 'kind', 'label', 'srclang'],
820 ul: ['compact', 'type'],
821 video: [
822 'autoplay',
823 'controls',
824 'height',
825 'loop',
826 'mediagroup',
827 'muted',
828 'poster',
829 'preload',
830 'src',
831 'width'
832 ]
833 },
834 // Inline CSS styles that HTML tags may have (and their allowed values)
835 allowedStyles: {
836 // To simplify the data, all styles are allowed on all tags that allow the style attribute
837 '*': {
838 'backface-visibility': [CssProp.BACKFACE_VISIBILITY],
839 background: [CssProp.BACKGROUND],
840 'background-attachment': [CssProp.BACKGROUND_ATTACHMENT],
841 'background-clip': [CssProp.BACKGROUND_CLIP],
842 'background-color': [CssProp.BACKGROUND_COLOR],
843 'background-image': [CssProp.BACKGROUND_IMAGE],
844 'background-origin': [CssProp.BACKGROUND_ORIGIN],
845 'background-position': [CssProp.BACKGROUND_POSITION],
846 'background-repeat': [CssProp.BACKGROUND_REPEAT],
847 'background-size': [CssProp.BACKGROUND_SIZE],
848 border: [CssProp.BORDER],
849 'border-bottom': [CssProp.BORDER_BOTTOM],
850 'border-bottom-color': [CssProp.BORDER_BOTTOM_COLOR],
851 'border-bottom-left-radius': [CssProp.BORDER_BOTTOM_LEFT_RADIUS],
852 'border-bottom-right-radius': [CssProp.BORDER_BOTTOM_RIGHT_RADIUS],
853 'border-bottom-style': [CssProp.BORDER_BOTTOM_STYLE],
854 'border-bottom-width': [CssProp.BORDER_BOTTOM_WIDTH],
855 'border-collapse': [CssProp.BORDER_COLLAPSE],
856 'border-color': [CssProp.BORDER_COLOR],
857 'border-left': [CssProp.BORDER_LEFT],
858 'border-left-color': [CssProp.BORDER_LEFT_COLOR],
859 'border-left-style': [CssProp.BORDER_LEFT_STYLE],
860 'border-left-width': [CssProp.BORDER_LEFT_WIDTH],
861 'border-radius': [CssProp.BORDER_RADIUS],
862 'border-right': [CssProp.BORDER_RIGHT],
863 'border-right-color': [CssProp.BORDER_RIGHT_COLOR],
864 'border-right-style': [CssProp.BORDER_RIGHT_STYLE],
865 'border-right-width': [CssProp.BORDER_RIGHT_WIDTH],
866 'border-spacing': [CssProp.BORDER_SPACING],
867 'border-style': [CssProp.BORDER_STYLE],
868 'border-top': [CssProp.BORDER_TOP],
869 'border-top-color': [CssProp.BORDER_TOP_COLOR],
870 'border-top-left-radius': [CssProp.BORDER_TOP_LEFT_RADIUS],
871 'border-top-right-radius': [CssProp.BORDER_TOP_RIGHT_RADIUS],
872 'border-top-style': [CssProp.BORDER_TOP_STYLE],
873 'border-top-width': [CssProp.BORDER_TOP_WIDTH],
874 'border-width': [CssProp.BORDER_WIDTH],
875 bottom: [CssProp.BOTTOM],
876 box: [CssProp.BOX],
877 'box-shadow': [CssProp.BOX_SHADOW],
878 'box-sizing': [CssProp.BOX_SIZING],
879 'caption-side': [CssProp.CAPTION_SIDE],
880 clear: [CssProp.CLEAR],
881 clip: [CssProp.CLIP],
882 color: [CssProp.COLOR],
883 cursor: [CssProp.CURSOR],
884 direction: [CssProp.DIRECTION],
885 display: [CssProp.DISPLAY],
886 'display-inside': [CssProp.DISPLAY_INSIDE],
887 'display-outside': [CssProp.DISPLAY_OUTSIDE],
888 elevation: [CssProp.ELEVATION],
889 'empty-cells': [CssProp.EMPTY_CELLS],
890 float: [CssProp.FLOAT],
891 font: [CssProp.FONT],
892 'font-family': [CssProp.FONT_FAMILY],
893 'font-size': [CssProp.FONT_SIZE],
894 'font-stretch': [CssProp.FONT_STRETCH],
895 'font-style': [CssProp.FONT_STYLE],
896 'font-variant': [CssProp.FONT_VARIANT],
897 'font-weight': [CssProp.FONT_WEIGHT],
898 height: [CssProp.HEIGHT],
899 left: [CssProp.LEFT],
900 'letter-spacing': [CssProp.LETTER_SPACING],
901 'line-height': [CssProp.LINE_HEIGHT],
902 'list-style': [CssProp.LIST_STYLE],
903 'list-style-image': [CssProp.LIST_STYLE_IMAGE],
904 'list-style-position': [CssProp.LIST_STYLE_POSITION],
905 'list-style-type': [CssProp.LIST_STYLE_TYPE],
906 margin: [CssProp.MARGIN],
907 'margin-bottom': [CssProp.MARGIN_BOTTOM],
908 'margin-left': [CssProp.MARGIN_LEFT],
909 'margin-right': [CssProp.MARGIN_RIGHT],
910 'margin-top': [CssProp.MARGIN_TOP],
911 'max-height': [CssProp.MAX_HEIGHT],
912 'max-width': [CssProp.MAX_WIDTH],
913 'min-height': [CssProp.MIN_HEIGHT],
914 'min-width': [CssProp.MIN_WIDTH],
915 opacity: [CssProp.OPACITY],
916 outline: [CssProp.OUTLINE],
917 'outline-color': [CssProp.OUTLINE_COLOR],
918 'outline-style': [CssProp.OUTLINE_STYLE],
919 'outline-width': [CssProp.OUTLINE_WIDTH],
920 overflow: [CssProp.OVERFLOW],
921 'overflow-wrap': [CssProp.OVERFLOW_WRAP],
922 'overflow-x': [CssProp.OVERFLOW_X],
923 'overflow-y': [CssProp.OVERFLOW_Y],
924 padding: [CssProp.PADDING],
925 'padding-bottom': [CssProp.PADDING_BOTTOM],
926 'padding-left': [CssProp.PADDING_LEFT],
927 'padding-right': [CssProp.PADDING_RIGHT],
928 'padding-top': [CssProp.PADDING_TOP],
929 'page-break-after': [CssProp.PAGE_BREAK_AFTER],
930 'page-break-before': [CssProp.PAGE_BREAK_BEFORE],
931 'page-break-inside': [CssProp.PAGE_BREAK_INSIDE],
932 'pause-after': [CssProp.PAUSE_AFTER],
933 perspective: [CssProp.PERSPECTIVE],
934 pitch: [CssProp.PITCH],
935 'pitch-range': [CssProp.PITCH_RANGE],
936 position: [CssProp.POSITION],
937 quotes: [CssProp.QUOTES],
938 resize: [CssProp.RESIZE],
939 richness: [CssProp.RICHNESS],
940 right: [CssProp.RIGHT],
941 speak: [CssProp.SPEAK],
942 'speak-header': [CssProp.SPEAK_HEADER],
943 'speak-numeral': [CssProp.SPEAK_NUMERAL],
944 'speak-punctuation': [CssProp.SPEAK_PUNCTUATION],
945 'speech-rate': [CssProp.SPEECH_RATE],
946 stress: [CssProp.STRESS],
947 'table-layout': [CssProp.TABLE_LAYOUT],
948 'text-align': [CssProp.TEXT_ALIGN],
949 'text-decoration': [CssProp.TEXT_DECORATION],
950 'text-indent': [CssProp.TEXT_INDENT],
951 'text-overflow': [CssProp.TEXT_OVERFLOW],
952 'text-shadow': [CssProp.TEXT_SHADOW],
953 'text-transform': [CssProp.TEXT_TRANSFORM],
954 'text-wrap': [CssProp.TEXT_WRAP],
955 top: [CssProp.TOP],
956 'unicode-bidi': [CssProp.UNICODE_BIDI],
957 'vertical-align': [CssProp.VERTICAL_ALIGN],
958 visibility: [CssProp.VISIBILITY],
959 volume: [CssProp.VOLUME],
960 'white-space': [CssProp.WHITE_SPACE],
961 width: [CssProp.WIDTH],
962 'word-break': [CssProp.WORD_BREAK],
963 'word-spacing': [CssProp.WORD_SPACING],
964 'word-wrap': [CssProp.WORD_WRAP],
965 'z-index': [CssProp.Z_INDEX],
966 zoom: [CssProp.ZOOM]
967 }
968 },
969 transformTags: {
970 // Set the "rel" attribute for <a> tags to "nofollow".
971 a: sanitize.simpleTransform('a', { rel: 'nofollow' }),
972 // Set the "disabled" attribute for <input> tags.
973 input: sanitize.simpleTransform('input', { disabled: 'disabled' })
974 },
975 allowedSchemes: [...sanitize.defaults.allowedSchemes],
976 allowedSchemesByTag: {
977 // Allow 'attachment:' img src (used for markdown cell attachments).
978 img: sanitize.defaults.allowedSchemes.concat(['attachment'])
979 },
980 // Override of the default option, so we can skip 'src' attribute validation.
981 // 'src' Attributes are validated to be URIs, which does not allow for embedded (image) data.
982 // Since embedded data is no longer deemed to be a threat, validation can be skipped.
983 // See https://github.com/jupyterlab/jupyterlab/issues/5183
984 allowedSchemesAppliedToAttributes: ['href', 'cite']
985 };
986}