1 | import cssProperties from 'css-properties'
|
2 | import isExpression from 'is-expression'
|
3 | import toCamelCase from 'to-camel-case'
|
4 |
|
5 | const BASIC = /^(CaptureEmail|CaptureFile|CaptureNumber|CapturePhone|CaptureSecure|CaptureText|CaptureTextArea|G|Horizontal|Image|List|Svg|SvgCircle|SvgEllipse|SvgDefs|SvgGroup|SvgLinearGradient|SvgRadialGradient|SvgLine|SvgPath|SvgPolygon|SvgPolyline|SvgRect|SvgSymbol|SvgText|SvgUse|SvgStop|Text|Vertical|FakeProps)$/i
|
6 | const BLOCK = /^([A-Z][a-zA-Z0-9]*)(\s+([A-Z][a-zA-Z0-9]*))?$/
|
7 | const BOOL = /^(false|true)$/i
|
8 | const CAPTURE = /^(CaptureEmail|CaptureFile|CaptureNumber|CapturePhone|CaptureSecure|CaptureText|CaptureTextArea)$/i
|
9 | const CODE_EXPLICIT = /^{.+}$/
|
10 | const CODE_IMPLICIT = /props\./
|
11 | const CODE_DEFAULT = /^props$/
|
12 | const COMMENT = /^#(.+)$/
|
13 | const INTERPOLATED_EXPRESSION = /\${.+}/
|
14 | const FLOAT = /^[0-9]+\.[0-9]+$/
|
15 | const FONTABLE = /^(CaptureEmail|CaptureNumber|CapturePhone|CaptureSecure|CaptureText|CaptureTextArea|Text)$/
|
16 | const INT = /^[0-9]+$/
|
17 | const NOT_GROUP = /^(Image|FakeProps|Text|Proxy|SvgCircle|SvgEllipse|SvgLine|SvgPath|SvgPolygon|SvgPolyline|SvgRect|SvgText|SvgStop)$/i
|
18 | const PROP = /^([a-z][a-zA-Z0-9]*)(\s+(.+))?$/
|
19 | const STYLE = new RegExp(
|
20 | `^(${cssProperties
|
21 | .map(toCamelCase)
|
22 | .join(
|
23 | '|'
|
24 | )}|pointerEvents|clipPath|appRegion|userSelect|hyphens|overflowWrap)$`
|
25 | )
|
26 | const TEMPLATE_LITERAL = /^`.+`$/
|
27 | const TRUE = /^true$/i
|
28 | const USER_COMMENT = /^##(.*)$/
|
29 |
|
30 | export const is = (thing, line) => thing.test(line)
|
31 | export const isBasic = line => is(BASIC, line)
|
32 | export const isBlock = line => is(BLOCK, line)
|
33 | export const isBool = line => is(BOOL, line)
|
34 | export const isCapture = line => is(CAPTURE, line)
|
35 | export const isCode = line =>
|
36 | is(CODE_EXPLICIT, line) || is(CODE_IMPLICIT, line) || isCodeDefault(line)
|
37 | export const isCodeDefault = line => is(CODE_DEFAULT, line)
|
38 | export const isValidCode = rcode => {
|
39 | try {
|
40 | let code = rcode
|
41 | if (isInterpolatedExpression(code) && !isTemplateLiteral(code)) {
|
42 | code = `\`${code}\``
|
43 | }
|
44 |
|
45 | new Function('props', 'state', 'event', code)({}, {}, {})
|
46 | return isExpression(code, { strict: true })
|
47 | } catch (error) {
|
48 | return false
|
49 | }
|
50 | }
|
51 | export const isComment = line => is(COMMENT, line)
|
52 | export const isEmptyList = line => line === 'is empty list'
|
53 | export const isEmptyText = line => line === ''
|
54 | export const isEnd = line => line === ''
|
55 | export const isInterpolatedExpression = line =>
|
56 | is(INTERPOLATED_EXPRESSION, line)
|
57 | export const isFloat = line => is(FLOAT, line)
|
58 | export const isFontable = line => is(FONTABLE, line)
|
59 | export const isGroup = line => !is(NOT_GROUP, line) && !isCapture(line)
|
60 | export const isList = line => line === 'List'
|
61 | export const isInt = line => is(INT, line)
|
62 | export const isProp = line => is(PROP, line)
|
63 | export const isTemplateLiteral = line => is(TEMPLATE_LITERAL, line)
|
64 | export const isStyle = line => is(STYLE, line)
|
65 | export const isTrue = line => is(TRUE, line)
|
66 | export const isUserComment = line => is(USER_COMMENT, line)
|
67 |
|
68 | const get = (regex, line) => line.match(regex)
|
69 |
|
70 | export const getBlock = line => {
|
71 |
|
72 | const [_, is, _1, block] = get(BLOCK, line)
|
73 | return {
|
74 | block: block || is,
|
75 | is: block ? is : null,
|
76 | }
|
77 | }
|
78 | export const getCodeData = line =>
|
79 | line
|
80 | .replace(/^{/, '')
|
81 | .replace(/}$/, '')
|
82 | .split(' ')
|
83 | .filter(l => /[.[]/.test(l))
|
84 | export const getComment = line => {
|
85 | try {
|
86 | return get(COMMENT, line).slice(1)
|
87 | } catch (err) {
|
88 | return ''
|
89 | }
|
90 | }
|
91 | export const getMainFont = line =>
|
92 | line ? line.split(',')[0].replace(/['"]/g, '') : ''
|
93 | export const getProp = line => {
|
94 |
|
95 | let [_, prop, _1, value = ''] = get(PROP, line)
|
96 | if (isCodeDefault(value)) {
|
97 | value = `props.${prop}`
|
98 | }
|
99 | return [prop, value]
|
100 | }
|
101 | export const getValue = value => {
|
102 | if (isFloat(value)) {
|
103 | return parseFloat(value, 10)
|
104 | } else if (isInt(value)) {
|
105 | return parseInt(value, 10)
|
106 | } else if (isEmptyText(value)) {
|
107 | return ''
|
108 | } else if (isBool(value)) {
|
109 | return isTrue(value)
|
110 | } else if (isInterpolatedExpression(value)) {
|
111 | return fixBackticks(value)
|
112 | } else {
|
113 | return value
|
114 | }
|
115 | }
|
116 |
|
117 | export const fixBackticks = value =>
|
118 | isTemplateLiteral(value) ? value : `\`${value}\``
|
119 |
|
120 | export const warn = (message, block) => {
|
121 | if (!Array.isArray(block.warnings)) {
|
122 | block.warnings = []
|
123 | }
|
124 | block.warnings.push(message)
|
125 | }
|
126 |
|
127 | const SYSTEM_SCOPES = [
|
128 | 'active',
|
129 |
|
130 | 'disabled',
|
131 | 'focus',
|
132 | 'hover',
|
133 | 'placeholder',
|
134 | 'print',
|
135 |
|
136 | ]
|
137 | export const isSystemScope = name => SYSTEM_SCOPES.includes(name)
|