unframer 2.7.6 → 2.7.8

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.
Files changed (78) hide show
  1. package/README.md +5 -6
  2. package/dist/babel-plugin-imports.d.ts +21 -0
  3. package/dist/babel-plugin-imports.d.ts.map +1 -0
  4. package/dist/babel-plugin-imports.js +375 -0
  5. package/dist/babel-plugin-imports.js.map +1 -0
  6. package/dist/cli.d.ts +14 -0
  7. package/dist/cli.d.ts.map +1 -1
  8. package/dist/cli.js +9 -42
  9. package/dist/cli.js.map +1 -1
  10. package/dist/css.d.ts.map +1 -1
  11. package/dist/css.js +4 -3
  12. package/dist/css.js.map +1 -1
  13. package/dist/esbuild.d.ts +7 -0
  14. package/dist/esbuild.d.ts.map +1 -1
  15. package/dist/esbuild.js +15 -1
  16. package/dist/esbuild.js.map +1 -1
  17. package/dist/exporter.d.ts +6 -14
  18. package/dist/exporter.d.ts.map +1 -1
  19. package/dist/exporter.js +79 -38
  20. package/dist/exporter.js.map +1 -1
  21. package/dist/exporter.test.js +48 -0
  22. package/dist/exporter.test.js.map +1 -1
  23. package/dist/framer.d.ts.map +1 -1
  24. package/dist/framer.js +26 -1788
  25. package/dist/framer.js.map +1 -1
  26. package/dist/index.d.ts.map +1 -1
  27. package/dist/index.js.map +1 -1
  28. package/dist/renamer.d.ts +12 -0
  29. package/dist/renamer.d.ts.map +1 -0
  30. package/dist/renamer.js +169 -0
  31. package/dist/renamer.js.map +1 -0
  32. package/dist/unframer-loader.d.ts.map +1 -1
  33. package/dist/unframer-loader.js +4 -3
  34. package/dist/unframer-loader.js.map +1 -1
  35. package/esm/babel-plugin-imports.d.ts +21 -0
  36. package/esm/babel-plugin-imports.d.ts.map +1 -0
  37. package/esm/babel-plugin-imports.js +344 -0
  38. package/esm/babel-plugin-imports.js.map +1 -0
  39. package/esm/cli.d.ts +14 -0
  40. package/esm/cli.d.ts.map +1 -1
  41. package/esm/cli.js +9 -42
  42. package/esm/cli.js.map +1 -1
  43. package/esm/css.d.ts.map +1 -1
  44. package/esm/css.js +3 -2
  45. package/esm/css.js.map +1 -1
  46. package/esm/esbuild.d.ts +7 -0
  47. package/esm/esbuild.d.ts.map +1 -1
  48. package/esm/esbuild.js +13 -0
  49. package/esm/esbuild.js.map +1 -1
  50. package/esm/exporter.d.ts +6 -14
  51. package/esm/exporter.d.ts.map +1 -1
  52. package/esm/exporter.js +78 -37
  53. package/esm/exporter.js.map +1 -1
  54. package/esm/exporter.test.js +48 -0
  55. package/esm/exporter.test.js.map +1 -1
  56. package/esm/framer.d.ts.map +1 -1
  57. package/esm/framer.js +27 -1788
  58. package/esm/framer.js.map +1 -1
  59. package/esm/index.d.ts.map +1 -1
  60. package/esm/index.js.map +1 -1
  61. package/esm/renamer.d.ts +12 -0
  62. package/esm/renamer.d.ts.map +1 -0
  63. package/esm/renamer.js +140 -0
  64. package/esm/renamer.js.map +1 -0
  65. package/esm/unframer-loader.d.ts.map +1 -1
  66. package/esm/unframer-loader.js +4 -3
  67. package/esm/unframer-loader.js.map +1 -1
  68. package/package.json +6 -4
  69. package/src/babel-plugin-imports.ts +441 -0
  70. package/src/cli.tsx +11 -52
  71. package/src/css.ts +3 -2
  72. package/src/esbuild.ts +24 -2
  73. package/src/exporter.test.ts +66 -0
  74. package/src/exporter.ts +95 -42
  75. package/src/framer.js +25 -1827
  76. package/src/index.ts +2 -0
  77. package/src/renamer.ts +184 -0
  78. package/src/unframer-loader.ts +7 -3
package/src/exporter.ts CHANGED
@@ -1,4 +1,10 @@
1
1
  import { BuildResult, context } from 'esbuild'
2
+ import {
3
+ babelPluginDeduplicateImports,
4
+ babelPluginJsxTransform,
5
+ } from './babel-plugin-imports.js'
6
+
7
+ import { Config } from './cli'
2
8
  import url from 'url'
3
9
 
4
10
  import { Sema } from 'async-sema'
@@ -7,7 +13,7 @@ import dprint from 'dprint-node'
7
13
  import { nodeModulesPolyfillPlugin } from 'esbuild-plugins-node-modules-polyfill'
8
14
 
9
15
  import { exec } from 'child_process'
10
- import dedent from 'dedent'
16
+ import dedent from 'string-dedent'
11
17
  import fs from 'fs'
12
18
  import path from 'path'
13
19
  import {
@@ -21,6 +27,7 @@ import {
21
27
  import {
22
28
  esbuildPluginBundleDependencies,
23
29
  externalPackages,
30
+ replaceWebPageIds,
24
31
  resolveRedirect,
25
32
  } from './esbuild'
26
33
  import {
@@ -30,6 +37,7 @@ import {
30
37
  combinedCSSRules,
31
38
  } from './framer.js'
32
39
  import { logger, spinner, terminalMarkdown } from './utils.js'
40
+ import { transform } from '@babel/core'
33
41
 
34
42
  function validateUrl(url: string) {
35
43
  try {
@@ -47,13 +55,17 @@ export type StyleToken = {
47
55
  }
48
56
 
49
57
  export async function bundle({
58
+ config,
50
59
  cwd: out = '',
51
60
  watch = false,
52
- components = {} as Record<string, string>,
53
- tokens = [] as StyleToken[],
54
- breakpoints = {} as BreakpointSizes,
55
61
  signal = undefined as AbortSignal | undefined,
62
+ }: {
63
+ config: Config
64
+ cwd: string
65
+ watch?: boolean
66
+ signal?: AbortSignal
56
67
  }) {
68
+ const { components, breakpoints, tokens, outDir, framerWebPages } = config
57
69
  out ||= path.resolve(process.cwd(), 'example')
58
70
  out = path.resolve(out)
59
71
  try {
@@ -146,23 +158,41 @@ export async function bundle({
146
158
  .readFile(file.path, 'utf-8')
147
159
  .catch(() => null)
148
160
 
161
+ // let res = transform(file.text || '', {
162
+ // babelrc: false,
163
+ // sourceType: 'module',
164
+ // plugins: [
165
+ // babelPluginDeduplicateImports,
166
+
167
+ // babelPluginJsxTransform(),
168
+ // ],
169
+ // filename: 'x.js',
170
+ // compact: true,
171
+ // sourceMaps: false,
172
+ // })
173
+ // let inputCode = res!.code!
174
+ let inputCode = file.text
175
+
149
176
  let codeNew =
150
177
  `// @ts-nocheck\n` +
151
178
  `/* eslint-disable */\n` +
152
179
  '/* This file was generated by Unframer, do not edit manually */\n' +
153
- dprint.format(resultPathAbs, file.text, {
180
+ dprint.format('file.jsx', inputCode, {
154
181
  lineWidth: 140,
155
182
  quoteStyle: 'alwaysSingle',
156
183
  trailingCommas: 'always',
157
184
  semiColons: 'always',
158
185
  })
186
+ if (framerWebPages?.length) {
187
+ codeNew = replaceWebPageIds({
188
+ code: codeNew,
189
+ elements: framerWebPages,
190
+ })
191
+ }
159
192
  const lines = findRelativeLinks(codeNew)
160
193
  if (lines.length) {
161
194
  spinner.error(
162
- `found broken links for ${path.relative(
163
- out,
164
- file.path,
165
- )}, don't use relative links in Framer components`,
195
+ `found broken links for ${path.relative(out, file.path)}`,
166
196
  )
167
197
  lines.forEach((line) => {
168
198
  logger.log(`${path.resolve(out, file.path)}:${line + 1}`)
@@ -236,7 +266,7 @@ export async function bundle({
236
266
  '/* This file was generated by Unframer, do not edit manually */\n' +
237
267
  '/* This css file has all the necessary styles to run all your components */\n' +
238
268
  '\n' +
239
- getStyleTokensCss(tokens) +
269
+ getStyleTokensCss(tokens || []) +
240
270
  breakpointsStyles(breakpoints) +
241
271
  '\n\n' +
242
272
  combinedCSSRules
@@ -317,17 +347,21 @@ export async function bundle({
317
347
  console.log()
318
348
  console.log()
319
349
 
320
- let withBreakpoints = result?.components?.filter((x) => {
321
- if (!x.propertyControls) return false
322
- const variants = getVariantsFromPropControls(x.propertyControls)
323
- return variants?.breakpoints.length >= 2
324
- })
325
- withBreakpoints = withBreakpoints?.sort((a, b) => {
350
+ let exampleComponent = result?.components?.sort((a, b) => {
351
+ const aVariants = getVariantsFromPropControls(a.propertyControls)
352
+ const bVariants = getVariantsFromPropControls(b.propertyControls)
353
+ const aHasBreakpoints = (aVariants?.breakpoints?.length || 0) >= 2
354
+ const bHasBreakpoints = (bVariants?.breakpoints?.length || 0) >= 2
355
+
356
+ // Sort components with breakpoints first
357
+ if (aHasBreakpoints && !bHasBreakpoints) return -1
358
+ if (!aHasBreakpoints && bHasBreakpoints) return 1
359
+
360
+ // Within each group, prefer components with example properties
326
361
  const aProp = findExampleProperty(a.propertyControls)
327
362
  const bProp = findExampleProperty(b.propertyControls)
328
363
  return (bProp ? 1 : 0) - (aProp ? 1 : 0)
329
- })
330
- let exampleComponent = withBreakpoints?.[0]
364
+ })?.[0]
331
365
  if (!exampleComponent) {
332
366
  logger.log(
333
367
  `No example component found with breakpoints, using random example`,
@@ -353,22 +387,31 @@ export async function bundle({
353
387
  const variants = getVariantsFromPropControls(
354
388
  exampleComponent?.propertyControls,
355
389
  )
356
- const breakpoints = variants?.breakpoints
357
- if (!breakpoints) {
358
- return
359
- }
390
+ const outDir = path.posix.relative(process.cwd(), out)
360
391
  logger.log(
361
392
  'exampleComponent?.propertyControls',
362
393
  exampleComponent?.propertyControls,
363
394
  )
364
- const variantsExample = {
365
- lg: breakpoints[1],
366
- base: breakpoints[0],
367
- }
368
- let prop =
395
+ const prop =
369
396
  findExampleProperty(exampleComponent?.propertyControls) ||
370
397
  'exampleFramerVariable'
371
- const outDir = path.posix.relative(process.cwd(), out)
398
+ const responsiveComponent = (() => {
399
+ const breakpoints = variants?.breakpoints
400
+ if (!breakpoints?.length) {
401
+ return ''
402
+ }
403
+ const variantsExample = {
404
+ lg: breakpoints[1],
405
+ base: breakpoints[0],
406
+ }
407
+
408
+ return dedent`
409
+ <${exampleComponent?.componentName}.Responsive
410
+ ${prop}='example'
411
+ variants={${JSON.stringify(variantsExample || {})}}
412
+ />
413
+ `
414
+ })()
372
415
  console.log(
373
416
  terminalMarkdown(dedent`
374
417
  # How to use the Framer components
@@ -396,10 +439,12 @@ export async function bundle({
396
439
  ${prop}='example'
397
440
  style={{ width: '100%' }}
398
441
  />
399
- <${exampleComponent?.componentName}.Responsive
400
- ${prop}='example'
401
- variants={${JSON.stringify(variantsExample || {})}}
402
- />
442
+ ${responsiveComponent
443
+ .split('\n')
444
+ .map((line, i) =>
445
+ !i ? line : ' ' + line,
446
+ )
447
+ .join('\n')}
403
448
  </div>
404
449
  );
405
450
  };
@@ -410,6 +455,7 @@ export async function bundle({
410
455
  To style components you can pass a \`style\` or \`className\` prop (but remember to use !important to increase the specificity).
411
456
 
412
457
  Read more on GitHub: https://github.com/remorses/unframer
458
+
413
459
  `),
414
460
  )
415
461
  return result
@@ -663,10 +709,6 @@ function getTokensCss({
663
709
 
664
710
  const nodePath = process.argv[0] || 'node'
665
711
 
666
- let UNFRAMER_RUNTIME_PATH = url.pathToFileURL(
667
- require.resolve('../esm/index.js'),
668
- ).href
669
-
670
712
  export async function extractPropControlsUnsafe(
671
713
  filename,
672
714
  name,
@@ -685,6 +727,11 @@ export async function extractPropControlsUnsafe(
685
727
  )}); console.log(${propCode}) })`
686
728
 
687
729
  const TIMEOUT = 5 * 1000
730
+ const UNFRAMER_MAP_PACKAGES = JSON.stringify({
731
+ unframer: url.pathToFileURL(require.resolve('../esm/index.js')).href,
732
+ react: url.pathToFileURL(require.resolve('react')).href,
733
+ 'react-dom': url.pathToFileURL(require.resolve('react-dom')).href,
734
+ })
688
735
  let stdout = await new Promise<string>((res, rej) => {
689
736
  let childProcess = exec(
690
737
  `${JSON.stringify(
@@ -695,14 +742,17 @@ export async function extractPropControlsUnsafe(
695
742
  {
696
743
  env: {
697
744
  // ...process.env,
698
- UNFRAMER_RUNTIME_PATH,
745
+ UNFRAMER_MAP_PACKAGES,
699
746
  },
700
747
  },
701
- (err, stdout) => {
748
+ (err, stdout, stderr) => {
702
749
  clearTimeout(timer)
703
750
  if (err) {
751
+ spinner.error(`error extracting types for ${name}`)
752
+ spinner.error(stderr)
704
753
  return rej(err)
705
754
  }
755
+
706
756
  res(stdout)
707
757
  },
708
758
  )
@@ -716,12 +766,15 @@ export async function extractPropControlsUnsafe(
716
766
  )
717
767
  }, TIMEOUT)
718
768
  }).catch((e) => {
719
- spinner.error(`error extracting types for ${name}`)
720
769
  logger.log(e.stack)
721
- throw e
770
+ return ''
722
771
  })
723
772
 
724
- stdout = stdout.split(delimiter)[1]
773
+ stdout = stdout.split(delimiter)[1] || ''
774
+ if (!stdout) {
775
+ return {}
776
+ }
777
+
725
778
  // console.log(stdout)
726
779
  return safeJsonParse(stdout)
727
780
  }
@@ -1000,7 +1053,7 @@ export function propCamelCase(str: string) {
1000
1053
  }
1001
1054
  // Convert dashes to camelCase (e.g. foo-bar -> fooBar)
1002
1055
  str = str.replace(/-([\w])/g, (g) => g[1].toUpperCase())
1003
- // Convert underscores to camelCase (e.g. foo_bar -> fooBar)
1056
+ // Convert underscores to camelCase (e.g. foo_bar -> fooBar)
1004
1057
  str = str.replace(/_([a-z])/g, (g) => g[1].toUpperCase())
1005
1058
  // Remove spaces (e.g. "Foo Bar" -> "fooBar")
1006
1059
  str = str.replace(/\s+(.)/g, (_, c) => c.toUpperCase())