@canva/cli 0.0.1-beta.22 → 0.0.1-beta.24
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/cli.js +519 -389
- package/lib/cjs/index.cjs +4 -3
- package/lib/esm/index.mjs +4 -3
- package/package.json +3 -2
- package/templates/base/eslint.config.mjs +2 -25
- package/templates/base/package.json +1 -1
- package/templates/dam/backend/routers/dam.ts +6 -7
- package/templates/dam/eslint.config.mjs +3 -28
- package/templates/dam/package.json +3 -11
- package/templates/gen_ai/backend/routers/image.ts +8 -8
- package/templates/gen_ai/eslint.config.mjs +2 -25
- package/templates/gen_ai/package.json +2 -10
- package/templates/hello_world/eslint.config.mjs +2 -25
- package/templates/hello_world/package.json +2 -10
- package/templates/common/conf/eslint-local-i18n-rules/index.mjs +0 -181
- package/templates/common/conf/eslint_general.mjs +0 -317
- package/templates/common/conf/eslint_i18n.mjs +0 -41
|
@@ -22,48 +22,48 @@ const imageUrls: ImageResponse[] = [
|
|
|
22
22
|
fullsize: {
|
|
23
23
|
width: 1280,
|
|
24
24
|
height: 853,
|
|
25
|
-
url: "https://
|
|
25
|
+
url: "https://images.pexels.com/photos/1145720/pexels-photo-1145720.jpeg?auto=compress&cs=tinysrgb&w=1280&h=853&dpr=2",
|
|
26
26
|
},
|
|
27
27
|
thumbnail: {
|
|
28
28
|
width: 640,
|
|
29
29
|
height: 427,
|
|
30
|
-
url: "https://
|
|
30
|
+
url: "https://images.pexels.com/photos/1145720/pexels-photo-1145720.jpeg?auto=compress&cs=tinysrgb&w=640&h=427&dpr=2",
|
|
31
31
|
},
|
|
32
32
|
},
|
|
33
33
|
{
|
|
34
34
|
fullsize: {
|
|
35
35
|
width: 1280,
|
|
36
36
|
height: 853,
|
|
37
|
-
url: "https://
|
|
37
|
+
url: "https://images.pexels.com/photos/4010108/pexels-photo-4010108.jpeg?auto=compress&cs=tinysrgb&w=1280&h=863&dpr=2",
|
|
38
38
|
},
|
|
39
39
|
thumbnail: {
|
|
40
40
|
width: 640,
|
|
41
41
|
height: 427,
|
|
42
|
-
url: "https://
|
|
42
|
+
url: "https://images.pexels.com/photos/4010108/pexels-photo-4010108.jpeg?auto=compress&cs=tinysrgb&w=640&h=427&dpr=2",
|
|
43
43
|
},
|
|
44
44
|
},
|
|
45
45
|
{
|
|
46
46
|
fullsize: {
|
|
47
47
|
width: 1280,
|
|
48
48
|
height: 853,
|
|
49
|
-
url: "https://
|
|
49
|
+
url: "https://images.pexels.com/photos/1327496/pexels-photo-1327496.jpeg?auto=compress&cs=tinysrgb&w=1280&h=853&dpr=2",
|
|
50
50
|
},
|
|
51
51
|
thumbnail: {
|
|
52
52
|
width: 640,
|
|
53
53
|
height: 427,
|
|
54
|
-
url: "https://
|
|
54
|
+
url: "https://images.pexels.com/photos/1327496/pexels-photo-1327496.jpeg?auto=compress&cs=tinysrgb&w=640&h=427&dpr=2",
|
|
55
55
|
},
|
|
56
56
|
},
|
|
57
57
|
{
|
|
58
58
|
fullsize: {
|
|
59
59
|
width: 1280,
|
|
60
60
|
height: 853,
|
|
61
|
-
url: "https://
|
|
61
|
+
url: "https://images.pexels.com/photos/4693135/pexels-photo-4693135.jpeg?auto=compress&cs=tinysrgb&w=1280&h=853&dpr=2",
|
|
62
62
|
},
|
|
63
63
|
thumbnail: {
|
|
64
64
|
width: 640,
|
|
65
65
|
height: 427,
|
|
66
|
-
url: "https://
|
|
66
|
+
url: "https://images.pexels.com/photos/4693135/pexels-photo-4693135.jpeg?auto=compress&cs=tinysrgb&w=640&h=427&dpr=2",
|
|
67
67
|
},
|
|
68
68
|
},
|
|
69
69
|
];
|
|
@@ -1,17 +1,4 @@
|
|
|
1
|
-
import
|
|
2
|
-
import { fileURLToPath } from "node:url";
|
|
3
|
-
import js from "@eslint/js";
|
|
4
|
-
import { FlatCompat } from "@eslint/eslintrc";
|
|
5
|
-
import general from "./conf/eslint_general.mjs";
|
|
6
|
-
import i18n from "./conf/eslint_i18n.mjs";
|
|
7
|
-
|
|
8
|
-
const __filename = fileURLToPath(import.meta.url);
|
|
9
|
-
const __dirname = path.dirname(__filename);
|
|
10
|
-
const compat = new FlatCompat({
|
|
11
|
-
baseDirectory: __dirname,
|
|
12
|
-
recommendedConfig: js.configs.recommended,
|
|
13
|
-
allConfig: js.configs.all,
|
|
14
|
-
});
|
|
1
|
+
import canvaPlugin from "@canva/app-eslint-plugin";
|
|
15
2
|
|
|
16
3
|
export default [
|
|
17
4
|
{
|
|
@@ -23,15 +10,5 @@ export default [
|
|
|
23
10
|
"**/*.config.*",
|
|
24
11
|
],
|
|
25
12
|
},
|
|
26
|
-
...
|
|
27
|
-
"eslint:recommended",
|
|
28
|
-
"plugin:@typescript-eslint/recommended",
|
|
29
|
-
"plugin:@typescript-eslint/eslint-recommended",
|
|
30
|
-
"plugin:@typescript-eslint/strict",
|
|
31
|
-
"plugin:@typescript-eslint/stylistic",
|
|
32
|
-
"plugin:react/recommended",
|
|
33
|
-
"plugin:jest/recommended",
|
|
34
|
-
),
|
|
35
|
-
...general,
|
|
36
|
-
...i18n,
|
|
13
|
+
...canvaPlugin.configs.apps,
|
|
37
14
|
];
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
"dependencies": {
|
|
21
21
|
"@canva/app-i18n-kit": "^1.0.2",
|
|
22
22
|
"@canva/app-ui-kit": "^4.8.0",
|
|
23
|
-
"@canva/asset": "^2.
|
|
23
|
+
"@canva/asset": "^2.2.0",
|
|
24
24
|
"@canva/design": "^2.4.0",
|
|
25
25
|
"@canva/error": "^2.1.0",
|
|
26
26
|
"@canva/platform": "^2.1.0",
|
|
@@ -37,8 +37,7 @@
|
|
|
37
37
|
},
|
|
38
38
|
"devDependencies": {
|
|
39
39
|
"@canva/cli": ">= 0.0.1-beta.13 < 0.0.2",
|
|
40
|
-
"@eslint
|
|
41
|
-
"@eslint/js": "9.18.0",
|
|
40
|
+
"@canva/app-eslint-plugin": "^1.0.0-beta.3",
|
|
42
41
|
"@formatjs/cli": "6.3.15",
|
|
43
42
|
"@formatjs/ts-transformer": "3.13.27",
|
|
44
43
|
"@ngrok/ngrok": "1.4.1",
|
|
@@ -60,8 +59,6 @@
|
|
|
60
59
|
"@types/webpack": "5.28.5",
|
|
61
60
|
"@types/webpack-dev-server": "4.7.1",
|
|
62
61
|
"@types/webpack-env": "1.18.5",
|
|
63
|
-
"@typescript-eslint/eslint-plugin": "8.20.0",
|
|
64
|
-
"@typescript-eslint/parser": "8.20.0",
|
|
65
62
|
"chalk": "4.1.2",
|
|
66
63
|
"cli-table3": "0.6.5",
|
|
67
64
|
"css-loader": "7.1.2",
|
|
@@ -69,11 +66,6 @@
|
|
|
69
66
|
"cssnano": "7.0.6",
|
|
70
67
|
"debug": "4.4.0",
|
|
71
68
|
"dotenv": "16.4.7",
|
|
72
|
-
"eslint": "9.18.0",
|
|
73
|
-
"eslint-plugin-formatjs": "5.2.8",
|
|
74
|
-
"eslint-plugin-jest": "28.11.0",
|
|
75
|
-
"eslint-plugin-react": "7.37.4",
|
|
76
|
-
"eslint-plugin-unicorn": "56.0.1",
|
|
77
69
|
"exponential-backoff": "3.1.1",
|
|
78
70
|
"express": "4.21.2",
|
|
79
71
|
"express-basic-auth": "1.2.1",
|
|
@@ -1,17 +1,4 @@
|
|
|
1
|
-
import
|
|
2
|
-
import { fileURLToPath } from "node:url";
|
|
3
|
-
import js from "@eslint/js";
|
|
4
|
-
import { FlatCompat } from "@eslint/eslintrc";
|
|
5
|
-
import general from "./conf/eslint_general.mjs";
|
|
6
|
-
import i18n from "./conf/eslint_i18n.mjs";
|
|
7
|
-
|
|
8
|
-
const __filename = fileURLToPath(import.meta.url);
|
|
9
|
-
const __dirname = path.dirname(__filename);
|
|
10
|
-
const compat = new FlatCompat({
|
|
11
|
-
baseDirectory: __dirname,
|
|
12
|
-
recommendedConfig: js.configs.recommended,
|
|
13
|
-
allConfig: js.configs.all,
|
|
14
|
-
});
|
|
1
|
+
import canvaPlugin from "@canva/app-eslint-plugin";
|
|
15
2
|
|
|
16
3
|
export default [
|
|
17
4
|
{
|
|
@@ -23,15 +10,5 @@ export default [
|
|
|
23
10
|
"**/*.config.*",
|
|
24
11
|
],
|
|
25
12
|
},
|
|
26
|
-
...
|
|
27
|
-
"eslint:recommended",
|
|
28
|
-
"plugin:@typescript-eslint/recommended",
|
|
29
|
-
"plugin:@typescript-eslint/eslint-recommended",
|
|
30
|
-
"plugin:@typescript-eslint/strict",
|
|
31
|
-
"plugin:@typescript-eslint/stylistic",
|
|
32
|
-
"plugin:react/recommended",
|
|
33
|
-
"plugin:jest/recommended",
|
|
34
|
-
),
|
|
35
|
-
...general,
|
|
36
|
-
...i18n,
|
|
13
|
+
...canvaPlugin.configs.apps,
|
|
37
14
|
];
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
"dependencies": {
|
|
22
22
|
"@canva/app-i18n-kit": "^1.0.2",
|
|
23
23
|
"@canva/app-ui-kit": "^4.8.0",
|
|
24
|
-
"@canva/asset": "^2.
|
|
24
|
+
"@canva/asset": "^2.2.0",
|
|
25
25
|
"@canva/design": "^2.4.0",
|
|
26
26
|
"@canva/error": "^2.1.0",
|
|
27
27
|
"@canva/platform": "^2.1.0",
|
|
@@ -32,8 +32,7 @@
|
|
|
32
32
|
},
|
|
33
33
|
"devDependencies": {
|
|
34
34
|
"@canva/cli": ">= 0.0.1-beta.13 < 0.0.2",
|
|
35
|
-
"@eslint
|
|
36
|
-
"@eslint/js": "9.18.0",
|
|
35
|
+
"@canva/app-eslint-plugin": "^1.0.0-beta.3",
|
|
37
36
|
"@formatjs/cli": "6.3.15",
|
|
38
37
|
"@formatjs/ts-transformer": "3.13.27",
|
|
39
38
|
"@ngrok/ngrok": "1.4.1",
|
|
@@ -51,8 +50,6 @@
|
|
|
51
50
|
"@types/react": "18.3.12",
|
|
52
51
|
"@types/react-dom": "18.3.1",
|
|
53
52
|
"@types/webpack-env": "1.18.5",
|
|
54
|
-
"@typescript-eslint/eslint-plugin": "8.20.0",
|
|
55
|
-
"@typescript-eslint/parser": "8.20.0",
|
|
56
53
|
"chalk": "4.1.2",
|
|
57
54
|
"cli-table3": "0.6.5",
|
|
58
55
|
"css-loader": "7.1.2",
|
|
@@ -60,11 +57,6 @@
|
|
|
60
57
|
"cssnano": "7.0.6",
|
|
61
58
|
"debug": "4.4.0",
|
|
62
59
|
"dotenv": "16.4.7",
|
|
63
|
-
"eslint": "9.18.0",
|
|
64
|
-
"eslint-plugin-formatjs": "5.2.8",
|
|
65
|
-
"eslint-plugin-jest": "28.11.0",
|
|
66
|
-
"eslint-plugin-react": "7.37.4",
|
|
67
|
-
"eslint-plugin-unicorn": "56.0.1",
|
|
68
60
|
"express": "4.21.2",
|
|
69
61
|
"express-basic-auth": "1.2.1",
|
|
70
62
|
"jest": "29.7.0",
|
|
@@ -1,181 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* ESLint rule that identifies and flags untranslated user-facing strings in object properties.
|
|
3
|
-
*
|
|
4
|
-
* This rule helps maintain internationalization consistency by detecting untranslated
|
|
5
|
-
* strings in specific object properties (default: 'label'). It suggests using
|
|
6
|
-
* intl.formatMessage for proper translation.
|
|
7
|
-
*
|
|
8
|
-
* Note: The rule is currently implemented as a local rule, with plans to publish as
|
|
9
|
-
* an npm package to make it available to the broader development community.
|
|
10
|
-
*
|
|
11
|
-
* @example
|
|
12
|
-
* // ❌ Incorrect - Untranslated strings
|
|
13
|
-
* const options = [
|
|
14
|
-
* { value: "inbox", label: "Inbox" },
|
|
15
|
-
* { value: "starred", label: "Starred messages" },
|
|
16
|
-
* { value: "spam", label: "Spam folder" }
|
|
17
|
-
* ];
|
|
18
|
-
*
|
|
19
|
-
* // ✅ Correct - Using intl.formatMessage with descriptions
|
|
20
|
-
* const options = [
|
|
21
|
-
* {
|
|
22
|
-
* value: "inbox",
|
|
23
|
-
* label: intl.formatMessage({
|
|
24
|
-
* defaultMessage: "Inbox",
|
|
25
|
-
* description: "Label for main message inbox folder option"
|
|
26
|
-
* })
|
|
27
|
-
* },
|
|
28
|
-
* {
|
|
29
|
-
* value: "starred",
|
|
30
|
-
* label: intl.formatMessage({
|
|
31
|
-
* defaultMessage: "Starred messages",
|
|
32
|
-
* description: "Label for folder containing messages marked as important"
|
|
33
|
-
* })
|
|
34
|
-
* },
|
|
35
|
-
* {
|
|
36
|
-
* value: "spam",
|
|
37
|
-
* label: intl.formatMessage({
|
|
38
|
-
* defaultMessage: "Spam folder",
|
|
39
|
-
* description: "Label for folder containing filtered spam messages"
|
|
40
|
-
* })
|
|
41
|
-
* }
|
|
42
|
-
* ];
|
|
43
|
-
*
|
|
44
|
-
* @see https://www.canva.dev/docs/apps/localization/
|
|
45
|
-
*/
|
|
46
|
-
export default {
|
|
47
|
-
rules: {
|
|
48
|
-
"enforce-object-property-translation": {
|
|
49
|
-
meta: {
|
|
50
|
-
type: "problem",
|
|
51
|
-
docs: {
|
|
52
|
-
description:
|
|
53
|
-
"Enforce translation of specific properties using intl.formatMessage",
|
|
54
|
-
category: "Possible Errors",
|
|
55
|
-
recommended: true,
|
|
56
|
-
},
|
|
57
|
-
fixable: "code",
|
|
58
|
-
schema: [
|
|
59
|
-
{
|
|
60
|
-
type: "object",
|
|
61
|
-
properties: {
|
|
62
|
-
properties: {
|
|
63
|
-
type: "array",
|
|
64
|
-
items: { type: "string" },
|
|
65
|
-
default: ["label"],
|
|
66
|
-
},
|
|
67
|
-
intlObjectName: {
|
|
68
|
-
type: "string",
|
|
69
|
-
default: "intl",
|
|
70
|
-
},
|
|
71
|
-
},
|
|
72
|
-
additionalProperties: false,
|
|
73
|
-
},
|
|
74
|
-
],
|
|
75
|
-
messages: {
|
|
76
|
-
untranslatedProperty: `If "{{ originalMessage }}" is a user-facing string, you should translate it using "intl.formatMessage". See https://www.canva.dev/docs/apps/localization/.`,
|
|
77
|
-
},
|
|
78
|
-
},
|
|
79
|
-
create(context) {
|
|
80
|
-
const config = context.options[0] || {};
|
|
81
|
-
const propertiesToCheck = config.properties || ["label"];
|
|
82
|
-
const intlObjectName = config.intlObjectName || "intl";
|
|
83
|
-
|
|
84
|
-
function getTemplateLiteralString(node) {
|
|
85
|
-
const src = context.getSourceCode();
|
|
86
|
-
return src.getText(node);
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
// Extract string content from different node types
|
|
90
|
-
function extractStringContent(node) {
|
|
91
|
-
if (!node) return [];
|
|
92
|
-
|
|
93
|
-
switch (node.type) {
|
|
94
|
-
// label: "Foo"
|
|
95
|
-
case "Literal":
|
|
96
|
-
return typeof node.value === "string"
|
|
97
|
-
? [{ node, value: node.value }]
|
|
98
|
-
: [];
|
|
99
|
-
|
|
100
|
-
// label: `Foo ${bar}`
|
|
101
|
-
case "TemplateLiteral":
|
|
102
|
-
return [{ node, value: getTemplateLiteralString(node) }];
|
|
103
|
-
// label: foo || "Bar"
|
|
104
|
-
case "LogicalExpression": {
|
|
105
|
-
if (node.operator === "||") {
|
|
106
|
-
return [
|
|
107
|
-
...extractStringContent(node.left),
|
|
108
|
-
...extractStringContent(node.right),
|
|
109
|
-
];
|
|
110
|
-
}
|
|
111
|
-
return [];
|
|
112
|
-
}
|
|
113
|
-
// label: "Foo" + "Bar" + "Baz"
|
|
114
|
-
case "BinaryExpression":
|
|
115
|
-
if (node.operator === "+") {
|
|
116
|
-
return [
|
|
117
|
-
...extractStringContent(node.left),
|
|
118
|
-
...extractStringContent(node.right),
|
|
119
|
-
];
|
|
120
|
-
}
|
|
121
|
-
return [];
|
|
122
|
-
// label: foo ? "Foo" : "Bar"
|
|
123
|
-
case "ConditionalExpression":
|
|
124
|
-
return [
|
|
125
|
-
...extractStringContent(node.consequent),
|
|
126
|
-
...extractStringContent(node.alternate),
|
|
127
|
-
];
|
|
128
|
-
|
|
129
|
-
default:
|
|
130
|
-
return [];
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
function isTranslated(node) {
|
|
135
|
-
return (
|
|
136
|
-
node.parent.type === "CallExpression" &&
|
|
137
|
-
node.parent.callee.type === "MemberExpression" &&
|
|
138
|
-
node.parent.callee.object.name === intlObjectName &&
|
|
139
|
-
node.parent.callee.property.name === "formatMessage"
|
|
140
|
-
);
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
return {
|
|
144
|
-
Property(node) {
|
|
145
|
-
const keyName = node.key.name || node.key.value;
|
|
146
|
-
if (propertiesToCheck.includes(keyName)) {
|
|
147
|
-
const results = extractStringContent(node.value);
|
|
148
|
-
if (!results) return;
|
|
149
|
-
results.forEach((result) => {
|
|
150
|
-
const { node: stringNode, value: stringValue } = result;
|
|
151
|
-
|
|
152
|
-
if (!isTranslated(stringNode)) {
|
|
153
|
-
context.report({
|
|
154
|
-
node: stringNode,
|
|
155
|
-
messageId: "untranslatedProperty",
|
|
156
|
-
data: {
|
|
157
|
-
property: keyName,
|
|
158
|
-
originalMessage:
|
|
159
|
-
stringValue.length > 40
|
|
160
|
-
? stringValue.split(" ").slice(0, 4).join(" ") + "..."
|
|
161
|
-
: stringValue,
|
|
162
|
-
intlObjectName,
|
|
163
|
-
},
|
|
164
|
-
fix(fixer) {
|
|
165
|
-
const newText = `${intlObjectName}.formatMessage({
|
|
166
|
-
defaultMessage: ${JSON.stringify(stringValue)},
|
|
167
|
-
// TODO: Provide a meaningful description for translators
|
|
168
|
-
description: ""
|
|
169
|
-
})`;
|
|
170
|
-
return fixer.replaceText(stringNode, newText);
|
|
171
|
-
},
|
|
172
|
-
});
|
|
173
|
-
}
|
|
174
|
-
});
|
|
175
|
-
}
|
|
176
|
-
},
|
|
177
|
-
};
|
|
178
|
-
},
|
|
179
|
-
},
|
|
180
|
-
},
|
|
181
|
-
};
|