unframer 2.9.2 → 2.10.1
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/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +4 -0
- package/dist/cli.js.map +1 -1
- package/dist/exporter.d.ts.map +1 -1
- package/dist/exporter.js +86 -90
- package/dist/exporter.js.map +1 -1
- package/dist/utils.d.ts +1 -0
- package/dist/utils.d.ts.map +1 -1
- package/dist/utils.js +2 -1
- package/dist/utils.js.map +1 -1
- package/esm/cli.d.ts.map +1 -1
- package/esm/cli.js +4 -0
- package/esm/cli.js.map +1 -1
- package/esm/exporter.d.ts.map +1 -1
- package/esm/exporter.js +87 -91
- package/esm/exporter.js.map +1 -1
- package/esm/utils.d.ts +1 -0
- package/esm/utils.d.ts.map +1 -1
- package/esm/utils.js +2 -1
- package/esm/utils.js.map +1 -1
- package/package.json +1 -2
- package/src/cli.tsx +4 -0
- package/src/exporter.ts +104 -110
- package/src/utils.ts +2 -1
package/src/exporter.ts
CHANGED
|
@@ -1,12 +1,7 @@
|
|
|
1
|
-
import {
|
|
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,
|
|
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
|
|
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
|
|
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,18 +205,31 @@ export async function bundle({
|
|
|
220
205
|
// sourceMaps: false,
|
|
221
206
|
// })
|
|
222
207
|
// let inputCode = res!.code!
|
|
223
|
-
let inputCode = file.text
|
|
224
208
|
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
dprint.format('file.jsx',
|
|
209
|
+
const twoMb = 2 * 1024 * 1024
|
|
210
|
+
|
|
211
|
+
let formatted = file.text
|
|
212
|
+
if (file.text.length < twoMb) {
|
|
213
|
+
formatted = dprint.format('file.jsx', file.text, {
|
|
230
214
|
lineWidth: 140,
|
|
231
215
|
quoteStyle: 'alwaysSingle',
|
|
232
216
|
trailingCommas: 'always',
|
|
233
217
|
semiColons: 'always',
|
|
234
218
|
})
|
|
219
|
+
} else {
|
|
220
|
+
spinner.info(
|
|
221
|
+
`skipping formatting ${path.relative(
|
|
222
|
+
out,
|
|
223
|
+
file.path,
|
|
224
|
+
)}, too big`,
|
|
225
|
+
)
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
let codeNew =
|
|
229
|
+
`// @ts-nocheck\n` +
|
|
230
|
+
`/* eslint-disable */\n` +
|
|
231
|
+
doNotEditComment +
|
|
232
|
+
formatted
|
|
235
233
|
if (framerWebPages?.length) {
|
|
236
234
|
codeNew = replaceWebPageIds({
|
|
237
235
|
code: codeNew,
|
|
@@ -265,14 +263,14 @@ export async function bundle({
|
|
|
265
263
|
JSON.stringify({ type: 'module' }),
|
|
266
264
|
'utf-8',
|
|
267
265
|
)
|
|
268
|
-
if (!
|
|
266
|
+
if (!buildResult?.outputFiles) {
|
|
269
267
|
throw new Error('Failed to generate result')
|
|
270
268
|
}
|
|
271
269
|
const sema = new Sema(5)
|
|
272
270
|
spinner.start('Extracting types')
|
|
273
271
|
logger.log(`using node path`, nodePath)
|
|
274
272
|
const propControlsData = await Promise.all(
|
|
275
|
-
|
|
273
|
+
buildResult?.outputFiles.map(async (file) => {
|
|
276
274
|
try {
|
|
277
275
|
await sema.acquire()
|
|
278
276
|
const name = path
|
|
@@ -301,15 +299,12 @@ export async function bundle({
|
|
|
301
299
|
fileName: name,
|
|
302
300
|
config,
|
|
303
301
|
})
|
|
304
|
-
// name = 'framer-' + name
|
|
305
|
-
// logger.log('name', name)
|
|
306
302
|
fs.mkdirSync(out, { recursive: true })
|
|
307
303
|
fs.writeFileSync(path.resolve(out, `${name}.d.ts`), types)
|
|
308
304
|
return {
|
|
309
305
|
propertyControls,
|
|
310
306
|
fonts,
|
|
311
307
|
name,
|
|
312
|
-
// componentPath: file.path,
|
|
313
308
|
}
|
|
314
309
|
} finally {
|
|
315
310
|
sema.release()
|
|
@@ -336,7 +331,7 @@ export async function bundle({
|
|
|
336
331
|
.split('\n')
|
|
337
332
|
.forEach((x) => logger.log(x))
|
|
338
333
|
|
|
339
|
-
const outFiles =
|
|
334
|
+
const outFiles = buildResult.outputFiles
|
|
340
335
|
.map((x) => path.resolve(out, x.path))
|
|
341
336
|
.concat([
|
|
342
337
|
path.resolve(out, 'meta.json'),
|
|
@@ -344,7 +339,7 @@ export async function bundle({
|
|
|
344
339
|
path.resolve(out, 'styles.css'),
|
|
345
340
|
])
|
|
346
341
|
.concat(
|
|
347
|
-
|
|
342
|
+
buildResult.outputFiles.map((x) =>
|
|
348
343
|
path.resolve(out, x.path.replace('.js', '.d.ts')),
|
|
349
344
|
),
|
|
350
345
|
)
|
|
@@ -356,14 +351,13 @@ export async function bundle({
|
|
|
356
351
|
|
|
357
352
|
fs.writeFileSync(
|
|
358
353
|
path.resolve(out, 'meta.json'),
|
|
359
|
-
JSON.stringify(
|
|
354
|
+
JSON.stringify(buildResult.metafile, null, 2),
|
|
360
355
|
'utf-8',
|
|
361
356
|
)
|
|
362
357
|
|
|
363
358
|
if (signal?.aborted) {
|
|
364
359
|
throw new Error('aborted')
|
|
365
360
|
}
|
|
366
|
-
// logger.log('result', result)
|
|
367
361
|
|
|
368
362
|
if (watch) {
|
|
369
363
|
logger.log('waiting for components or config changes')
|
|
@@ -372,7 +366,7 @@ export async function bundle({
|
|
|
372
366
|
const tokensCss =
|
|
373
367
|
"/* 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
368
|
'/* 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 })
|
|
369
|
+
getTokensCss({ out, result: buildResult })
|
|
376
370
|
fs.writeFileSync(
|
|
377
371
|
path.resolve(out, 'tokens.css'),
|
|
378
372
|
tokensCss,
|
|
@@ -398,82 +392,83 @@ export async function bundle({
|
|
|
398
392
|
return res
|
|
399
393
|
}
|
|
400
394
|
|
|
401
|
-
if (
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
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)
|
|
395
|
+
if (watch) {
|
|
396
|
+
throw new Error('--watch is not supported yet')
|
|
397
|
+
}
|
|
398
|
+
const result = await rebuild()
|
|
399
|
+
console.log()
|
|
400
|
+
console.log()
|
|
401
|
+
|
|
402
|
+
let exampleComponent = result?.components?.sort((a, b) => {
|
|
403
|
+
const aVariants = getVariantsFromPropControls(a.propertyControls)
|
|
404
|
+
const bVariants = getVariantsFromPropControls(b.propertyControls)
|
|
405
|
+
const aHasBreakpoints = (aVariants?.breakpoints?.length || 0) >= 2
|
|
406
|
+
const bHasBreakpoints = (bVariants?.breakpoints?.length || 0) >= 2
|
|
407
|
+
|
|
408
|
+
// Sort components with breakpoints first
|
|
409
|
+
if (aHasBreakpoints && !bHasBreakpoints) return -1
|
|
410
|
+
if (!aHasBreakpoints && bHasBreakpoints) return 1
|
|
411
|
+
|
|
412
|
+
// Within each group, prefer components with example properties
|
|
413
|
+
const aProp = findExampleProperty(a.propertyControls)
|
|
414
|
+
const bProp = findExampleProperty(b.propertyControls)
|
|
415
|
+
return (bProp ? 1 : 0) - (aProp ? 1 : 0)
|
|
416
|
+
})?.[0]
|
|
417
|
+
if (!exampleComponent) {
|
|
448
418
|
logger.log(
|
|
449
|
-
|
|
450
|
-
exampleComponent?.propertyControls,
|
|
419
|
+
`No example component found with breakpoints, using random example`,
|
|
451
420
|
)
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
'
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
421
|
+
// Create an example component if none found with breakpoints
|
|
422
|
+
exampleComponent = {
|
|
423
|
+
path: 'hero',
|
|
424
|
+
componentName: 'HeroFramerComponent',
|
|
425
|
+
propertyControls: {
|
|
426
|
+
variant: {
|
|
427
|
+
type: ControlType.Enum,
|
|
428
|
+
options: ['Desktop', 'Tablet', 'Mobile'],
|
|
429
|
+
optionTitles: ['Desktop', 'Tablet', 'Mobile'],
|
|
430
|
+
},
|
|
431
|
+
} as any,
|
|
432
|
+
name: 'Hero',
|
|
433
|
+
url: '',
|
|
434
|
+
}
|
|
435
|
+
if (!exampleComponent) {
|
|
436
|
+
return
|
|
437
|
+
}
|
|
438
|
+
}
|
|
439
|
+
const variants = getVariantsFromPropControls(
|
|
440
|
+
exampleComponent?.propertyControls,
|
|
441
|
+
)
|
|
442
|
+
const outDirNice = path.posix.relative(process.cwd(), out)
|
|
443
|
+
logger.log(
|
|
444
|
+
'exampleComponent?.propertyControls',
|
|
445
|
+
exampleComponent?.propertyControls,
|
|
446
|
+
)
|
|
447
|
+
const prop =
|
|
448
|
+
findExampleProperty(exampleComponent?.propertyControls) ||
|
|
449
|
+
'exampleFramerVariable'
|
|
450
|
+
const responsiveComponent = (() => {
|
|
451
|
+
const breakpoints = variants?.breakpoints
|
|
452
|
+
if (!breakpoints?.length) {
|
|
453
|
+
return ''
|
|
454
|
+
}
|
|
455
|
+
const variantsExample = {
|
|
456
|
+
lg: breakpoints[1],
|
|
457
|
+
base: breakpoints[0],
|
|
458
|
+
}
|
|
464
459
|
|
|
465
|
-
|
|
460
|
+
return dedent`
|
|
466
461
|
<${exampleComponent?.componentName}.Responsive
|
|
467
462
|
${prop}='example'
|
|
468
463
|
variants={${JSON.stringify(variantsExample || {})}}
|
|
469
464
|
/>
|
|
470
465
|
`
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
466
|
+
})()
|
|
467
|
+
console.log(
|
|
468
|
+
terminalMarkdown(dedent`
|
|
474
469
|
# How to use the Framer components
|
|
475
470
|
|
|
476
|
-
Your components are exported to \`${
|
|
471
|
+
Your components are exported to \`${outDirNice}\` folder. Now please install the \`unframer\` runtime dependency:
|
|
477
472
|
|
|
478
473
|
\`\`\`sh
|
|
479
474
|
npm install unframer
|
|
@@ -484,10 +479,10 @@ export async function bundle({
|
|
|
484
479
|
You can use the components like this (try copy pasting the code below into your React app):
|
|
485
480
|
|
|
486
481
|
\`\`\`jsx
|
|
487
|
-
import './${
|
|
488
|
-
import ${exampleComponent?.componentName} from './${
|
|
489
|
-
|
|
490
|
-
|
|
482
|
+
import './${outDirNice}/styles.css'
|
|
483
|
+
import ${exampleComponent?.componentName} from './${outDirNice}/${
|
|
484
|
+
exampleComponent?.path
|
|
485
|
+
}'
|
|
491
486
|
|
|
492
487
|
export default function App() {
|
|
493
488
|
return (
|
|
@@ -512,9 +507,8 @@ export async function bundle({
|
|
|
512
507
|
Read more on GitHub: https://github.com/remorses/unframer
|
|
513
508
|
|
|
514
509
|
`),
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
}
|
|
510
|
+
)
|
|
511
|
+
return result
|
|
518
512
|
|
|
519
513
|
// // when user press ctrl+c dispose
|
|
520
514
|
// 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 (!
|
|
22
|
+
if (!logger.debug) {
|
|
22
23
|
return
|
|
23
24
|
}
|
|
24
25
|
console.log(prefix, ...args)
|