unframer 2.9.2 → 2.10.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/exporter.ts CHANGED
@@ -1,12 +1,7 @@
1
- import { BuildResult, context } from 'esbuild'
1
+ import { build, BuildResult } from 'esbuild'
2
2
 
3
- import {
4
- babelPluginDeduplicateImports,
5
- babelPluginJsxTransform,
6
- } from './babel-plugin-imports.js'
7
-
8
- import { Config } from './cli'
9
3
  import url from 'url'
4
+ import { Config } from './cli'
10
5
 
11
6
  import { Sema } from 'async-sema'
12
7
  import dprint from 'dprint-node'
@@ -14,11 +9,10 @@ import dprint from 'dprint-node'
14
9
  import { nodeModulesPolyfillPlugin } from 'esbuild-plugins-node-modules-polyfill'
15
10
 
16
11
  import { exec } from 'child_process'
17
- import dedent from 'string-dedent'
18
12
  import fs from 'fs'
19
13
  import path from 'path'
14
+ import dedent from 'string-dedent'
20
15
  import {
21
- BreakpointSizes,
22
16
  ComponentFontBundle,
23
17
  breakpointsStyles,
24
18
  getFontsStyles,
@@ -38,7 +32,6 @@ import {
38
32
  combinedCSSRules,
39
33
  } from './framer.js'
40
34
  import { logger, spinner, terminalMarkdown } from './utils.js'
41
- import { transform } from '@babel/core'
42
35
 
43
36
  function validateUrl(url: string) {
44
37
  try {
@@ -66,7 +59,7 @@ export async function bundle({
66
59
  watch?: boolean
67
60
  signal?: AbortSignal
68
61
  }) {
69
- const { components, breakpoints, tokens, outDir, framerWebPages } = config
62
+ const { components, breakpoints, tokens, framerWebPages } = config
70
63
  out ||= path.resolve(process.cwd(), 'example')
71
64
  out = path.resolve(out)
72
65
  try {
@@ -74,10 +67,7 @@ export async function bundle({
74
67
  } catch (e) {}
75
68
 
76
69
  spinner.start()
77
- const buildContext = await context({
78
- // entryPoints: {
79
- // index: url,
80
- // },
70
+ const buildResult = await build({
81
71
  absWorkingDir: out,
82
72
  entryPoints: Object.keys(components).map((name) => {
83
73
  const url = components[name]
@@ -98,7 +88,6 @@ export async function bundle({
98
88
 
99
89
  treeShaking: true,
100
90
  splitting: true,
101
- // splitting: true,
102
91
  logLevel: 'error',
103
92
 
104
93
  pure: ['addPropertyControls'],
@@ -190,23 +179,19 @@ export async function bundle({
190
179
  ],
191
180
  write: false,
192
181
 
193
- // outfile: 'dist/example.js',
194
182
  outdir: out,
195
- // outfile: path.resolve(cwd, sourcefile),
196
183
  })
197
184
  const doNotEditComment = `/* This file was generated by Unframer for Framer project ${
198
185
  config.projectId || ''
199
186
  } "${config.projectName}", do not edit manually */\n`
200
187
  async function rebuild() {
201
188
  const prevFiles = recursiveReaddir(out)
202
- const result = await buildContext.rebuild()
203
189
 
204
- for (let file of result.outputFiles!) {
190
+ for (let file of buildResult.outputFiles!) {
205
191
  const resultPathAbs = path.resolve(out, file.path)
206
192
  const existing = await fs.promises
207
193
  .readFile(file.path, 'utf-8')
208
194
  .catch(() => null)
209
-
210
195
  // let res = transform(file.text || '', {
211
196
  // babelrc: false,
212
197
  // sourceType: 'module',
@@ -220,6 +205,7 @@ export async function bundle({
220
205
  // sourceMaps: false,
221
206
  // })
222
207
  // let inputCode = res!.code!
208
+
223
209
  let inputCode = file.text
224
210
 
225
211
  let codeNew =
@@ -265,14 +251,14 @@ export async function bundle({
265
251
  JSON.stringify({ type: 'module' }),
266
252
  'utf-8',
267
253
  )
268
- if (!result?.outputFiles) {
254
+ if (!buildResult?.outputFiles) {
269
255
  throw new Error('Failed to generate result')
270
256
  }
271
257
  const sema = new Sema(5)
272
258
  spinner.start('Extracting types')
273
259
  logger.log(`using node path`, nodePath)
274
260
  const propControlsData = await Promise.all(
275
- result?.outputFiles.map(async (file) => {
261
+ buildResult?.outputFiles.map(async (file) => {
276
262
  try {
277
263
  await sema.acquire()
278
264
  const name = path
@@ -301,15 +287,12 @@ export async function bundle({
301
287
  fileName: name,
302
288
  config,
303
289
  })
304
- // name = 'framer-' + name
305
- // logger.log('name', name)
306
290
  fs.mkdirSync(out, { recursive: true })
307
291
  fs.writeFileSync(path.resolve(out, `${name}.d.ts`), types)
308
292
  return {
309
293
  propertyControls,
310
294
  fonts,
311
295
  name,
312
- // componentPath: file.path,
313
296
  }
314
297
  } finally {
315
298
  sema.release()
@@ -336,7 +319,7 @@ export async function bundle({
336
319
  .split('\n')
337
320
  .forEach((x) => logger.log(x))
338
321
 
339
- const outFiles = result.outputFiles
322
+ const outFiles = buildResult.outputFiles
340
323
  .map((x) => path.resolve(out, x.path))
341
324
  .concat([
342
325
  path.resolve(out, 'meta.json'),
@@ -344,7 +327,7 @@ export async function bundle({
344
327
  path.resolve(out, 'styles.css'),
345
328
  ])
346
329
  .concat(
347
- result.outputFiles.map((x) =>
330
+ buildResult.outputFiles.map((x) =>
348
331
  path.resolve(out, x.path.replace('.js', '.d.ts')),
349
332
  ),
350
333
  )
@@ -356,14 +339,13 @@ export async function bundle({
356
339
 
357
340
  fs.writeFileSync(
358
341
  path.resolve(out, 'meta.json'),
359
- JSON.stringify(result.metafile, null, 2),
342
+ JSON.stringify(buildResult.metafile, null, 2),
360
343
  'utf-8',
361
344
  )
362
345
 
363
346
  if (signal?.aborted) {
364
347
  throw new Error('aborted')
365
348
  }
366
- // logger.log('result', result)
367
349
 
368
350
  if (watch) {
369
351
  logger.log('waiting for components or config changes')
@@ -372,7 +354,7 @@ export async function bundle({
372
354
  const tokensCss =
373
355
  "/* This css file contains your color variables, sometimes these get desynced when updated in Framer so it's good that you copy and paste this snippet into your app css */\n" +
374
356
  '/* Bug: https://www.framer.community/c/bugs/color-style-unlinks-when-copying-component-between-projects-resulting-in-potential-value-discrepancy */\n' +
375
- getTokensCss({ out, result })
357
+ getTokensCss({ out, result: buildResult })
376
358
  fs.writeFileSync(
377
359
  path.resolve(out, 'tokens.css'),
378
360
  tokensCss,
@@ -398,82 +380,83 @@ export async function bundle({
398
380
  return res
399
381
  }
400
382
 
401
- if (!watch) {
402
- const result = await rebuild()
403
- await buildContext.dispose()
404
- console.log()
405
- console.log()
406
-
407
- let exampleComponent = result?.components?.sort((a, b) => {
408
- const aVariants = getVariantsFromPropControls(a.propertyControls)
409
- const bVariants = getVariantsFromPropControls(b.propertyControls)
410
- const aHasBreakpoints = (aVariants?.breakpoints?.length || 0) >= 2
411
- const bHasBreakpoints = (bVariants?.breakpoints?.length || 0) >= 2
412
-
413
- // Sort components with breakpoints first
414
- if (aHasBreakpoints && !bHasBreakpoints) return -1
415
- if (!aHasBreakpoints && bHasBreakpoints) return 1
416
-
417
- // Within each group, prefer components with example properties
418
- const aProp = findExampleProperty(a.propertyControls)
419
- const bProp = findExampleProperty(b.propertyControls)
420
- return (bProp ? 1 : 0) - (aProp ? 1 : 0)
421
- })?.[0]
422
- if (!exampleComponent) {
423
- logger.log(
424
- `No example component found with breakpoints, using random example`,
425
- )
426
- // Create an example component if none found with breakpoints
427
- exampleComponent = {
428
- path: 'hero',
429
- componentName: 'HeroFramerComponent',
430
- propertyControls: {
431
- variant: {
432
- type: ControlType.Enum,
433
- options: ['Desktop', 'Tablet', 'Mobile'],
434
- optionTitles: ['Desktop', 'Tablet', 'Mobile'],
435
- },
436
- } as any,
437
- name: 'Hero',
438
- url: '',
439
- }
440
- if (!exampleComponent) {
441
- return
442
- }
443
- }
444
- const variants = getVariantsFromPropControls(
445
- exampleComponent?.propertyControls,
446
- )
447
- const outDir = path.posix.relative(process.cwd(), out)
383
+ if (watch) {
384
+ throw new Error('--watch is not supported yet')
385
+ }
386
+ const result = await rebuild()
387
+ console.log()
388
+ console.log()
389
+
390
+ let exampleComponent = result?.components?.sort((a, b) => {
391
+ const aVariants = getVariantsFromPropControls(a.propertyControls)
392
+ const bVariants = getVariantsFromPropControls(b.propertyControls)
393
+ const aHasBreakpoints = (aVariants?.breakpoints?.length || 0) >= 2
394
+ const bHasBreakpoints = (bVariants?.breakpoints?.length || 0) >= 2
395
+
396
+ // Sort components with breakpoints first
397
+ if (aHasBreakpoints && !bHasBreakpoints) return -1
398
+ if (!aHasBreakpoints && bHasBreakpoints) return 1
399
+
400
+ // Within each group, prefer components with example properties
401
+ const aProp = findExampleProperty(a.propertyControls)
402
+ const bProp = findExampleProperty(b.propertyControls)
403
+ return (bProp ? 1 : 0) - (aProp ? 1 : 0)
404
+ })?.[0]
405
+ if (!exampleComponent) {
448
406
  logger.log(
449
- 'exampleComponent?.propertyControls',
450
- exampleComponent?.propertyControls,
407
+ `No example component found with breakpoints, using random example`,
451
408
  )
452
- const prop =
453
- findExampleProperty(exampleComponent?.propertyControls) ||
454
- 'exampleFramerVariable'
455
- const responsiveComponent = (() => {
456
- const breakpoints = variants?.breakpoints
457
- if (!breakpoints?.length) {
458
- return ''
459
- }
460
- const variantsExample = {
461
- lg: breakpoints[1],
462
- base: breakpoints[0],
463
- }
409
+ // Create an example component if none found with breakpoints
410
+ exampleComponent = {
411
+ path: 'hero',
412
+ componentName: 'HeroFramerComponent',
413
+ propertyControls: {
414
+ variant: {
415
+ type: ControlType.Enum,
416
+ options: ['Desktop', 'Tablet', 'Mobile'],
417
+ optionTitles: ['Desktop', 'Tablet', 'Mobile'],
418
+ },
419
+ } as any,
420
+ name: 'Hero',
421
+ url: '',
422
+ }
423
+ if (!exampleComponent) {
424
+ return
425
+ }
426
+ }
427
+ const variants = getVariantsFromPropControls(
428
+ exampleComponent?.propertyControls,
429
+ )
430
+ const outDirNice = path.posix.relative(process.cwd(), out)
431
+ logger.log(
432
+ 'exampleComponent?.propertyControls',
433
+ exampleComponent?.propertyControls,
434
+ )
435
+ const prop =
436
+ findExampleProperty(exampleComponent?.propertyControls) ||
437
+ 'exampleFramerVariable'
438
+ const responsiveComponent = (() => {
439
+ const breakpoints = variants?.breakpoints
440
+ if (!breakpoints?.length) {
441
+ return ''
442
+ }
443
+ const variantsExample = {
444
+ lg: breakpoints[1],
445
+ base: breakpoints[0],
446
+ }
464
447
 
465
- return dedent`
448
+ return dedent`
466
449
  <${exampleComponent?.componentName}.Responsive
467
450
  ${prop}='example'
468
451
  variants={${JSON.stringify(variantsExample || {})}}
469
452
  />
470
453
  `
471
- })()
472
- console.log(
473
- terminalMarkdown(dedent`
454
+ })()
455
+ console.log(
456
+ terminalMarkdown(dedent`
474
457
  # How to use the Framer components
475
458
 
476
- Your components are exported to \`${outDir}\` folder. Now please install the \`unframer\` runtime dependency:
459
+ Your components are exported to \`${outDirNice}\` folder. Now please install the \`unframer\` runtime dependency:
477
460
 
478
461
  \`\`\`sh
479
462
  npm install unframer
@@ -484,10 +467,10 @@ export async function bundle({
484
467
  You can use the components like this (try copy pasting the code below into your React app):
485
468
 
486
469
  \`\`\`jsx
487
- import './${outDir}/styles.css'
488
- import ${exampleComponent?.componentName} from './${outDir}/${
489
- exampleComponent?.path
490
- }'
470
+ import './${outDirNice}/styles.css'
471
+ import ${exampleComponent?.componentName} from './${outDirNice}/${
472
+ exampleComponent?.path
473
+ }'
491
474
 
492
475
  export default function App() {
493
476
  return (
@@ -512,9 +495,8 @@ export async function bundle({
512
495
  Read more on GitHub: https://github.com/remorses/unframer
513
496
 
514
497
  `),
515
- )
516
- return result
517
- }
498
+ )
499
+ return result
518
500
 
519
501
  // // when user press ctrl+c dispose
520
502
  // process.on('SIGINT', async () => {
package/src/utils.ts CHANGED
@@ -17,8 +17,9 @@ const shouldDebugUnframer = !!process.env.DEBUG_UNFRAMER
17
17
 
18
18
  const prefix = '[unframer]'
19
19
  export const logger = {
20
+ debug: shouldDebugUnframer,
20
21
  log(...args) {
21
- if (!shouldDebugUnframer) {
22
+ if (!logger.debug) {
22
23
  return
23
24
  }
24
25
  console.log(prefix, ...args)