zenn-model 0.2.6-alpha.2 → 0.2.6-alpha.3
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/lib/index.js +3 -3
- package/lib/utils.js +26 -52
- package/package.json +15 -15
package/lib/index.js
CHANGED
|
@@ -16,13 +16,13 @@ var __copyProps = (to, from, except, desc) => {
|
|
|
16
16
|
return to;
|
|
17
17
|
};
|
|
18
18
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
-
var
|
|
20
|
-
__export(
|
|
19
|
+
var index_exports = {};
|
|
20
|
+
__export(index_exports, {
|
|
21
21
|
validateArticle: () => validateArticle,
|
|
22
22
|
validateBook: () => validateBook,
|
|
23
23
|
validateBookChapter: () => validateBookChapter
|
|
24
24
|
});
|
|
25
|
-
module.exports = __toCommonJS(
|
|
25
|
+
module.exports = __toCommonJS(index_exports);
|
|
26
26
|
var import_utils = require("./utils");
|
|
27
27
|
function getValidationErrors(item, validators) {
|
|
28
28
|
return validators.reduce((errors, validator) => {
|
package/lib/utils.js
CHANGED
|
@@ -65,13 +65,11 @@ module.exports = __toCommonJS(utils_exports);
|
|
|
65
65
|
var import_emoji_regex = __toESM(require("emoji-regex"));
|
|
66
66
|
var cheerio = __toESM(require("cheerio"));
|
|
67
67
|
function validateSlug(slug) {
|
|
68
|
-
if (!slug)
|
|
69
|
-
return false;
|
|
68
|
+
if (!slug) return false;
|
|
70
69
|
return /^[0-9a-z\-_]{12,50}$/.test(slug);
|
|
71
70
|
}
|
|
72
71
|
function validateChapterSlug(slug) {
|
|
73
|
-
if (!slug)
|
|
74
|
-
return false;
|
|
72
|
+
if (!slug) return false;
|
|
75
73
|
return /^[0-9a-z\-_]{1,50}$/.test(slug) || /^[0-9]+.[0-9a-z\-_]{1,50}$/.test(slug);
|
|
76
74
|
}
|
|
77
75
|
function isAnyText(val) {
|
|
@@ -94,8 +92,7 @@ const validateTitleLength = {
|
|
|
94
92
|
isCritical: true,
|
|
95
93
|
getMessage: () => "\u30BF\u30A4\u30C8\u30EB\u306F70\u5B57\u4EE5\u5185\u306B\u3057\u3066\u304F\u3060\u3055\u3044",
|
|
96
94
|
isValid: ({ title }) => {
|
|
97
|
-
if (!isAnyText(title))
|
|
98
|
-
return true;
|
|
95
|
+
if (!isAnyText(title)) return true;
|
|
99
96
|
return title.length <= 70;
|
|
100
97
|
}
|
|
101
98
|
};
|
|
@@ -113,10 +110,8 @@ const validatePublishedAtParse = {
|
|
|
113
110
|
isCritical: true,
|
|
114
111
|
getMessage: () => "published_at\uFF08\u516C\u958B\u65E5\u6642\uFF09\u306F `YYYY-MM-DD` \u307E\u305F\u306F `YYYY-MM-DD hh:mm` \u306E\u30D5\u30A9\u30FC\u30DE\u30C3\u30C8\u3067\u6307\u5B9A\u3057\u3066\u304F\u3060\u3055\u3044",
|
|
115
112
|
isValid: ({ published_at: publishedAt }) => {
|
|
116
|
-
if (publishedAt == void 0)
|
|
117
|
-
|
|
118
|
-
if (!publishedAt.match(PUBLISHED_AT_PATTERN))
|
|
119
|
-
return false;
|
|
113
|
+
if (publishedAt == void 0) return true;
|
|
114
|
+
if (!publishedAt.match(PUBLISHED_AT_PATTERN)) return false;
|
|
120
115
|
return !isNaN(Date.parse(publishedAt.replace(" ", "T")));
|
|
121
116
|
}
|
|
122
117
|
};
|
|
@@ -125,10 +120,8 @@ const validatePublishedAtSchedule = {
|
|
|
125
120
|
isCritical: true,
|
|
126
121
|
getMessage: () => "published_at\uFF08\u516C\u958B\u65E5\u6642\uFF09\u306B\u672A\u6765\u306E\u65E5\u6642\u3092\u6307\u5B9A\u3059\u308B\u5834\u5408\u306F\u3001published\uFF08\u516C\u958B\u8A2D\u5B9A\uFF09\u306B true \u3092\u6307\u5B9A\u3057\u3066\u304F\u3060\u3055\u3044\uFF08\u516C\u958B\u65E5\u6642\u3092\u904E\u304E\u308B\u3068Zenn\u306E\u30B5\u30FC\u30D3\u30B9\u4E0A\u3067\u81EA\u52D5\u7684\u306B\u516C\u958B\u3055\u308C\u307E\u3059\uFF09",
|
|
127
122
|
isValid: ({ published, published_at: publishedAt }) => {
|
|
128
|
-
if (published === true)
|
|
129
|
-
|
|
130
|
-
if (publishedAt == null)
|
|
131
|
-
return true;
|
|
123
|
+
if (published === true) return true;
|
|
124
|
+
if (publishedAt == null) return true;
|
|
132
125
|
if (isNaN(Date.parse(publishedAt))) {
|
|
133
126
|
return true;
|
|
134
127
|
} else {
|
|
@@ -143,8 +136,7 @@ const validateArticleType = {
|
|
|
143
136
|
detailUrlText: "\u8A73\u7D30\u3092\u958B\u304F",
|
|
144
137
|
getMessage: () => "type\uFF08\u8A18\u4E8B\u306E\u30BF\u30A4\u30D7\uFF09\u306B tech \u3082\u3057\u304F\u306F idea \u3092\u6307\u5B9A\u3057\u3066\u304F\u3060\u3055\u3044\u3002\u6280\u8853\u8A18\u4E8B\u306E\u5834\u5408\u306F tech \u3092\u6307\u5B9A\u3057\u3066\u304F\u3060\u3055\u3044",
|
|
145
138
|
isValid: ({ type }) => {
|
|
146
|
-
if (!type)
|
|
147
|
-
return false;
|
|
139
|
+
if (!type) return false;
|
|
148
140
|
return type === "tech" || type === "idea";
|
|
149
141
|
}
|
|
150
142
|
};
|
|
@@ -160,12 +152,10 @@ const validateEmojiFormat = {
|
|
|
160
152
|
isCritical: true,
|
|
161
153
|
getMessage: () => "\u7D75\u6587\u5B57\uFF08emoji\uFF09\u30921\u3064\u3060\u3051\u6307\u5B9A\u3057\u3066\u304F\u3060\u3055\u3044",
|
|
162
154
|
isValid: ({ emoji }) => {
|
|
163
|
-
if (!isAnyText(emoji))
|
|
164
|
-
return true;
|
|
155
|
+
if (!isAnyText(emoji)) return true;
|
|
165
156
|
const emojiRegex = (0, import_emoji_regex.default)();
|
|
166
157
|
const matches = emoji.match(emojiRegex);
|
|
167
|
-
if (!matches || !matches[0] || matches[1])
|
|
168
|
-
return false;
|
|
158
|
+
if (!matches || !matches[0] || matches[1]) return false;
|
|
169
159
|
return true;
|
|
170
160
|
}
|
|
171
161
|
};
|
|
@@ -174,8 +164,7 @@ const validateMissingTopics = {
|
|
|
174
164
|
isCritical: false,
|
|
175
165
|
getMessage: () => 'topics\uFF08\u8A18\u4E8B\u306B\u95A2\u9023\u3059\u308B\u8A00\u8A9E\u3084\u6280\u8853\uFF09\u3092\u914D\u5217\u3067\u6307\u5B9A\u3057\u3066\u304F\u3060\u3055\u3044\u3002\u4F8B\uFF09["react", "javascript"]',
|
|
176
166
|
isValid: ({ topics }) => {
|
|
177
|
-
if (!Array.isArray(topics))
|
|
178
|
-
return false;
|
|
167
|
+
if (!Array.isArray(topics)) return false;
|
|
179
168
|
return topics.length > 0;
|
|
180
169
|
}
|
|
181
170
|
};
|
|
@@ -184,8 +173,7 @@ const validateTooManyTopics = {
|
|
|
184
173
|
isCritical: true,
|
|
185
174
|
getMessage: () => "topics\u306F\u6700\u59275\u3064\u307E\u3067\u6307\u5B9A\u3067\u304D\u307E\u3059",
|
|
186
175
|
isValid: ({ topics }) => {
|
|
187
|
-
if (!Array.isArray(topics))
|
|
188
|
-
return true;
|
|
176
|
+
if (!Array.isArray(topics)) return true;
|
|
189
177
|
return topics.length <= 5;
|
|
190
178
|
}
|
|
191
179
|
};
|
|
@@ -194,8 +182,7 @@ const validateTopicType = {
|
|
|
194
182
|
isCritical: true,
|
|
195
183
|
getMessage: () => "topics\u306F\u5168\u3066\u6587\u5B57\u5217\u3067\u6307\u5B9A\u3057\u3066\u304F\u3060\u3055\u3044",
|
|
196
184
|
isValid: ({ topics }) => {
|
|
197
|
-
if (!Array.isArray(topics))
|
|
198
|
-
return true;
|
|
185
|
+
if (!Array.isArray(topics)) return true;
|
|
199
186
|
return topics.every((t) => typeof t === "string" && t.length > 0);
|
|
200
187
|
}
|
|
201
188
|
};
|
|
@@ -204,10 +191,8 @@ const validateTopicLength = {
|
|
|
204
191
|
isCritical: true,
|
|
205
192
|
getMessage: () => "topics\u306F18\u5B57\u4EE5\u5185\u306B\u3057\u3066\u304F\u3060\u3055\u3044",
|
|
206
193
|
isValid: ({ topics }) => {
|
|
207
|
-
if (!Array.isArray(topics))
|
|
208
|
-
|
|
209
|
-
if (topics.some((t) => typeof t !== "string"))
|
|
210
|
-
return true;
|
|
194
|
+
if (!Array.isArray(topics)) return true;
|
|
195
|
+
if (topics.some((t) => typeof t !== "string")) return true;
|
|
211
196
|
return topics.every((t) => typeof t === "string" && t.length <= 18);
|
|
212
197
|
}
|
|
213
198
|
};
|
|
@@ -215,8 +200,7 @@ const validateInvalidTopicLetters = {
|
|
|
215
200
|
type: "invalid-topic-letters",
|
|
216
201
|
getMessage: () => "topics\u306B\u8A18\u53F7\u3084\u30B9\u30DA\u30FC\u30B9\u3092\u4F7F\u7528\u3059\u308B\u3053\u3068\u306F\u3067\u304D\u307E\u305B\u3093\u3002\u4F8B\u3048\u3070C++\u306F\u300Ccpp\u300D\u3001C#\u306F\u300Ccsharp\u300D\u3068\u8A18\u8F09\u3057\u3066\u304F\u3060\u3055\u3044",
|
|
217
202
|
isValid: ({ topics }) => {
|
|
218
|
-
if (!Array.isArray(topics))
|
|
219
|
-
return true;
|
|
203
|
+
if (!Array.isArray(topics)) return true;
|
|
220
204
|
const anyInvalidFormat = topics.some(
|
|
221
205
|
(t) => typeof t === "string" && t.match(/[ -/:-@[-`{-~]/g)
|
|
222
206
|
);
|
|
@@ -233,8 +217,7 @@ const validatePublicationName = {
|
|
|
233
217
|
isCritical: true,
|
|
234
218
|
getMessage: () => "Publication\u306E\u540D\u524D\u304C\u4E0D\u6B63\u3067\u3059\u3002\u5C0F\u6587\u5B57\u306E\u534A\u89D2\u82F1\u6570\u5B57\uFF08a-z0-9\uFF09\u3001\u30A2\u30F3\u30C0\u30FC\u30B9\u30B3\u30A2\uFF08_\uFF09\u306E2\u301C15\u5B57\u306E\u7D44\u307F\u5408\u308F\u305B\u306B\u3057\u3066\u304F\u3060\u3055\u3044",
|
|
235
219
|
isValid: ({ publication_name }) => {
|
|
236
|
-
if (!publication_name)
|
|
237
|
-
return true;
|
|
220
|
+
if (!publication_name) return true;
|
|
238
221
|
return /^[0-9a-z_]{2,15}$/.test(publication_name);
|
|
239
222
|
}
|
|
240
223
|
};
|
|
@@ -255,10 +238,8 @@ const validateBookPriceRange = {
|
|
|
255
238
|
isCritical: true,
|
|
256
239
|
getMessage: () => "price\uFF08\u672C\u306E\u4FA1\u683C\uFF09\u3092\u6709\u6599\u306B\u3059\u308B\u5834\u5408\u3001200\u301C5000\u306E\u9593\u3067\u6307\u5B9A\u3057\u3066\u304F\u3060\u3055\u3044",
|
|
257
240
|
isValid: ({ price }) => {
|
|
258
|
-
if (typeof price !== "number")
|
|
259
|
-
|
|
260
|
-
if (price === 0)
|
|
261
|
-
return true;
|
|
241
|
+
if (typeof price !== "number") return true;
|
|
242
|
+
if (price === 0) return true;
|
|
262
243
|
return price >= 200 && price <= 5e3;
|
|
263
244
|
}
|
|
264
245
|
};
|
|
@@ -267,8 +248,7 @@ const validateBookPriceFraction = {
|
|
|
267
248
|
isCritical: true,
|
|
268
249
|
getMessage: () => "price\uFF08\u672C\u306E\u4FA1\u683C\uFF09\u306F100\u5186\u5358\u4F4D\u3067\u6307\u5B9A\u3057\u3066\u304F\u3060\u3055\u3044",
|
|
269
250
|
isValid: ({ price }) => {
|
|
270
|
-
if (typeof price !== "number")
|
|
271
|
-
return true;
|
|
251
|
+
if (typeof price !== "number") return true;
|
|
272
252
|
return price % 100 === 0;
|
|
273
253
|
}
|
|
274
254
|
};
|
|
@@ -282,14 +262,12 @@ const validateBookCoverSize = {
|
|
|
282
262
|
isCritical: true,
|
|
283
263
|
getMessage: (item) => `\u30AB\u30D0\u30FC\u753B\u50CF\u306E\u30B5\u30A4\u30BA\u306F1MB\u4EE5\u5185\u306B\u3057\u3066\u304F\u3060\u3055\u3044\u3002\u73FE\u5728\u306E\u30B5\u30A4\u30BA: ${item.coverFilesize ? `${Math.trunc(item.coverFilesize / 1024)}KB` : "\u53D6\u5F97\u3067\u304D\u307E\u305B\u3093\u3067\u3057\u305F"}`,
|
|
284
264
|
isValid: ({ coverDataUrl, coverFilesize }) => {
|
|
285
|
-
if (typeof coverDataUrl !== "string")
|
|
286
|
-
return true;
|
|
265
|
+
if (typeof coverDataUrl !== "string") return true;
|
|
287
266
|
return typeof coverFilesize === "number" && coverFilesize <= 1024 * 1024;
|
|
288
267
|
}
|
|
289
268
|
};
|
|
290
269
|
function getAspectRatio(width, height) {
|
|
291
|
-
if (!height || !width)
|
|
292
|
-
return null;
|
|
270
|
+
if (!height || !width) return null;
|
|
293
271
|
return Math.round(height / width * 10) / 10;
|
|
294
272
|
}
|
|
295
273
|
const validateBookCoverAspectRatio = {
|
|
@@ -302,8 +280,7 @@ const validateBookCoverAspectRatio = {
|
|
|
302
280
|
return `\u30AB\u30D0\u30FC\u753B\u50CF\u306E\u300C\u5E45 : \u9AD8\u3055\u300D\u306E\u6BD4\u7387\u306F\u300C1 : 1.4\u300D\u306B\u3059\u308B\u3053\u3068\u3092\u304A\u3059\u3059\u3081\u3057\u307E\u3059\uFF08\u6700\u7D42\u7684\u306B\u5E45500px\u30FB\u9AD8\u3055700px\u306B\u30EA\u30B5\u30A4\u30BA\u3055\u308C\u307E\u3059\uFF09\u3002${currentAspectRatio ? `\u73FE\u5728\u306E\u6BD4\u7387\u306F\u300C1 : ${currentAspectRatio}\u300D\u3067\u3059` : ""}`;
|
|
303
281
|
},
|
|
304
282
|
isValid: ({ coverDataUrl, coverHeight, coverWidth }) => {
|
|
305
|
-
if (typeof coverDataUrl !== "string")
|
|
306
|
-
return true;
|
|
283
|
+
if (typeof coverDataUrl !== "string") return true;
|
|
307
284
|
const currentAspectRatio = getAspectRatio(coverWidth, coverHeight);
|
|
308
285
|
return typeof currentAspectRatio === "number" && currentAspectRatio === 1.4;
|
|
309
286
|
}
|
|
@@ -314,8 +291,7 @@ const validateBookChapterSlugs = {
|
|
|
314
291
|
getMessage: () => `config.yaml\u306E chapters \u306E\u6307\u5B9A\u306B\u8AA4\u308A\u304C\u3042\u308A\u307E\u3059`,
|
|
315
292
|
detailUrl: "https://zenn.dev/zenn/articles/zenn-cli-guide#%F0%9F%93%84-config.yaml",
|
|
316
293
|
isValid: ({ specifiedChapterSlugs }) => {
|
|
317
|
-
if (specifiedChapterSlugs === void 0)
|
|
318
|
-
return true;
|
|
294
|
+
if (specifiedChapterSlugs === void 0) return true;
|
|
319
295
|
return Array.isArray(specifiedChapterSlugs) && specifiedChapterSlugs.every((slug) => typeof slug === "string");
|
|
320
296
|
}
|
|
321
297
|
};
|
|
@@ -325,8 +301,7 @@ const validateBookChaptersFormat = {
|
|
|
325
301
|
getMessage: () => `chapters \u306B\u6307\u5B9A\u3059\u308B\u6587\u5B57\u5217\u306B\u306F\u62E1\u5F35\u5B50\uFF08.md\uFF09\u3092\u542B\u3081\u306A\u3044\u3067\u304F\u3060\u3055\u3044\u3002\u30D5\u30A1\u30A4\u30EB\u540D\u304C example.md \u3067\u3042\u308C\u3070 example \u3068\u306E\u307F\u8A18\u8F09\u3057\u3066\u304F\u3060\u3055\u3044`,
|
|
326
302
|
detailUrl: "https://zenn.dev/zenn/articles/zenn-cli-guide#%F0%9F%93%84-config.yaml",
|
|
327
303
|
isValid: ({ specifiedChapterSlugs }) => {
|
|
328
|
-
if (!Array.isArray(specifiedChapterSlugs))
|
|
329
|
-
return true;
|
|
304
|
+
if (!Array.isArray(specifiedChapterSlugs)) return true;
|
|
330
305
|
const anyInvalidFormat = specifiedChapterSlugs.some(
|
|
331
306
|
(slug) => typeof slug === "string" && slug.match(/\.md$/)
|
|
332
307
|
);
|
|
@@ -351,8 +326,7 @@ const validateBody = {
|
|
|
351
326
|
getMessage: () => `\u8A18\u4E8B\u672C\u6587\u306B\u30A8\u30E9\u30FC\u304C\u3042\u308A\u307E\u3059\u3002\u672C\u6587\u3092\u78BA\u8A8D\u3057\u3066\u304F\u3060\u3055\u3044\u3002`,
|
|
352
327
|
// data-body-error がある場合はエラー
|
|
353
328
|
isValid: ({ bodyHtml }) => {
|
|
354
|
-
if (!bodyHtml)
|
|
355
|
-
return true;
|
|
329
|
+
if (!bodyHtml) return true;
|
|
356
330
|
const $ = cheerio.load(bodyHtml);
|
|
357
331
|
return !$("[data-body-error]").length;
|
|
358
332
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "zenn-model",
|
|
3
|
-
"version": "0.2.6-alpha.
|
|
3
|
+
"version": "0.2.6-alpha.3",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"description": "Model utils for Zenn contents",
|
|
6
6
|
"main": "lib/index.js",
|
|
@@ -18,29 +18,29 @@
|
|
|
18
18
|
"build:src": "esbuild ./src/*.ts --format=cjs --outdir=lib",
|
|
19
19
|
"build:types": "tsc --project ./tsconfig.build.json",
|
|
20
20
|
"lint": "run-s lint:*",
|
|
21
|
-
"lint:eslint": "eslint .
|
|
21
|
+
"lint:eslint": "eslint .",
|
|
22
22
|
"lint:prettier": "prettier .",
|
|
23
23
|
"lint-strict": "run-s lint-strict:*",
|
|
24
|
-
"lint-strict:eslint": "eslint . --
|
|
24
|
+
"lint-strict:eslint": "eslint . --max-warnings 0",
|
|
25
25
|
"lint-strict:prettier": "prettier --check .",
|
|
26
26
|
"fix": "run-s fix:*",
|
|
27
|
-
"fix:eslint": "eslint . --
|
|
27
|
+
"fix:eslint": "eslint . --fix",
|
|
28
28
|
"fix:prettier": "prettier -w .",
|
|
29
29
|
"test": "vitest run"
|
|
30
30
|
},
|
|
31
31
|
"devDependencies": {
|
|
32
|
-
"@
|
|
33
|
-
"
|
|
34
|
-
"
|
|
35
|
-
"eslint": "^
|
|
36
|
-
"
|
|
37
|
-
"
|
|
38
|
-
"typescript": "^
|
|
39
|
-
"vitest": "^
|
|
32
|
+
"@eslint/js": "^9.38.0",
|
|
33
|
+
"esbuild": "^0.25.11",
|
|
34
|
+
"eslint": "^9.38.0",
|
|
35
|
+
"eslint-config-prettier": "^10.1.8",
|
|
36
|
+
"rimraf": "^6.0.1",
|
|
37
|
+
"typescript": "^5.9.3",
|
|
38
|
+
"typescript-eslint": "^8.46.2",
|
|
39
|
+
"vitest": "^3.2.4"
|
|
40
40
|
},
|
|
41
41
|
"dependencies": {
|
|
42
|
-
"cheerio": "^1.
|
|
43
|
-
"emoji-regex": "^10.
|
|
42
|
+
"cheerio": "^1.1.2",
|
|
43
|
+
"emoji-regex": "^10.6.0"
|
|
44
44
|
},
|
|
45
|
-
"gitHead": "
|
|
45
|
+
"gitHead": "9cca382bdb5638330513bdabac3e015022dbf73b"
|
|
46
46
|
}
|