|
|
@@ -1,3 +1,101 @@
|
|
|
+import { makeMap } from 'shared/util'
|
|
|
+
|
|
|
+const isAttr = makeMap(
|
|
|
+ 'accept,accept-charset,accesskey,action,align,alt,async,autocomplete,' +
|
|
|
+ 'autofocus,autoplay,autosave,bgcolor,border,buffered,challenge,charset,' +
|
|
|
+ 'checked,cite,class,code,codebase,color,cols,colspan,content,' +
|
|
|
+ 'contenteditable,contextmenu,controls,coords,data,datetime,default,' +
|
|
|
+ 'defer,dir,dirname,disabled,download,draggable,dropzone,enctype,for,' +
|
|
|
+ 'form,formaction,headers,height,hidden,high,href,hreflang,http-equiv,' +
|
|
|
+ 'icon,id,ismap,itemprop,keytype,kind,label,lang,language,list,loop,low,' +
|
|
|
+ 'manifest,max,maxlength,media,method,GET,POST,min,multiple,email,file,' +
|
|
|
+ 'muted,name,novalidate,open,optimum,pattern,ping,placeholder,poster,' +
|
|
|
+ 'preload,radiogroup,readonly,rel,required,reversed,rows,rowspan,sandbox,' +
|
|
|
+ 'scope,scoped,seamless,selected,shape,size,type,text,password,sizes,span,' +
|
|
|
+ 'spellcheck,src,srcdoc,srclang,srcset,start,step,style,summary,tabindex,' +
|
|
|
+ 'target,title,usemap,value,width,wrap'
|
|
|
+)
|
|
|
+
|
|
|
+const unsafeAttrCharRE = /[>/="'\u0009\u000a\u000c\u0020]/ // eslint-disable-line no-control-regex
|
|
|
+export const isSSRUnsafeAttr = (name: string): boolean => {
|
|
|
+ return unsafeAttrCharRE.test(name)
|
|
|
+}
|
|
|
+
|
|
|
+/* istanbul ignore next */
|
|
|
+const isRenderableAttr = (name: string): boolean => {
|
|
|
+ return (
|
|
|
+ isAttr(name) || name.indexOf('data-') === 0 || name.indexOf('aria-') === 0
|
|
|
+ )
|
|
|
+}
|
|
|
+export { isRenderableAttr }
|
|
|
+
|
|
|
+export const propsToAttrMap = {
|
|
|
+ acceptCharset: 'accept-charset',
|
|
|
+ className: 'class',
|
|
|
+ htmlFor: 'for',
|
|
|
+ httpEquiv: 'http-equiv'
|
|
|
+}
|
|
|
+
|
|
|
+const ESC = {
|
|
|
+ '<': '<',
|
|
|
+ '>': '>',
|
|
|
+ '"': '"',
|
|
|
+ '&': '&'
|
|
|
+}
|
|
|
+
|
|
|
+export function escape(s: string) {
|
|
|
+ return s.replace(/[<>"&]/g, escapeChar)
|
|
|
+}
|
|
|
+
|
|
|
+function escapeChar(a) {
|
|
|
+ return ESC[a] || a
|
|
|
+}
|
|
|
+
|
|
|
+export const noUnitNumericStyleProps = {
|
|
|
+ 'animation-iteration-count': true,
|
|
|
+ 'border-image-outset': true,
|
|
|
+ 'border-image-slice': true,
|
|
|
+ 'border-image-width': true,
|
|
|
+ 'box-flex': true,
|
|
|
+ 'box-flex-group': true,
|
|
|
+ 'box-ordinal-group': true,
|
|
|
+ 'column-count': true,
|
|
|
+ columns: true,
|
|
|
+ flex: true,
|
|
|
+ 'flex-grow': true,
|
|
|
+ 'flex-positive': true,
|
|
|
+ 'flex-shrink': true,
|
|
|
+ 'flex-negative': true,
|
|
|
+ 'flex-order': true,
|
|
|
+ 'grid-row': true,
|
|
|
+ 'grid-row-end': true,
|
|
|
+ 'grid-row-span': true,
|
|
|
+ 'grid-row-start': true,
|
|
|
+ 'grid-column': true,
|
|
|
+ 'grid-column-end': true,
|
|
|
+ 'grid-column-span': true,
|
|
|
+ 'grid-column-start': true,
|
|
|
+ 'font-weight': true,
|
|
|
+ 'line-clamp': true,
|
|
|
+ 'line-height': true,
|
|
|
+ opacity: true,
|
|
|
+ order: true,
|
|
|
+ orphans: true,
|
|
|
+ 'tab-size': true,
|
|
|
+ widows: true,
|
|
|
+ 'z-index': true,
|
|
|
+ zoom: true,
|
|
|
+ // SVG
|
|
|
+ 'fill-opacity': true,
|
|
|
+ 'flood-opacity': true,
|
|
|
+ 'stop-opacity': true,
|
|
|
+ 'stroke-dasharray': true,
|
|
|
+ 'stroke-dashoffset': true,
|
|
|
+ 'stroke-miterlimit': true,
|
|
|
+ 'stroke-opacity': true,
|
|
|
+ 'stroke-width': true
|
|
|
+}
|
|
|
+
|
|
|
export const isJS = (file: string): boolean => /\.js(\?[^.]+)?$/.test(file)
|
|
|
|
|
|
export const isCSS = (file: string): boolean => /\.css(\?[^.]+)?$/.test(file)
|