UNPKG

11.8 kBJavaScriptView Raw
1"use strict";
2
3Object.defineProperty(exports, "__esModule", {
4 value: true
5});
6exports.getPropertyInfo = getPropertyInfo;
7exports.isAttributeNameSafe = isAttributeNameSafe;
8exports.shouldRemoveAttribute = shouldRemoveAttribute;
9exports.shouldIgnoreAttribute = shouldIgnoreAttribute;
10exports.POSITIVE_NUMERIC = exports.NUMERIC = exports.OVERLOADED_BOOLEAN = exports.BOOLEAN = exports.BOOLEANISH_STRING = exports.STRING = exports.RESERVED = exports.VALID_ATTRIBUTE_NAME_REGEX = exports.ATTRIBUTE_NAME_CHAR = exports.ATTRIBUTE_NAME_START_CHAR = exports.ROOT_ATTRIBUTE_NAME = exports.isUnitlessNumber = exports.newlineEatingTags = exports.omittedCloseTags = exports.RESERVED_PROPS = exports.STYLE = void 0;
11
12var _index = require("../../values/index.js");
13
14var _invariant = _interopRequireDefault(require("../../invariant.js"));
15
16function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
17
18/**
19 * Copyright (c) 2017-present, Facebook, Inc.
20 * All rights reserved.
21 *
22 * This source code is licensed under the BSD-style license found in the
23 * LICENSE file in the root directory of this source tree. An additional grant
24 * of patent rights can be found in the PATENTS file in the same directory.
25 */
26// Warning: This code is experimental and might not fully work. There is no guarantee
27// that it is up-to-date with the current react-dom/server logic and there may also be
28// security holes in the string escaping because of this.
29const STYLE = "style";
30exports.STYLE = STYLE;
31const RESERVED_PROPS = new Set(["children", "dangerouslySetInnerHTML", "suppressContentEditableWarning", "suppressHydrationWarning"]);
32exports.RESERVED_PROPS = RESERVED_PROPS;
33const omittedCloseTags = new Set(["area", "base", "br", "col", "embed", "hr", "img", "input", "keygen", "link", "meta", "param", "source", "track", "wbr"]);
34exports.omittedCloseTags = omittedCloseTags;
35const newlineEatingTags = {
36 listing: true,
37 pre: true,
38 textarea: true
39};
40exports.newlineEatingTags = newlineEatingTags;
41const isUnitlessNumber = {
42 animationIterationCount: true,
43 borderImageOutset: true,
44 borderImageSlice: true,
45 borderImageWidth: true,
46 boxFlex: true,
47 boxFlexGroup: true,
48 boxOrdinalGroup: true,
49 columnCount: true,
50 columns: true,
51 flex: true,
52 flexGrow: true,
53 flexPositive: true,
54 flexShrink: true,
55 flexNegative: true,
56 flexOrder: true,
57 gridRow: true,
58 gridRowEnd: true,
59 gridRowSpan: true,
60 gridRowStart: true,
61 gridColumn: true,
62 gridColumnEnd: true,
63 gridColumnSpan: true,
64 gridColumnStart: true,
65 fontWeight: true,
66 lineClamp: true,
67 lineHeight: true,
68 opacity: true,
69 order: true,
70 orphans: true,
71 tabSize: true,
72 widows: true,
73 zIndex: true,
74 zoom: true,
75 // SVG-related properties
76 fillOpacity: true,
77 floodOpacity: true,
78 stopOpacity: true,
79 strokeDasharray: true,
80 strokeDashoffset: true,
81 strokeMiterlimit: true,
82 strokeOpacity: true,
83 strokeWidth: true
84};
85exports.isUnitlessNumber = isUnitlessNumber;
86const prefixes = ["Webkit", "ms", "Moz", "O"];
87const ROOT_ATTRIBUTE_NAME = "data-reactroot";
88/* eslint-disable max-len */
89
90exports.ROOT_ATTRIBUTE_NAME = ROOT_ATTRIBUTE_NAME;
91const ATTRIBUTE_NAME_START_CHAR = ":A-Z_a-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD";
92exports.ATTRIBUTE_NAME_START_CHAR = ATTRIBUTE_NAME_START_CHAR;
93const ATTRIBUTE_NAME_CHAR = ATTRIBUTE_NAME_START_CHAR + "\\-.0-9\\u00B7\\u0300-\\u036F\\u203F-\\u2040";
94exports.ATTRIBUTE_NAME_CHAR = ATTRIBUTE_NAME_CHAR;
95const VALID_ATTRIBUTE_NAME_REGEX = new RegExp("^[" + ATTRIBUTE_NAME_START_CHAR + "][" + ATTRIBUTE_NAME_CHAR + "]*$");
96exports.VALID_ATTRIBUTE_NAME_REGEX = VALID_ATTRIBUTE_NAME_REGEX;
97
98function prefixKey(prefix, key) {
99 return prefix + key.charAt(0).toUpperCase() + key.substring(1);
100}
101
102Object.keys(isUnitlessNumber).forEach(function (prop) {
103 prefixes.forEach(function (prefix) {
104 isUnitlessNumber[prefixKey(prefix, prop)] = isUnitlessNumber[prop];
105 });
106});
107const RESERVED = 0;
108exports.RESERVED = RESERVED;
109const STRING = 1;
110exports.STRING = STRING;
111const BOOLEANISH_STRING = 2;
112exports.BOOLEANISH_STRING = BOOLEANISH_STRING;
113const BOOLEAN = 3;
114exports.BOOLEAN = BOOLEAN;
115const OVERLOADED_BOOLEAN = 4;
116exports.OVERLOADED_BOOLEAN = OVERLOADED_BOOLEAN;
117const NUMERIC = 5;
118exports.NUMERIC = NUMERIC;
119const POSITIVE_NUMERIC = 6;
120exports.POSITIVE_NUMERIC = POSITIVE_NUMERIC;
121const properties = {};
122
123function PropertyInfoRecord(name, type, mustUseProperty, attributeName, attributeNamespace) {
124 this.acceptsBooleans = type === BOOLEANISH_STRING || type === BOOLEAN || type === OVERLOADED_BOOLEAN;
125 this.attributeName = attributeName;
126 this.attributeNamespace = attributeNamespace;
127 this.mustUseProperty = mustUseProperty;
128 this.propertyName = name;
129 this.type = type;
130}
131
132[["acceptCharset", "accept-charset"], ["className", "class"], ["htmlFor", "for"], ["httpEquiv", "http-equiv"]].forEach(([name, attributeName]) => {
133 properties[name] = new PropertyInfoRecord(name, STRING, false, attributeName, null);
134});
135["children", "dangerouslySetInnerHTML", "defaultValue", "defaultChecked", "innerHTML", "suppressContentEditableWarning", "suppressHydrationWarning", "style"].forEach(name => {
136 properties[name] = new PropertyInfoRecord(name, RESERVED, false, name, null);
137});
138["contentEditable", "draggable", "spellCheck", "value"].forEach(name => {
139 properties[name] = new PropertyInfoRecord(name, BOOLEANISH_STRING, false, name.toLowerCase(), null);
140});
141["autoReverse", "externalResourcesRequired", "preserveAlpha"].forEach(name => {
142 properties[name] = new PropertyInfoRecord(name, BOOLEANISH_STRING, false, name, null);
143});
144["allowFullScreen", "async", "autoFocus", "autoPlay", "controls", "default", "defer", "disabled", "formNoValidate", "hidden", "loop", "noModule", "noValidate", "open", "playsInline", "readOnly", "required", "reversed", "scoped", "seamless", "itemScope"].forEach(name => {
145 properties[name] = new PropertyInfoRecord(name, BOOLEAN, false, name.toLowerCase(), null);
146});
147["checked", "multiple", "muted", "selected"].forEach(name => {
148 properties[name] = new PropertyInfoRecord(name, BOOLEAN, true, name.toLowerCase(), null);
149});
150["capture", "download"].forEach(name => {
151 properties[name] = new PropertyInfoRecord(name, OVERLOADED_BOOLEAN, false, name.toLowerCase(), null);
152});
153["cols", "rows", "size", "span"].forEach(name => {
154 properties[name] = new PropertyInfoRecord(name, POSITIVE_NUMERIC, false, name.toLowerCase(), null);
155});
156["rowSpan", "start"].forEach(name => {
157 properties[name] = new PropertyInfoRecord(name, NUMERIC, false, name.toLowerCase(), null);
158});
159const CAMELIZE = /[\-\:]([a-z])/g;
160
161const capitalize = token => token[1].toUpperCase();
162
163["accent-height", "alignment-baseline", "arabic-form", "baseline-shift", "cap-height", "clip-path", "clip-rule", "color-interpolation", "color-interpolation-filters", "color-profile", "color-rendering", "dominant-baseline", "enable-background", "fill-opacity", "fill-rule", "flood-color", "flood-opacity", "font-family", "font-size", "font-size-adjust", "font-stretch", "font-style", "font-variant", "font-weight", "glyph-name", "glyph-orientation-horizontal", "glyph-orientation-vertical", "horiz-adv-x", "horiz-origin-x", "image-rendering", "letter-spacing", "lighting-color", "marker-end", "marker-mid", "marker-start", "overline-position", "overline-thickness", "paint-order", "panose-1", "pointer-events", "rendering-intent", "shape-rendering", "stop-color", "stop-opacity", "strikethrough-position", "strikethrough-thickness", "stroke-dasharray", "stroke-dashoffset", "stroke-linecap", "stroke-linejoin", "stroke-miterlimit", "stroke-opacity", "stroke-width", "text-anchor", "text-decoration", "text-rendering", "underline-position", "underline-thickness", "unicode-bidi", "unicode-range", "units-per-em", "v-alphabetic", "v-hanging", "v-ideographic", "v-mathematical", "vector-effect", "vert-adv-y", "vert-origin-x", "vert-origin-y", "word-spacing", "writing-mode", "xmlns:xlink", "x-height"].forEach(attributeName => {
164 const name = attributeName.replace(CAMELIZE, capitalize);
165 properties[name] = new PropertyInfoRecord(name, STRING, false, attributeName, null);
166});
167["xlink:actuate", "xlink:arcrole", "xlink:href", "xlink:role", "xlink:show", "xlink:title", "xlink:type"].forEach(attributeName => {
168 const name = attributeName.replace(CAMELIZE, capitalize);
169 properties[name] = new PropertyInfoRecord(name, STRING, false, attributeName, "http://www.w3.org/1999/xlink");
170});
171["xml:base", "xml:lang", "xml:space"].forEach(attributeName => {
172 const name = attributeName.replace(CAMELIZE, capitalize);
173 properties[name] = new PropertyInfoRecord(name, STRING, false, attributeName, "http://www.w3.org/XML/1998/namespace");
174});
175properties.tabIndex = new PropertyInfoRecord("tabIndex", STRING, false, "tabindex", null);
176
177function getPropertyInfo(name) {
178 return properties.hasOwnProperty(name) ? properties[name] : null;
179}
180
181const illegalAttributeNameCache = {};
182const validatedAttributeNameCache = {};
183
184function isAttributeNameSafe(attributeName) {
185 if (validatedAttributeNameCache.hasOwnProperty(attributeName)) {
186 return true;
187 }
188
189 if (illegalAttributeNameCache.hasOwnProperty(attributeName)) {
190 return false;
191 }
192
193 if (VALID_ATTRIBUTE_NAME_REGEX.test(attributeName)) {
194 validatedAttributeNameCache[attributeName] = true;
195 return true;
196 }
197
198 illegalAttributeNameCache[attributeName] = true;
199 return false;
200}
201
202function shouldRemoveAttributeWithWarning(name, value, propertyInfo, isCustomComponentTag) {
203 if (propertyInfo !== null && propertyInfo.type === RESERVED) {
204 return false;
205 }
206
207 if (value instanceof _index.FunctionValue || value instanceof _index.SymbolValue) {
208 return true;
209 } else if (value instanceof _index.BooleanValue) {
210 if (isCustomComponentTag) {
211 return false;
212 }
213
214 if (propertyInfo !== null) {
215 return !propertyInfo.acceptsBooleans;
216 } else {
217 const prefix = name.toLowerCase().slice(0, 5);
218 return prefix !== "data-" && prefix !== "aria-";
219 }
220 } else if (value instanceof _index.AbstractValue) {
221 (0, _invariant.default)(false, "TODO");
222 }
223
224 return false;
225}
226
227function shouldRemoveAttribute(realm, name, value, propertyInfo, isCustomComponentTag) {
228 if (value === realm.intrinsics.null || value === realm.intrinsics.undefined) {
229 return true;
230 }
231
232 if (shouldRemoveAttributeWithWarning(name, value, propertyInfo, isCustomComponentTag)) {
233 return true;
234 }
235
236 if (isCustomComponentTag) {
237 return false;
238 }
239
240 if (propertyInfo !== null) {
241 switch (propertyInfo.type) {
242 case BOOLEAN:
243 if (value instanceof _index.BooleanValue) {
244 return !value.value;
245 }
246
247 return (0, _invariant.default)(false, "TODO");
248
249 case OVERLOADED_BOOLEAN:
250 if (value instanceof _index.BooleanValue) {
251 return value.value === false;
252 }
253
254 return (0, _invariant.default)(false, "TODO");
255
256 case NUMERIC:
257 if (value instanceof _index.NumberValue) {
258 return isNaN(value.value);
259 }
260
261 return (0, _invariant.default)(false, "TODO");
262
263 case POSITIVE_NUMERIC:
264 if (value instanceof _index.NumberValue) {
265 return isNaN(value.value) || value.value < 1;
266 }
267
268 return (0, _invariant.default)(false, "TODO");
269
270 default:
271 return false;
272 }
273 }
274
275 return false;
276}
277
278function shouldIgnoreAttribute(name, propertyInfo, isCustomComponentTag) {
279 if (propertyInfo !== null) {
280 return propertyInfo.type === RESERVED;
281 }
282
283 if (isCustomComponentTag) {
284 return false;
285 }
286
287 if (name.length > 2 && (name[0] === "o" || name[0] === "O") && (name[1] === "n" || name[1] === "N")) {
288 return true;
289 }
290
291 return false;
292}
293//# sourceMappingURL=dom-config.js.map
\No newline at end of file