@webflow/webflow-cli 1.8.37 → 1.8.39

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.
@@ -10,22 +10,13 @@ const webflowOverrides = {
10
10
  base: "${COSMIC_MOUNT_PATH}",
11
11
  output: "server",
12
12
  adapter: cloudflare({
13
+ imageService: "custom",
13
14
  platformProxy: {
14
15
  enabled: true
15
16
  }
16
17
  }),
17
18
 
18
19
  integrations: [react()],
19
-
20
- build: {
21
- assetsPrefix: "${COSMIC_DEPLOY_URL}${COSMIC_MOUNT_PATH}"
22
- }
23
- };
24
-
25
- // https://astro.build/config
26
- export default defineConfig({
27
- ...userConfig,
28
- ...webflowOverrides,
29
20
  vite: {
30
21
  ...userConfig.vite,
31
22
  resolve: {
@@ -37,4 +28,25 @@ export default defineConfig({
37
28
  } : undefined,
38
29
  },
39
30
  },
40
- });
31
+
32
+ build: {
33
+ assetsPrefix: "${COSMIC_DEPLOY_URL}${COSMIC_MOUNT_PATH}"
34
+ },
35
+
36
+ image: {
37
+ ...userConfig.image,
38
+ service: {
39
+ entrypoint: "./webflow-loader.ts",
40
+ config: {
41
+ deployUrl: "${COSMIC_DEPLOY_URL}",
42
+ mountPath: "${COSMIC_MOUNT_PATH}"
43
+ }
44
+ },
45
+ }
46
+ };
47
+
48
+ // https://astro.build/config
49
+ export default defineConfig({
50
+ ...userConfig,
51
+ ...webflowOverrides,
52
+ });
@@ -0,0 +1,112 @@
1
+ import type { ExternalImageService, ImageTransform, AstroConfig } from "astro";
2
+
3
+ function normalizeSrc(src: string, deployUrl?: string, mountPath?: string) {
4
+ // For local assets, include the mount path but not the deploy url, and remove the leading slash
5
+ if (deployUrl && src.startsWith(deployUrl)) {
6
+ return `${src.slice(deployUrl.length)}`.slice(1);
7
+ } else if (mountPath && src.startsWith(mountPath)) {
8
+ return src.slice(1);
9
+ } else if (src.startsWith("/")) {
10
+ return `${mountPath}${src}`.slice(1);
11
+ }
12
+ return src;
13
+ }
14
+
15
+ // Default implementation copied from Astro's baseService
16
+ function getTargetDimensions(options: ImageTransform) {
17
+ let targetWidth = options.width;
18
+ let targetHeight = options.height;
19
+
20
+ // For ESM imported images, calculate missing dimensions based on aspect ratio
21
+ if (
22
+ typeof options.src === "object" &&
23
+ "width" in options.src &&
24
+ "height" in options.src
25
+ ) {
26
+ const aspectRatio = options.src.width / options.src.height;
27
+ if (targetHeight && !targetWidth) {
28
+ targetWidth = Math.round(targetHeight * aspectRatio);
29
+ } else if (targetWidth && !targetHeight) {
30
+ targetHeight = Math.round(targetWidth / aspectRatio);
31
+ } else if (!targetWidth && !targetHeight) {
32
+ targetWidth = options.src.width;
33
+ targetHeight = options.src.height;
34
+ }
35
+ }
36
+
37
+ return {
38
+ targetWidth,
39
+ targetHeight,
40
+ };
41
+ }
42
+
43
+ const cloudflareLoader: ExternalImageService = {
44
+ getURL(options: ImageTransform, imageConfig: AstroConfig["image"]) {
45
+ const normalizedSrc = normalizeSrc(
46
+ typeof options.src === "object" ? options.src.src : options.src,
47
+ imageConfig.service.config.deployUrl,
48
+ imageConfig.service.config.mountPath
49
+ );
50
+ // Our cloudflare zone doesn't allow optimizing external images for security reasons, so just load the original image
51
+ // For now, also skip optimization for images hosted on regular webflow sites (cdn.website-files.com)
52
+ // because optimizing them would result in two bandwidth charges: one from the website-files zone (for the full image)
53
+ // and one from the cosmic.webflow.services zone (for the resized image)
54
+ if (
55
+ normalizedSrc.startsWith("http://") ||
56
+ normalizedSrc.startsWith("https://")
57
+ ) {
58
+ return normalizedSrc;
59
+ }
60
+
61
+ const supportedOptions = ["width", "height", "quality", "format"];
62
+ const params = [];
63
+ for (const option of supportedOptions) {
64
+ if (options[option]) {
65
+ params.push(`${option}=${options[option]}`);
66
+ }
67
+ }
68
+
69
+ const workerUrl = imageConfig.service.config.deployUrl;
70
+ // Skip resizing svgs, since it doesn't do anything
71
+ const isSvg =
72
+ typeof options.src === "object"
73
+ ? options.src.format === "svg"
74
+ : options.src.endsWith(".svg");
75
+ if (isSvg || params.length === 0) {
76
+ return `${workerUrl}/${normalizedSrc}`;
77
+ }
78
+
79
+ const paramsString = params.join(",");
80
+ return `${workerUrl}/cdn-cgi/image/${paramsString}/${normalizedSrc}`;
81
+ },
82
+
83
+ // Default implementation copied from Astro's baseService
84
+ getHTMLAttributes(options: ImageTransform) {
85
+ const { targetWidth, targetHeight } = getTargetDimensions(options);
86
+ const {
87
+ src,
88
+ width,
89
+ height,
90
+ format,
91
+ quality,
92
+ densities,
93
+ widths,
94
+ formats,
95
+ layout,
96
+ priority,
97
+ fit,
98
+ position,
99
+ ...attributes
100
+ } = options;
101
+
102
+ return {
103
+ ...attributes,
104
+ width: targetWidth,
105
+ height: targetHeight,
106
+ loading: attributes.loading ?? "lazy",
107
+ decoding: attributes.decoding ?? "async",
108
+ };
109
+ },
110
+ };
111
+
112
+ export default cloudflareLoader;
@@ -0,0 +1,5 @@
1
+ // For tests
2
+ export default {
3
+ basePath: "",
4
+ assetPrefix: "",
5
+ };
@@ -2,8 +2,15 @@ import type { NextConfig } from "next";
2
2
  import userConfig from './clouduser.next.config';
3
3
 
4
4
  const webflowOverrides: NextConfig = {
5
- basePath: "${COSMIC_MOUNT_PATH}",
6
- assetPrefix: "${COSMIC_DEPLOY_URL}${COSMIC_MOUNT_PATH}",
5
+ basePath: '${COSMIC_MOUNT_PATH}',
6
+ assetPrefix: '${COSMIC_DEPLOY_URL}${COSMIC_MOUNT_PATH}',
7
+ images: {
8
+ ...userConfig.images,
9
+ // TODO: determine whether any of the non-custom loader options (imgix, cloudinary, akamai) work
10
+ // and if so allow them to be used here
11
+ loader: 'custom',
12
+ loaderFile: userConfig.images?.loaderFile || './webflow-loader.ts',
13
+ },
7
14
  };
8
15
 
9
16
  const nextConfig: NextConfig = {
@@ -0,0 +1,36 @@
1
+ import config from './next.config';
2
+
3
+ const basePath = config.basePath || '';
4
+ const assetPrefix = config.assetPrefix || basePath;
5
+
6
+ function normalizeSrc(src: string) {
7
+ // For local assets, include the base path but not the asset prefix, and remove the leading slash
8
+ if (assetPrefix && src.startsWith(assetPrefix)) {
9
+ return `${basePath}${src.slice(assetPrefix.length)}`.slice(1);
10
+ } else if (basePath && src.startsWith(basePath)) {
11
+ return src.slice(1);
12
+ } else if (src.startsWith('/')) {
13
+ return `${basePath}${src}`.slice(1);
14
+ }
15
+ return src;
16
+ }
17
+
18
+ export default function cloudflareLoader({ src, width, quality }: { src: string; width: number; quality?: number }) {
19
+ const normalizedSrc = normalizeSrc(src);
20
+
21
+ // Our cloudflare zone doesn't allow optimizing external images for security reasons, so just load the original image
22
+ // For now, also skip optimization for images hosted on regular webflow sites (cdn.website-files.com)
23
+ // because optimizing them would result in two bandwidth charges: one from the website-files zone (for the full image)
24
+ // and one from the cosmic.webflow.services zone (for the resized image)
25
+ if (normalizedSrc.startsWith('http://') || normalizedSrc.startsWith('https://')) {
26
+ return normalizedSrc;
27
+ }
28
+
29
+ const params = [`width=${width}`];
30
+ if (quality) {
31
+ params.push(`quality=${quality}`);
32
+ }
33
+ const paramsString = params.join(',');
34
+ const workerUrl = `${assetPrefix.slice(0, -basePath.length)}`;
35
+ return `${workerUrl}/cdn-cgi/image/${paramsString}/${normalizedSrc}`;
36
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@webflow/webflow-cli",
3
- "version": "1.8.37",
3
+ "version": "1.8.39",
4
4
  "license": "MIT",
5
5
  "bin": {
6
6
  "webflow": "./dist/index.js"
@@ -24,8 +24,8 @@
24
24
  "@babel/preset-react": "^7.26.3",
25
25
  "@babel/preset-typescript": "^7.27.0",
26
26
  "@dotenvx/dotenvx": "^1.44.1",
27
- "@module-federation/enhanced": "^0.18.0",
28
- "@webflow/data-types": "0.0.11",
27
+ "@module-federation/enhanced": "0.18.3",
28
+ "@webflow/data-types": "0.0.12",
29
29
  "ajv": "^8.17.1",
30
30
  "archiver": "^5.3.1",
31
31
  "babel-loader": "^10.0.0",
@@ -37,6 +37,7 @@
37
37
  "env-paths": "^3.0.0",
38
38
  "fast-glob": "^3.3.3",
39
39
  "filenamify": "^6.0.0",
40
+ "fork-ts-checker-webpack-plugin": "9.1.0",
40
41
  "form-data": "4.0.0",
41
42
  "fs-extra": "^11.3.0",
42
43
  "inquirer": "^9.1.4",
@@ -79,6 +80,7 @@
79
80
  "@types/serve-handler": "^6.1.1",
80
81
  "@types/source-map": "^0.5.2",
81
82
  "@types/webpack-node-externals": "^3.0.4",
83
+ "astro": "^5.7.0",
82
84
  "eslint-config-custom": "*",
83
85
  "express": "^4.18.1",
84
86
  "jest": "^29.3.1",