@teleporthq/teleport-plugin-css 0.38.0-alpha.0 → 0.38.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/src/index.ts CHANGED
@@ -12,6 +12,8 @@ import {
12
12
  UIDLElementNodeReferenceStyles,
13
13
  UIDLStyleMediaQueryScreenSizeCondition,
14
14
  PluginCSS,
15
+ UIDLElement,
16
+ UIDLElementNode,
15
17
  } from '@teleporthq/teleport-types'
16
18
  import { createStyleSheetPlugin } from './style-sheet'
17
19
 
@@ -21,7 +23,6 @@ interface CSSPluginConfig {
21
23
  componentDecoratorChunkName: string
22
24
  inlineStyleAttributeKey: string // style vs :style vs ...
23
25
  classAttributeName: string // class vs className
24
- forceScoping: boolean // class names get the component name prefix
25
26
  templateStyle: 'html' | 'jsx'
26
27
  declareDependency: 'import' | 'decorator' | 'none'
27
28
  dynamicVariantPrefix?: string
@@ -37,7 +38,6 @@ const createCSSPlugin: ComponentPluginFactory<CSSPluginConfig> = (config) => {
37
38
  classAttributeName = 'class',
38
39
  templateStyle = 'html',
39
40
  declareDependency = 'none',
40
- forceScoping = false,
41
41
  dynamicVariantPrefix,
42
42
  staticPropReferences = false,
43
43
  } = config || {}
@@ -71,7 +71,7 @@ const createCSSPlugin: ComponentPluginFactory<CSSPluginConfig> = (config) => {
71
71
  (chunk) => chunk.name === componentDecoratorChunkName
72
72
  )
73
73
 
74
- const templateLookup = templateChunk.meta.nodesLookup as Record<
74
+ const jsxNodesLookup = templateChunk.meta.nodesLookup as Record<
75
75
  string,
76
76
  HastNode | types.JSXElement
77
77
  >
@@ -86,27 +86,33 @@ const createCSSPlugin: ComponentPluginFactory<CSSPluginConfig> = (config) => {
86
86
  Array<{ [x: string]: Record<string, string | number> }>
87
87
  > = {}
88
88
 
89
- UIDLUtils.traverseElements(node, (element) => {
89
+ const generateStylesForElementNode = (element: UIDLElement) => {
90
90
  const classNamesToAppend: Set<string> = new Set()
91
91
  const dynamicVariantsToAppend: Set<string> = new Set()
92
92
  const {
93
93
  style = {},
94
94
  key,
95
95
  referencedStyles = {},
96
- dependency,
97
96
  attrs = {},
98
97
  elementType,
98
+ dependency,
99
99
  } = element
100
- const elementClassName = StringUtils.camelCaseToDashCase(key)
101
100
 
102
- if (forceScoping && dependency?.type === 'local') {
101
+ const root = jsxNodesLookup[key]
102
+ if (!root) {
103
+ return
104
+ }
105
+
106
+ // Refer to line 323 all component scoped styles are appended with component name by default
107
+ if (dependency?.type === 'local') {
103
108
  StyleBuilders.setPropValueForCompStyle({
104
109
  attrs,
105
- key,
106
- jsxNodesLookup: templateLookup,
110
+ root,
107
111
  templateStyle,
112
+ // elementType is used here in-order to target the component name that the class is actually defined.
113
+ // Here we are appendigng to the node where the component is being called.
108
114
  getClassName: (styleName: string) =>
109
- getClassName(forceScoping, StringUtils.camelCaseToDashCase(elementType), styleName),
115
+ StringUtils.camelCaseToDashCase(elementType + styleName),
110
116
  })
111
117
  }
112
118
 
@@ -118,12 +124,7 @@ const createCSSPlugin: ComponentPluginFactory<CSSPluginConfig> = (config) => {
118
124
  return
119
125
  }
120
126
 
121
- const root = templateLookup[key]
122
- if (!root) {
123
- throw new PluginCSS(`Node - ${key} is missing from the template chunk`)
124
- }
125
-
126
- const className = getClassName(forceScoping, uidl.name, elementClassName)
127
+ const className = StringUtils.camelCaseToDashCase(key)
127
128
 
128
129
  const { staticStyles, dynamicStyles, tokenStyles } =
129
130
  UIDLUtils.splitDynamicAndStaticStyles(style)
@@ -206,24 +207,21 @@ const createCSSPlugin: ComponentPluginFactory<CSSPluginConfig> = (config) => {
206
207
  propDefinitions[styleRef.content.content.content.id]?.defaultValue
207
208
 
208
209
  if (defaultPropValue) {
209
- /* Changing the default value of the prop.
210
- When forceScoping is enabled the classnames change. So, we need to change the default prop too. */
211
- propDefinitions[styleRef.content.content.content.id].defaultValue = getClassName(
212
- forceScoping,
213
- uidl.name,
214
- String(defaultPropValue)
215
- )
210
+ propDefinitions[styleRef.content.content.content.id].defaultValue =
211
+ StringUtils.camelCaseToDashCase(String(defaultPropValue))
216
212
  }
217
213
 
214
+ // staticPropReferences flag is only used for just html-code generation.
215
+ // This is used to append the class name to the node where the component is being called.
216
+ // Instead of how frameworks handle them using props at runtime. This makes the props
217
+ // to behave statically during the generation time instead by appending them directly.
218
218
  if (staticPropReferences) {
219
- if (!defaultPropValue) {
219
+ if (defaultPropValue === undefined || typeof defaultPropValue !== 'string') {
220
220
  return
221
221
  }
222
- if (staticPropReferences) {
223
- classNamesToAppend.add(
224
- getClassName(forceScoping, uidl.name, String(defaultPropValue))
225
- )
226
- }
222
+ classNamesToAppend.add(
223
+ StringUtils.camelCaseToDashCase(uidl.name + defaultPropValue)
224
+ )
227
225
  } else {
228
226
  dynamicVariantsToAppend.add(styleRef.content.content.content.id)
229
227
  }
@@ -239,7 +237,7 @@ const createCSSPlugin: ComponentPluginFactory<CSSPluginConfig> = (config) => {
239
237
  )
240
238
  }
241
239
  classNamesToAppend.add(
242
- getClassName(forceScoping, uidl.name, String(styleRef.content.content.content.id))
240
+ StringUtils.camelCaseToDashCase(uidl.name + styleRef.content.content.content.id)
243
241
  )
244
242
  }
245
243
 
@@ -300,14 +298,26 @@ const createCSSPlugin: ComponentPluginFactory<CSSPluginConfig> = (config) => {
300
298
  })
301
299
  )
302
300
  }
303
- })
301
+ }
302
+
303
+ UIDLUtils.traverseElements(node, generateStylesForElementNode)
304
+ for (const prop of Object.values(propDefinitions)) {
305
+ if (prop.type === 'element' && prop.defaultValue) {
306
+ UIDLUtils.traverseElements(
307
+ prop.defaultValue as UIDLElementNode,
308
+ generateStylesForElementNode
309
+ )
310
+ }
311
+ }
304
312
 
305
313
  if (Object.keys(componentStyleSet).length > 0) {
306
314
  StyleBuilders.generateStylesFromStyleSetDefinitions(
307
315
  componentStyleSet,
308
316
  cssMap,
309
317
  mediaStylesMap,
310
- (styleName: string) => getClassName(forceScoping, uidl.name, styleName)
318
+ (styleName: string) => {
319
+ return StringUtils.camelCaseToDashCase(uidl.name + styleName)
320
+ }
311
321
  )
312
322
  }
313
323
 
@@ -348,7 +358,7 @@ const createCSSPlugin: ComponentPluginFactory<CSSPluginConfig> = (config) => {
348
358
  type: ChunkType.STRING,
349
359
  name: chunkName,
350
360
  fileType: FileType.CSS,
351
- content: cssMap.join('\n'),
361
+ content: cssMap.join('\n \n'),
352
362
  linkAfter: [],
353
363
  })
354
364
  }
@@ -370,9 +380,3 @@ const createDynamicInlineStyle = (styles: UIDLStyleDefinitions) => {
370
380
  })
371
381
  .join(', ')
372
382
  }
373
-
374
- const getClassName = (scoping: boolean, uidlName: string, nodeStyleName: string) => {
375
- return scoping
376
- ? StringUtils.camelCaseToDashCase(`${uidlName}-${nodeStyleName}`)
377
- : StringUtils.camelCaseToDashCase(nodeStyleName)
378
- }
@@ -5,22 +5,42 @@ import {
5
5
  ChunkType,
6
6
  FileType,
7
7
  } from '@teleporthq/teleport-types'
8
+ import { join, relative } from 'path'
8
9
 
9
10
  interface StyleSheetPlugin {
10
11
  fileName?: string
12
+ /*
13
+ Frameworks with dev servers don't need relative path mapping.
14
+ */
15
+ relativeFontPath?: boolean
11
16
  }
12
17
 
13
18
  export const createStyleSheetPlugin: ComponentPluginFactory<StyleSheetPlugin> = (config) => {
14
- const { fileName } = config || { fileName: 'style' }
19
+ const { fileName = 'style', relativeFontPath = false } = config || {
20
+ fileName: 'style',
21
+ relativeFontPath: false,
22
+ }
23
+
15
24
  const styleSheetPlugin: ComponentPlugin = async (structure) => {
16
- const { uidl, chunks } = structure
25
+ const {
26
+ uidl,
27
+ chunks,
28
+ options: { assets },
29
+ } = structure
17
30
  const { styleSetDefinitions = {}, designLanguage: { tokens = {} } = {} } = uidl
31
+ const {
32
+ localFonts = [],
33
+ fontsFolder,
34
+ identifier: assetIdentifier,
35
+ } = assets || { localFonts: [] }
18
36
 
19
- if (
20
- (!styleSetDefinitions && !tokens) ||
21
- (Object.keys(styleSetDefinitions).length === 0 && Object.keys(tokens).length === 0)
22
- ) {
23
- return
37
+ const canSkipThePlugin =
38
+ localFonts?.length === 0 &&
39
+ Object.keys(styleSetDefinitions).length === 0 &&
40
+ Object.keys(tokens).length === 0
41
+
42
+ if (canSkipThePlugin) {
43
+ return structure
24
44
  }
25
45
 
26
46
  const cssMap: string[] = []
@@ -29,6 +49,35 @@ export const createStyleSheetPlugin: ComponentPluginFactory<StyleSheetPlugin> =
29
49
  Array<{ [x: string]: Record<string, string | number> }>
30
50
  > = {}
31
51
 
52
+ uidl.outputOptions = uidl.outputOptions || {}
53
+ uidl.outputOptions.styleFileName = fileName
54
+
55
+ if (localFonts.length > 0) {
56
+ localFonts.forEach((font) => {
57
+ const properties = StyleUtils.getContentOfStyleObject(font.properties) as Record<
58
+ string,
59
+ string | number
60
+ >
61
+ const format = properties?.format ? `format('${properties.format}')` : ''
62
+ /* tslint:disable:no-string-literal */
63
+ delete properties['format']
64
+
65
+ const fontPath = relativeFontPath
66
+ ? join(
67
+ relative(join(...(uidl.outputOptions?.folderPath || [])), './'),
68
+ join(fontsFolder || '', font.path)
69
+ )
70
+ : join('/', assetIdentifier || '', 'fonts', font.path)
71
+
72
+ cssMap.push(
73
+ StyleBuilders.createFontDecleration({
74
+ ...properties,
75
+ src: `url("${fontPath}") ${format}`,
76
+ })
77
+ )
78
+ })
79
+ }
80
+
32
81
  if (Object.keys(tokens).length > 0) {
33
82
  cssMap.push(
34
83
  StyleBuilders.createCSSClassWithSelector(
@@ -44,7 +93,7 @@ export const createStyleSheetPlugin: ComponentPluginFactory<StyleSheetPlugin> =
44
93
  styleSetDefinitions,
45
94
  cssMap,
46
95
  mediaStylesMap,
47
- (styleName: string) => styleName
96
+ (styleName) => styleName
48
97
  )
49
98
  }
50
99
 
@@ -54,14 +103,11 @@ export const createStyleSheetPlugin: ComponentPluginFactory<StyleSheetPlugin> =
54
103
  return structure
55
104
  }
56
105
 
57
- uidl.outputOptions = uidl.outputOptions || {}
58
- uidl.outputOptions.styleFileName = fileName
59
-
60
106
  chunks.push({
61
107
  name: fileName,
62
108
  type: ChunkType.STRING,
63
109
  fileType: FileType.CSS,
64
- content: cssMap.join('\n'),
110
+ content: cssMap.join('\n \n'),
65
111
  linkAfter: [],
66
112
  })
67
113