@webflow/webflow-cli 2.1.0 → 2.2.0-next.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/CHANGELOG.md +8 -0
- package/README.md +52 -0
- package/dist/cloud-scaffolds/fetcher.ts +5 -1
- package/dist/cloud-scaffolds/registry.ts +10 -0
- package/dist/cloud-scaffolds/types.ts +6 -0
- package/dist/index.js +117 -109
- package/dist/index.js.map +1 -1
- package/dist/templates/astro/v7/astro.config.mjs.template +34 -0
- package/dist/templates/astro/v7/webflow-loader.ts +122 -0
- package/dist/templates/astro/v7/wrangler.json +9 -0
- package/package.json +4 -4
- package/dist/extension-scaffolds/default/.eslintrc +0 -25
- package/dist/extension-scaffolds/react/.eslintrc +0 -25
- package/dist/extension-scaffolds/typescript-alt/.eslintrc +0 -25
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
// Generated by the Webflow Cloud builder. Merge logic lives in ./astro.config.webflow.ts.
|
|
2
|
+
import { defineConfig } from 'astro/config';
|
|
3
|
+
import { readFileSync } from 'node:fs';
|
|
4
|
+
import cloudflare from '@astrojs/cloudflare';
|
|
5
|
+
import react from '@astrojs/react';
|
|
6
|
+
import userConfig from './clouduser.astro.config';
|
|
7
|
+
import { withWebflowOverrides } from './astro.config.webflow';
|
|
8
|
+
|
|
9
|
+
// Detect React 19+ so we know whether to alias react-dom/server -> .edge.
|
|
10
|
+
let isReact19 = false;
|
|
11
|
+
try {
|
|
12
|
+
const pkg = JSON.parse(readFileSync('./package.json', 'utf8'));
|
|
13
|
+
const reactVersion = pkg.dependencies?.react || pkg.devDependencies?.react || '';
|
|
14
|
+
// Match versions like "19", "^19", "~19", "19.0.0", "^19.0.0", etc.
|
|
15
|
+
isReact19 = /(?:^|[^\d])19(?:\.|$)/.test(reactVersion);
|
|
16
|
+
} catch {
|
|
17
|
+
// Could not read package.json, assume not React 19.
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export default defineConfig(
|
|
21
|
+
withWebflowOverrides(userConfig, {
|
|
22
|
+
mountPath: '${COSMIC_MOUNT_PATH}',
|
|
23
|
+
deployUrl: '${COSMIC_DEPLOY_URL}',
|
|
24
|
+
adapter: cloudflare({
|
|
25
|
+
imageService: 'custom',
|
|
26
|
+
// Note: workerd runs natively via @cloudflare/vite-plugin (no platformProxy needed).
|
|
27
|
+
}),
|
|
28
|
+
reactIntegration: react(),
|
|
29
|
+
// Only React 19+ has react-dom/server.edge. React 18 has only .browser, which doesn't run in edge runtimes.
|
|
30
|
+
reactDomServerAlias: import.meta.env.PROD && isReact19
|
|
31
|
+
? { 'react-dom/server': 'react-dom/server.edge' }
|
|
32
|
+
: undefined,
|
|
33
|
+
})
|
|
34
|
+
);
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Webflow Image Loader for Astro 7
|
|
3
|
+
*
|
|
4
|
+
* This is the same loader as Astro 5/6 - it handles image optimization
|
|
5
|
+
* through Cloudflare's image resizing service.
|
|
6
|
+
*
|
|
7
|
+
* Note: Astro defaults to 'cloudflare-binding' for imageService,
|
|
8
|
+
* but we use 'custom' to maintain compatibility with our CDN setup.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import type { ExternalImageService, ImageTransform, AstroConfig } from "astro";
|
|
12
|
+
|
|
13
|
+
function normalizeSrc(src: string, deployUrl?: string, mountPath?: string) {
|
|
14
|
+
// For local assets, include the mount path but not the deploy url, and remove the leading slash
|
|
15
|
+
if (deployUrl && src.startsWith(deployUrl)) {
|
|
16
|
+
return `${src.slice(deployUrl.length)}`.slice(1);
|
|
17
|
+
} else if (mountPath && src.startsWith(mountPath)) {
|
|
18
|
+
return src.slice(1);
|
|
19
|
+
} else if (src.startsWith("/")) {
|
|
20
|
+
return `${mountPath}${src}`.slice(1);
|
|
21
|
+
}
|
|
22
|
+
return src;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
// Default implementation copied from Astro's baseService
|
|
26
|
+
function getTargetDimensions(options: ImageTransform) {
|
|
27
|
+
let targetWidth = options.width;
|
|
28
|
+
let targetHeight = options.height;
|
|
29
|
+
|
|
30
|
+
// For ESM imported images, calculate missing dimensions based on aspect ratio
|
|
31
|
+
if (
|
|
32
|
+
typeof options.src === "object" &&
|
|
33
|
+
"width" in options.src &&
|
|
34
|
+
"height" in options.src
|
|
35
|
+
) {
|
|
36
|
+
const aspectRatio = options.src.width / options.src.height;
|
|
37
|
+
if (targetHeight && !targetWidth) {
|
|
38
|
+
targetWidth = Math.round(targetHeight * aspectRatio);
|
|
39
|
+
} else if (targetWidth && !targetHeight) {
|
|
40
|
+
targetHeight = Math.round(targetWidth / aspectRatio);
|
|
41
|
+
} else if (!targetWidth && !targetHeight) {
|
|
42
|
+
targetWidth = options.src.width;
|
|
43
|
+
targetHeight = options.src.height;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
return {
|
|
48
|
+
targetWidth,
|
|
49
|
+
targetHeight,
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
const cloudflareLoader: ExternalImageService = {
|
|
54
|
+
getURL(options: ImageTransform, imageConfig: AstroConfig["image"]) {
|
|
55
|
+
const normalizedSrc = normalizeSrc(
|
|
56
|
+
typeof options.src === "object" ? options.src.src : options.src,
|
|
57
|
+
imageConfig.service.config.deployUrl,
|
|
58
|
+
imageConfig.service.config.mountPath
|
|
59
|
+
);
|
|
60
|
+
// Our cloudflare zone doesn't allow optimizing external images for security reasons, so just load the original image
|
|
61
|
+
// For now, also skip optimization for images hosted on regular webflow sites (cdn.website-files.com)
|
|
62
|
+
// because optimizing them would result in two bandwidth charges: one from the website-files zone (for the full image)
|
|
63
|
+
// and one from the cosmic.webflow.services zone (for the resized image)
|
|
64
|
+
if (
|
|
65
|
+
normalizedSrc.startsWith("http://") ||
|
|
66
|
+
normalizedSrc.startsWith("https://")
|
|
67
|
+
) {
|
|
68
|
+
return normalizedSrc;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
const supportedOptions = ["width", "height", "quality", "format"];
|
|
72
|
+
const params = [];
|
|
73
|
+
for (const option of supportedOptions) {
|
|
74
|
+
if (options[option]) {
|
|
75
|
+
params.push(`${option}=${options[option]}`);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
const workerUrl = imageConfig.service.config.deployUrl;
|
|
80
|
+
// Skip resizing svgs, since it doesn't do anything
|
|
81
|
+
const isSvg =
|
|
82
|
+
typeof options.src === "object"
|
|
83
|
+
? options.src.format === "svg"
|
|
84
|
+
: options.src.endsWith(".svg");
|
|
85
|
+
if (isSvg || params.length === 0) {
|
|
86
|
+
return `${workerUrl}/${normalizedSrc}`;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
const paramsString = params.join(",");
|
|
90
|
+
return `${workerUrl}/cdn-cgi/image/${paramsString}/${normalizedSrc}`;
|
|
91
|
+
},
|
|
92
|
+
|
|
93
|
+
// Default implementation copied from Astro's baseService
|
|
94
|
+
getHTMLAttributes(options: ImageTransform) {
|
|
95
|
+
const { targetWidth, targetHeight } = getTargetDimensions(options);
|
|
96
|
+
const {
|
|
97
|
+
src,
|
|
98
|
+
width,
|
|
99
|
+
height,
|
|
100
|
+
format,
|
|
101
|
+
quality,
|
|
102
|
+
densities,
|
|
103
|
+
widths,
|
|
104
|
+
formats,
|
|
105
|
+
layout,
|
|
106
|
+
priority,
|
|
107
|
+
fit,
|
|
108
|
+
position,
|
|
109
|
+
...attributes
|
|
110
|
+
} = options;
|
|
111
|
+
|
|
112
|
+
return {
|
|
113
|
+
...attributes,
|
|
114
|
+
width: targetWidth,
|
|
115
|
+
height: targetHeight,
|
|
116
|
+
loading: attributes.loading ?? "lazy",
|
|
117
|
+
decoding: attributes.decoding ?? "async",
|
|
118
|
+
};
|
|
119
|
+
},
|
|
120
|
+
};
|
|
121
|
+
|
|
122
|
+
export default cloudflareLoader;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@webflow/webflow-cli",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.2.0-next.0",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"bin": {
|
|
6
6
|
"webflow": "./dist/index.js"
|
|
@@ -32,7 +32,7 @@
|
|
|
32
32
|
"@module-federation/enhanced": "0.20.0",
|
|
33
33
|
"@rspack/core": "^1.7.8",
|
|
34
34
|
"@webflow/cosmic-deploy-contract": "^1.0.2",
|
|
35
|
-
"@webflow/data-types": "
|
|
35
|
+
"@webflow/data-types": "*",
|
|
36
36
|
"ajv": "^8.17.1",
|
|
37
37
|
"archiver": "^5.3.1",
|
|
38
38
|
"babel-loader": "^10.0.0",
|
|
@@ -61,7 +61,7 @@
|
|
|
61
61
|
"semver": "^7.7.2",
|
|
62
62
|
"serve-handler": "^6.1.5",
|
|
63
63
|
"source-map-support": "^0.5.21",
|
|
64
|
-
"tar": "^7.
|
|
64
|
+
"tar": "^7.5.16",
|
|
65
65
|
"ts-checker-rspack-plugin": "^1.0.0",
|
|
66
66
|
"tsconfig-paths": "^4.2.0",
|
|
67
67
|
"tsconfig-paths-webpack-plugin": "^4.2.0",
|
|
@@ -90,7 +90,7 @@
|
|
|
90
90
|
"express": "^4.18.1",
|
|
91
91
|
"jest": "^29.3.1",
|
|
92
92
|
"nock": "13.3.1",
|
|
93
|
-
"tar": "^7.
|
|
93
|
+
"tar": "^7.5.16",
|
|
94
94
|
"ts-jest": "^29.4.9",
|
|
95
95
|
"ts-node": "^10.9.1",
|
|
96
96
|
"tsconfig": "*",
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"extends": [
|
|
3
|
-
"eslint:recommended",
|
|
4
|
-
"plugin:@typescript-eslint/eslint-recommended",
|
|
5
|
-
"plugin:@typescript-eslint/recommended"
|
|
6
|
-
],
|
|
7
|
-
"parser": "@typescript-eslint/parser",
|
|
8
|
-
"parserOptions": {
|
|
9
|
-
"project": "./tsconfig.json"
|
|
10
|
-
},
|
|
11
|
-
"plugins": ["@typescript-eslint", "promise"],
|
|
12
|
-
"rules": {
|
|
13
|
-
"@typescript-eslint/explicit-function-return-type": "off",
|
|
14
|
-
"@typescript-eslint/no-explicit-any": "off",
|
|
15
|
-
"@typescript-eslint/no-floating-promises": "error",
|
|
16
|
-
"@typescript-eslint/no-misused-promises": [
|
|
17
|
-
"error",
|
|
18
|
-
{ "checksVoidReturn": false }
|
|
19
|
-
],
|
|
20
|
-
"@typescript-eslint/no-unused-vars": "error",
|
|
21
|
-
"no-async-promise-executor": "error",
|
|
22
|
-
"require-await": "error",
|
|
23
|
-
"promise/catch-or-return": "error"
|
|
24
|
-
}
|
|
25
|
-
}
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"extends": [
|
|
3
|
-
"eslint:recommended",
|
|
4
|
-
"plugin:@typescript-eslint/eslint-recommended",
|
|
5
|
-
"plugin:@typescript-eslint/recommended"
|
|
6
|
-
],
|
|
7
|
-
"parser": "@typescript-eslint/parser",
|
|
8
|
-
"parserOptions": {
|
|
9
|
-
"project": "./tsconfig.json"
|
|
10
|
-
},
|
|
11
|
-
"plugins": ["@typescript-eslint", "promise"],
|
|
12
|
-
"rules": {
|
|
13
|
-
"@typescript-eslint/explicit-function-return-type": "off",
|
|
14
|
-
"@typescript-eslint/no-explicit-any": "off",
|
|
15
|
-
"@typescript-eslint/no-floating-promises": "error",
|
|
16
|
-
"@typescript-eslint/no-misused-promises": [
|
|
17
|
-
"error",
|
|
18
|
-
{ "checksVoidReturn": false }
|
|
19
|
-
],
|
|
20
|
-
"@typescript-eslint/no-unused-vars": "error",
|
|
21
|
-
"no-async-promise-executor": "error",
|
|
22
|
-
"require-await": "error",
|
|
23
|
-
"promise/catch-or-return": "error"
|
|
24
|
-
}
|
|
25
|
-
}
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"extends": [
|
|
3
|
-
"eslint:recommended",
|
|
4
|
-
"plugin:@typescript-eslint/eslint-recommended",
|
|
5
|
-
"plugin:@typescript-eslint/recommended"
|
|
6
|
-
],
|
|
7
|
-
"parser": "@typescript-eslint/parser",
|
|
8
|
-
"parserOptions": {
|
|
9
|
-
"project": "./tsconfig.json"
|
|
10
|
-
},
|
|
11
|
-
"plugins": ["@typescript-eslint", "promise"],
|
|
12
|
-
"rules": {
|
|
13
|
-
"@typescript-eslint/explicit-function-return-type": "off",
|
|
14
|
-
"@typescript-eslint/no-explicit-any": "off",
|
|
15
|
-
"@typescript-eslint/no-floating-promises": "error",
|
|
16
|
-
"@typescript-eslint/no-misused-promises": [
|
|
17
|
-
"error",
|
|
18
|
-
{ "checksVoidReturn": false }
|
|
19
|
-
],
|
|
20
|
-
"@typescript-eslint/no-unused-vars": "error",
|
|
21
|
-
"no-async-promise-executor": "error",
|
|
22
|
-
"require-await": "error",
|
|
23
|
-
"promise/catch-or-return": "error"
|
|
24
|
-
}
|
|
25
|
-
}
|