@everipedia/iq-utils 1.0.1 → 2.0.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.
Files changed (44) hide show
  1. package/CHANGELOG.md +13 -1
  2. package/dist/index.d.mts +693 -0
  3. package/dist/index.d.ts +693 -0
  4. package/dist/index.js +640 -0
  5. package/dist/index.js.map +1 -0
  6. package/dist/index.mjs +580 -0
  7. package/dist/index.mjs.map +1 -0
  8. package/package.json +52 -53
  9. package/build/main/data/constants.d.ts +0 -24
  10. package/build/main/data/constants.js +0 -28
  11. package/build/main/index.d.ts +0 -7
  12. package/build/main/index.js +0 -24
  13. package/build/main/lib/checkWikiValidity.d.ts +0 -67
  14. package/build/main/lib/checkWikiValidity.js +0 -209
  15. package/build/main/lib/helpers/wiki.helpers.d.ts +0 -32
  16. package/build/main/lib/helpers/wiki.helpers.js +0 -86
  17. package/build/main/lib/isDeepEqual.d.ts +0 -3
  18. package/build/main/lib/isDeepEqual.js +0 -53
  19. package/build/main/lib/wikiScore.d.ts +0 -2
  20. package/build/main/lib/wikiScore.js +0 -127
  21. package/build/main/schema/wiki.schema.d.ts +0 -798
  22. package/build/main/schema/wiki.schema.js +0 -289
  23. package/build/main/types/wiki.d.ts +0 -9
  24. package/build/main/types/wiki.js +0 -14
  25. package/build/main/types/wikiBuilder.d.ts +0 -11
  26. package/build/main/types/wikiBuilder.js +0 -3
  27. package/build/module/data/constants.d.ts +0 -24
  28. package/build/module/data/constants.js +0 -25
  29. package/build/module/index.d.ts +0 -7
  30. package/build/module/index.js +0 -8
  31. package/build/module/lib/checkWikiValidity.d.ts +0 -67
  32. package/build/module/lib/checkWikiValidity.js +0 -191
  33. package/build/module/lib/helpers/wiki.helpers.d.ts +0 -32
  34. package/build/module/lib/helpers/wiki.helpers.js +0 -75
  35. package/build/module/lib/isDeepEqual.d.ts +0 -3
  36. package/build/module/lib/isDeepEqual.js +0 -51
  37. package/build/module/lib/wikiScore.d.ts +0 -2
  38. package/build/module/lib/wikiScore.js +0 -121
  39. package/build/module/schema/wiki.schema.d.ts +0 -798
  40. package/build/module/schema/wiki.schema.js +0 -286
  41. package/build/module/types/wiki.d.ts +0 -9
  42. package/build/module/types/wiki.js +0 -11
  43. package/build/module/types/wikiBuilder.d.ts +0 -11
  44. package/build/module/types/wikiBuilder.js +0 -2
package/dist/index.js ADDED
@@ -0,0 +1,640 @@
1
+ 'use strict';
2
+
3
+ var zod = require('zod');
4
+ var axios = require('axios');
5
+
6
+ function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
7
+
8
+ var axios__default = /*#__PURE__*/_interopDefault(axios);
9
+
10
+ // src/data/constants.ts
11
+ var WIKI_SUMMARY_MAX_LENGTH = 255;
12
+ var WIKI_CONTENT_MIN_WORDS = 100;
13
+ var WIKI_TITLE_MAX_LENGTH = 60;
14
+ var MEDIA_UPLOAD_PENDING_SUFFIX = "default";
15
+ var MAX_MEDIA_COUNT = 25;
16
+ var IPFS_HASH_LENGTH = 46;
17
+ var EditorContentOverride = "%OVERRIDE@EDITOR@MARKDOWN%";
18
+ var CreateNewWikiSlug = "/*CREATE+NEW+WIKI*/";
19
+ var MIN_CONTENT_WORD_COUNT = 10;
20
+ var GOOD_CONTENT_WORD_COUNT = 500;
21
+ var IDEAL_CONTENT_WORD_COUNT = 1500;
22
+ var CONTENT_SCORE_WEIGHT = 0.8;
23
+ var INTERNAL_LINKS_SCORE_WEIGHT = 0.5;
24
+ var CITATIONS_SCORE_WEIGHT = 0.5;
25
+ var MEDIA_SCORE_WEIGHT = 0.3;
26
+ var TAGS_SCORE_WEIGHT = 0.3;
27
+ var SUMMARY_SCORE_WEIGHT = 0.5;
28
+ var SOCIAL_SCORE_WEIGHT = 0.5;
29
+ var IDEAL_INTERNAL_LINKS_COUNT = 10;
30
+ var IDEAL_CITATIONS_COUNT = 10;
31
+ var IDEAL_MEDIA_COUNT = 5;
32
+ var IDEAL_TAGS_COUNT = 3;
33
+ var IDEAL_SUMMARY_LENGTH = 100;
34
+ var IDEAL_SOCIAL_MEDIA_COUNT = 4;
35
+ var WHITELISTED_DOMAINS = [
36
+ "youtube.com/watch",
37
+ "youtu.be",
38
+ "vimeo.com",
39
+ "alpha.everipedia.org/wiki",
40
+ "beta.everipedia.org/wiki",
41
+ "iq.wiki/wiki",
42
+ "ipfs.everipedia.org/ipfs"
43
+ ];
44
+ var WHITELISTED_LINK_NAMES = ["YOUTUBE@VID", "DUNE@EMBED"];
45
+ var countWords = (text) => {
46
+ return text.split(" ").filter((word) => word !== "").length;
47
+ };
48
+ var isValidUrl = (urlString) => {
49
+ try {
50
+ return Boolean(new URL(urlString));
51
+ } catch (_e) {
52
+ return false;
53
+ }
54
+ };
55
+ var containsOnlyVerifiedLinks = (content) => {
56
+ const markdownLinks = content.match(/\[(.*?)\]\((.*?)\)/g);
57
+ return markdownLinks?.every((link) => {
58
+ const [, linkText, linkUrl] = RegExp(/\[(.*?)\]\((.*?)\)/).exec(link) || [];
59
+ if (linkText && linkUrl && WHITELISTED_LINK_NAMES.includes(linkText) && !isValidUrl(linkUrl)) {
60
+ return true;
61
+ }
62
+ if (linkUrl && !linkUrl.startsWith("#")) {
63
+ const validDomainPattern = new RegExp(
64
+ `^https?://(www\\.)?(${WHITELISTED_DOMAINS.join("|")})`
65
+ );
66
+ return validDomainPattern.test(linkUrl);
67
+ }
68
+ return true;
69
+ }) ?? true;
70
+ };
71
+ var isMediaContentValid = (media) => {
72
+ return media.every((item) => {
73
+ if (item.source === MediaSource.Enum.IPFS_IMG || item.source === MediaSource.Enum.IPFS_VID) {
74
+ return item.id.length === IPFS_HASH_LENGTH;
75
+ }
76
+ if (item.source === MediaSource.Enum.YOUTUBE) {
77
+ const youtubePattern = /^.*(?:youtu\.be\/|v\/|vi\/|u\/\w\/|embed\/|shorts\/|watch\?v=)([^#&?]*).*/;
78
+ return item.id === `https://www.youtube.com/watch?v=${item.name}` && youtubePattern.test(item.id);
79
+ }
80
+ if (item.source === MediaSource.Enum.VIMEO) {
81
+ return item.id === `https://vimeo.com/${item.name}`;
82
+ }
83
+ return item.type ? item.type in MediaType : true;
84
+ });
85
+ };
86
+ var isMediaCountWithinLimits = (media) => {
87
+ const iconMediaCount = media.filter(
88
+ (item) => item.type === MediaType.Enum.ICON
89
+ ).length;
90
+ return media.length <= MAX_MEDIA_COUNT && iconMediaCount <= 1;
91
+ };
92
+ var isMediaContentAndCountValid = (media) => {
93
+ return isMediaContentValid(media) && isMediaCountWithinLimits(media);
94
+ };
95
+ var isEventWikiValid = (wiki) => {
96
+ if (wiki.tags.some((tag) => tag.id === "Events")) {
97
+ const referencesData = wiki.metadata.find(
98
+ (meta) => meta.id === CommonMetaIds.Enum.references
99
+ )?.value || "[]";
100
+ const references = JSON.parse(
101
+ referencesData
102
+ );
103
+ const hasEventLink = references.some(
104
+ (item) => item.description.toLowerCase() === "event link"
105
+ );
106
+ return hasEventLink && Array.isArray(wiki.events) && wiki.events.length > 0;
107
+ }
108
+ return true;
109
+ };
110
+ var hasMinimumWordCount = (content) => {
111
+ return countWords(content) >= WIKI_CONTENT_MIN_WORDS;
112
+ };
113
+ var hasAtLeastOneReference = (metadata) => {
114
+ const referencesData = metadata.find((meta) => meta.id === CommonMetaIds.Enum.references)?.value || "[]";
115
+ const references = JSON.parse(referencesData);
116
+ return references.length > 0;
117
+ };
118
+ var areMetadataAndExplorerValid = async (metadata) => {
119
+ const explorers = await getExplorers();
120
+ const validIds = /* @__PURE__ */ new Set([
121
+ ...CommonMetaIds.options,
122
+ ...EditSpecificMetaIds.options,
123
+ ...explorers.map((e) => e.id)
124
+ ]);
125
+ return metadata.every(
126
+ (meta) => validIds.has(meta.id) && (!explorers.some((e) => e.id === meta.id) || isValidUrl(meta.value) && new URL(meta.value).origin === new URL(explorers.find((e) => e.id === meta.id)?.baseUrl || "").origin)
127
+ );
128
+ };
129
+ var transformAndFilterTags = (tags) => {
130
+ return tags.filter((tag) => Tag.safeParse(tag.id).success).map((tag) => ({ id: tag.id }));
131
+ };
132
+ async function getExplorers() {
133
+ const query = `
134
+ query ExplorersList($offset: Int!, $limit: Int!) {
135
+ explorers(offset: $offset, limit: $limit) {
136
+ id
137
+ baseUrl
138
+ explorer
139
+ hidden
140
+ }
141
+ }
142
+ `;
143
+ const client = axios__default.default.create({
144
+ baseURL: "https://graphql.everipedia.org",
145
+ headers: {
146
+ "Content-Type": "application/json"
147
+ }
148
+ });
149
+ const { data } = await client.post("", {
150
+ query,
151
+ variables: {
152
+ offset: 0,
153
+ limit: 30
154
+ }
155
+ });
156
+ return data;
157
+ }
158
+
159
+ // src/schema/index.ts
160
+ var MediaType = zod.z.enum(["GALLERY", "ICON"]);
161
+ var MediaSource = zod.z.enum(["IPFS_IMG", "VIMEO", "YOUTUBE", "IPFS_VID"]);
162
+ var CommonMetaIds = zod.z.enum([
163
+ "references",
164
+ "website",
165
+ "contract_url",
166
+ "location",
167
+ "email_url",
168
+ "facebook_profile",
169
+ "instagram_profile",
170
+ "twitter_profile",
171
+ "linkedin_profile",
172
+ "youtube_profile",
173
+ "discord_profile",
174
+ "reddit_profile",
175
+ "telegram_profile",
176
+ "github_profile",
177
+ "coinmarketcap_url",
178
+ "coingecko_profile",
179
+ "opensea_profile",
180
+ "medium_profile",
181
+ "mirror_profile",
182
+ "tiktok_profile",
183
+ "explorer_injective_profile"
184
+ ]);
185
+ var EditSpecificMetaIds = zod.z.enum(["previous_cid", "commit-message"]);
186
+ var ValidatorCodes = zod.z.enum([
187
+ "VALID_WIKI",
188
+ "ID_ERROR",
189
+ "LANGUAGE_ERROR",
190
+ "USER_ERROR",
191
+ "WORD_COUNT_ERROR",
192
+ "CATEGORY_ERROR",
193
+ "SUMMARY_ERROR",
194
+ "IMAGE_ERROR",
195
+ "TAG_ERROR",
196
+ "EXTERNAL_URL_ERROR",
197
+ "METADATA_ERROR",
198
+ "MEDIA_ERROR",
199
+ "GLOBAL_RATE_LIMIT",
200
+ "LINKED_WIKIS",
201
+ "EVENTS_ERROR"
202
+ ]);
203
+ var LanguagesISO = zod.z.enum(["en", "es", "zh", "ko"]);
204
+ var LinkedWikiKey = zod.z.enum(["founders", "blockchains", "speakers"]);
205
+ var EventType = zod.z.enum(["CREATED", "DEFAULT", "MULTIDATE"]);
206
+ var Tag = zod.z.enum([
207
+ "Artists",
208
+ "AI",
209
+ "BinanceSmartChain",
210
+ "Blockchains",
211
+ "CEXes",
212
+ "Collections",
213
+ "Collectors",
214
+ "Conference",
215
+ "DEXes",
216
+ "Developers",
217
+ "Entertainment",
218
+ "Ethereum",
219
+ "Events",
220
+ "Forum",
221
+ "Founders",
222
+ "Festival",
223
+ "Games",
224
+ "Glossary",
225
+ "Hackathon",
226
+ "Marketplaces",
227
+ "Memecoins",
228
+ "Organizations",
229
+ "Online",
230
+ "PeopleInDeFi",
231
+ "Polkadot",
232
+ "Polygon",
233
+ "Protocols",
234
+ "Solana",
235
+ "Speakers",
236
+ "Stablecoins",
237
+ "Venture"
238
+ ]);
239
+ var Category = zod.z.enum([
240
+ "nfts",
241
+ "defi",
242
+ "exchanges",
243
+ "cryptocurrencies",
244
+ "daos",
245
+ "people",
246
+ "dapps",
247
+ "organizations"
248
+ ]);
249
+ var ProfileLinks = zod.z.object({
250
+ twitter: zod.z.string().nullable(),
251
+ website: zod.z.string().nullable(),
252
+ instagram: zod.z.string().nullable()
253
+ });
254
+ var ProfileData = zod.z.object({
255
+ id: zod.z.string().nullable(),
256
+ username: zod.z.string().nullable(),
257
+ bio: zod.z.string().nullable(),
258
+ links: zod.z.array(ProfileLinks).nullable(),
259
+ banner: zod.z.string().nullable(),
260
+ avatar: zod.z.string().nullable()
261
+ });
262
+ var Image = zod.z.object({
263
+ id: zod.z.string(),
264
+ type: zod.z.string()
265
+ });
266
+ var Media = zod.z.object({
267
+ id: zod.z.string(),
268
+ size: zod.z.string().nullish(),
269
+ name: zod.z.string().nullish(),
270
+ type: MediaType.nullish(),
271
+ caption: zod.z.string().nullish(),
272
+ thumbnail: zod.z.string().nullish(),
273
+ source: MediaSource
274
+ });
275
+ var MetaData = zod.z.object({
276
+ id: zod.z.string(),
277
+ value: zod.z.any()
278
+ });
279
+ var BaseCategory = zod.z.object({
280
+ id: Category,
281
+ title: zod.z.string()
282
+ });
283
+ var BaseEvents = zod.z.object({
284
+ id: zod.z.string().nullish(),
285
+ date: zod.z.string().nullable(),
286
+ title: zod.z.string().nullish(),
287
+ type: EventType.nullable(),
288
+ description: zod.z.string().nullish(),
289
+ link: zod.z.string().nullish(),
290
+ multiDateStart: zod.z.string().nullish(),
291
+ multiDateEnd: zod.z.string().nullish(),
292
+ continent: zod.z.string().nullish(),
293
+ country: zod.z.string().nullish(),
294
+ action: zod.z.enum(["DELETE", "EDIT", "CREATE"]).nullish()
295
+ });
296
+ var Wiki = zod.z.object({
297
+ id: zod.z.string(),
298
+ title: zod.z.string().min(1, "Add a Title at the top for this Wiki to continue").max(
299
+ WIKI_TITLE_MAX_LENGTH,
300
+ `Title should be less than ${WIKI_TITLE_MAX_LENGTH} characters`
301
+ ),
302
+ content: zod.z.string().min(1, "Add a Content section to continue").refine(
303
+ hasMinimumWordCount,
304
+ `Add a minimum of ${WIKI_CONTENT_MIN_WORDS} words in the content section to continue`
305
+ ).refine(
306
+ containsOnlyVerifiedLinks,
307
+ "Please remove all external links from the content"
308
+ ),
309
+ summary: zod.z.string().max(
310
+ WIKI_SUMMARY_MAX_LENGTH,
311
+ `Summary exceeds maximum limit of ${WIKI_SUMMARY_MAX_LENGTH}`
312
+ ),
313
+ images: zod.z.array(Image).min(1, "Add a main image on the right column to continue"),
314
+ categories: zod.z.array(BaseCategory).min(1, "Add one category to continue"),
315
+ tags: zod.z.array(zod.z.object({ id: zod.z.string() })).transform(transformAndFilterTags),
316
+ media: zod.z.array(Media).max(MAX_MEDIA_COUNT).refine(isMediaContentAndCountValid, "Media is invalid").optional(),
317
+ metadata: zod.z.array(MetaData).refine(hasAtLeastOneReference, "Please add at least one citation").refine(
318
+ areMetadataAndExplorerValid,
319
+ "Invalid metadata Ids or explorer metadata"
320
+ ),
321
+ events: zod.z.array(BaseEvents).nullish(),
322
+ user: zod.z.object({ id: zod.z.string() }),
323
+ author: zod.z.object({ id: zod.z.string() }),
324
+ language: LanguagesISO.default(LanguagesISO.Enum.en),
325
+ version: zod.z.number().default(1),
326
+ linkedWikis: zod.z.object({
327
+ [LinkedWikiKey.Enum.blockchains]: zod.z.array(zod.z.string()).nullish(),
328
+ [LinkedWikiKey.Enum.founders]: zod.z.array(zod.z.string()).nullish(),
329
+ [LinkedWikiKey.Enum.speakers]: zod.z.array(zod.z.string()).nullish()
330
+ }).nullish().default({})
331
+ }).refine(isEventWikiValid, {
332
+ message: "Event wikis must have an event link citation and at least one event date",
333
+ path: ["events"]
334
+ });
335
+ var Reference = zod.z.object({
336
+ id: zod.z.string(),
337
+ description: zod.z.string(),
338
+ timestamp: zod.z.number(),
339
+ url: zod.z.string()
340
+ });
341
+
342
+ // src/lib/wiki-score.ts
343
+ var contentQuality = (wordCount) => {
344
+ const scoreMin = 0;
345
+ const scoreMax = 1;
346
+ let score = 0;
347
+ if (wordCount < MIN_CONTENT_WORD_COUNT) {
348
+ return scoreMin;
349
+ }
350
+ if (wordCount >= MIN_CONTENT_WORD_COUNT && wordCount <= GOOD_CONTENT_WORD_COUNT) {
351
+ score = wordCount / GOOD_CONTENT_WORD_COUNT;
352
+ score *= 0.8;
353
+ }
354
+ if (wordCount > GOOD_CONTENT_WORD_COUNT && wordCount < IDEAL_CONTENT_WORD_COUNT) {
355
+ const baseScore = 0.8;
356
+ const wordCountAboveGood = wordCount - GOOD_CONTENT_WORD_COUNT;
357
+ const extraScoreFactor = wordCountAboveGood / (IDEAL_CONTENT_WORD_COUNT - GOOD_CONTENT_WORD_COUNT);
358
+ const extraScore = Math.sqrt(extraScoreFactor) * 0.2;
359
+ score = baseScore + extraScore;
360
+ }
361
+ if (wordCount >= IDEAL_CONTENT_WORD_COUNT) {
362
+ return scoreMax;
363
+ }
364
+ if (score < scoreMin) {
365
+ return scoreMin;
366
+ }
367
+ if (score > scoreMax) {
368
+ return scoreMax;
369
+ }
370
+ return score;
371
+ };
372
+ var countQuality = (idealCount, realCount) => {
373
+ const scoreMin = 0;
374
+ const scoreMax = 1;
375
+ const score = realCount / idealCount;
376
+ if (score < scoreMin) {
377
+ return scoreMin;
378
+ }
379
+ if (score > scoreMax) {
380
+ return scoreMax;
381
+ }
382
+ return score;
383
+ };
384
+ var getHostnameFromRegex = (url) => {
385
+ const matches = RegExp(/^https?:\/\/([^/?#]+)(?:[/?#]|$)/i).exec(url);
386
+ return matches?.[1];
387
+ };
388
+ var getWikiInternalLinks = (content) => {
389
+ const markdownLinkRegex = /\[(.*?)\]\((.*?)\)/g;
390
+ let internalLinksCount = 0;
391
+ let match = markdownLinkRegex.exec(content);
392
+ while (match !== null) {
393
+ const url = match[2];
394
+ if (url && !url.startsWith("#")) {
395
+ const hostname = getHostnameFromRegex(url);
396
+ if (hostname === "everipedia.org" || hostname === "iq.wiki" || hostname?.endsWith(".everipedia.org")) {
397
+ internalLinksCount++;
398
+ }
399
+ }
400
+ match = markdownLinkRegex.exec(content);
401
+ }
402
+ return internalLinksCount;
403
+ };
404
+ var getWikiCitationLinks = (wiki) => {
405
+ const rawWikiReferences = wiki.metadata.find(
406
+ (m) => m.id === CommonMetaIds.Enum.references
407
+ )?.value;
408
+ if (rawWikiReferences === void 0 || rawWikiReferences?.trim().length === 0) {
409
+ return 0;
410
+ }
411
+ const wikiReferences = JSON.parse(rawWikiReferences);
412
+ return wikiReferences.length;
413
+ };
414
+ var getSocialsCount = (wiki) => {
415
+ let socialsCount = 0;
416
+ for (const meta of wiki.metadata) {
417
+ if (CommonMetaIds.options.includes(meta.id)) {
418
+ if (meta.value) {
419
+ socialsCount += 1;
420
+ }
421
+ }
422
+ }
423
+ return socialsCount;
424
+ };
425
+ var calculateWikiScore = (wiki) => {
426
+ const wordCount = wiki.content.split(" ").length;
427
+ const internalLinksCount = getWikiInternalLinks(wiki.content);
428
+ const citationCount = getWikiCitationLinks(wiki);
429
+ const mediaCount = wiki.media?.length || 0;
430
+ const tagsCount = wiki.tags?.length || 0;
431
+ const summaryWordCount = wiki.summary?.length || 0;
432
+ const socialsCount = getSocialsCount(wiki);
433
+ const contentScore = contentQuality(wordCount);
434
+ const internalLinksScore = countQuality(
435
+ IDEAL_INTERNAL_LINKS_COUNT,
436
+ internalLinksCount
437
+ );
438
+ const citationScore = countQuality(IDEAL_CITATIONS_COUNT, citationCount);
439
+ const mediaScore = countQuality(IDEAL_MEDIA_COUNT, mediaCount);
440
+ const tagsScore = countQuality(IDEAL_TAGS_COUNT, tagsCount);
441
+ const summaryScore = countQuality(IDEAL_SUMMARY_LENGTH, summaryWordCount);
442
+ const socialsScore = countQuality(IDEAL_SOCIAL_MEDIA_COUNT, socialsCount);
443
+ const sumOfWeights = CONTENT_SCORE_WEIGHT + INTERNAL_LINKS_SCORE_WEIGHT + CITATIONS_SCORE_WEIGHT + MEDIA_SCORE_WEIGHT + TAGS_SCORE_WEIGHT + SUMMARY_SCORE_WEIGHT + SOCIAL_SCORE_WEIGHT;
444
+ const score = (contentScore * CONTENT_SCORE_WEIGHT + internalLinksScore * INTERNAL_LINKS_SCORE_WEIGHT + citationScore * CITATIONS_SCORE_WEIGHT + mediaScore * MEDIA_SCORE_WEIGHT + tagsScore * TAGS_SCORE_WEIGHT + summaryScore * SUMMARY_SCORE_WEIGHT + socialsScore * SOCIAL_SCORE_WEIGHT) / sumOfWeights;
445
+ const percentScore = Math.floor(score * 100);
446
+ return percentScore;
447
+ };
448
+
449
+ // src/lib/check-wiki-validity.ts
450
+ var countWords2 = (text) => text.split(" ").filter((word) => word !== "").length;
451
+ var isValidUrl2 = (urlString) => {
452
+ try {
453
+ return Boolean(new URL(urlString));
454
+ } catch (_e) {
455
+ return false;
456
+ }
457
+ };
458
+ var areContentLinksVerified = (content) => {
459
+ const markdownLinks = content.match(/\[(.*?)\]\((.*?)\)/g);
460
+ return markdownLinks?.every((link) => {
461
+ const [, linkText, linkUrl] = RegExp(/\[(.*?)\]\((.*?)\)/).exec(link) || [];
462
+ if (linkText && linkUrl && WHITELISTED_LINK_NAMES.includes(linkText) && !isValidUrl2(linkUrl)) {
463
+ return true;
464
+ }
465
+ if (linkUrl && !linkUrl.startsWith("#")) {
466
+ const validDomainPattern = new RegExp(
467
+ `^https?://(www\\.)?(${WHITELISTED_DOMAINS.join("|")})`
468
+ );
469
+ return validDomainPattern.test(linkUrl);
470
+ }
471
+ return true;
472
+ }) ?? true;
473
+ };
474
+ var isMediaValid = (wiki) => {
475
+ if (!wiki.media) return true;
476
+ const isMediaContentValid2 = wiki.media.every((media) => {
477
+ if (media.source === MediaSource.Enum.IPFS_IMG || media.source === MediaSource.Enum.IPFS_VID) {
478
+ return media.id.length === IPFS_HASH_LENGTH;
479
+ }
480
+ if (media.source === MediaSource.Enum.YOUTUBE) {
481
+ const youtubePattern = /^.*(?:youtu\.be\/|v\/|vi\/|u\/\w\/|embed\/|shorts\/|watch\?v=)([^#&?]*).*/;
482
+ return media.id === `https://www.youtube.com/watch?v=${media.name}` && youtubePattern.test(media.id);
483
+ }
484
+ if (media.source === MediaSource.Enum.VIMEO) {
485
+ return media.id === `https://vimeo.com/${media.name}`;
486
+ }
487
+ return media.type ? MediaType.options.includes(media.type) : true;
488
+ });
489
+ const iconMediaCount = wiki.media.filter(
490
+ (media) => media.type === MediaType.Enum.ICON
491
+ ).length;
492
+ return wiki.media.length <= MAX_MEDIA_COUNT && isMediaContentValid2 && iconMediaCount <= 1;
493
+ };
494
+ var isAnyMediaUploading = (wiki) => wiki.media?.some((media) => media.id.endsWith(MEDIA_UPLOAD_PENDING_SUFFIX)) ?? false;
495
+ var isEventUrlMissing = (wiki) => {
496
+ if (wiki.tags.some((tag) => tag.id === "Events")) {
497
+ const referencesData = wiki.metadata.find((meta) => meta.id === CommonMetaIds.Enum.references)?.value || "[]";
498
+ const references = JSON.parse(referencesData);
499
+ return !references.some(
500
+ (item) => item.description.toLowerCase() === "event link"
501
+ );
502
+ }
503
+ return false;
504
+ };
505
+ var isEventDateMissing = (wiki) => wiki.tags.some((tag) => tag.id === "Events") && wiki.events?.length === 0;
506
+ var isSummaryTooLong = (wiki) => !!(wiki.summary && wiki.summary.length > WIKI_SUMMARY_MAX_LENGTH);
507
+ var hasNoCitations = (wiki) => {
508
+ const references = wiki.metadata.find(
509
+ (meta) => meta.id === CommonMetaIds.Enum.references
510
+ );
511
+ return !references?.value || references.value.length === 0;
512
+ };
513
+ var validateWiki = (wiki) => {
514
+ const wordCount = countWords2(wiki.content || "");
515
+ if (!wiki.title) {
516
+ return {
517
+ isValid: false,
518
+ error: "Add a Title at the top for this Wiki to continue"
519
+ };
520
+ }
521
+ if (wiki.title.length > WIKI_TITLE_MAX_LENGTH) {
522
+ return {
523
+ isValid: false,
524
+ error: `Title should be less than ${WIKI_TITLE_MAX_LENGTH} characters`
525
+ };
526
+ }
527
+ if (!wiki.content) {
528
+ return { isValid: false, error: "Add a Content section to continue" };
529
+ }
530
+ if (wordCount < WIKI_CONTENT_MIN_WORDS) {
531
+ return {
532
+ isValid: false,
533
+ error: `Add a minimum of ${WIKI_CONTENT_MIN_WORDS} words in the content section to continue. You have written ${wordCount}`
534
+ };
535
+ }
536
+ if (!areContentLinksVerified(wiki.content)) {
537
+ return {
538
+ isValid: false,
539
+ error: "Please remove all external links from the content"
540
+ };
541
+ }
542
+ if (!wiki.images?.length) {
543
+ return {
544
+ isValid: false,
545
+ error: "Add a main image on the right column to continue"
546
+ };
547
+ }
548
+ if (wiki.categories.length === 0) {
549
+ return { isValid: false, error: "Add one category to continue" };
550
+ }
551
+ if (isSummaryTooLong(wiki)) {
552
+ return {
553
+ isValid: false,
554
+ error: `Summary exceeds maximum limit of ${WIKI_SUMMARY_MAX_LENGTH}`
555
+ };
556
+ }
557
+ if (isAnyMediaUploading(wiki)) {
558
+ return {
559
+ isValid: false,
560
+ error: "Some media are still uploading, please wait"
561
+ };
562
+ }
563
+ if (hasNoCitations(wiki)) {
564
+ return { isValid: false, error: "Please add at least one citation" };
565
+ }
566
+ if (isEventUrlMissing(wiki)) {
567
+ return {
568
+ isValid: false,
569
+ error: "Please cite the event official website with 'Event Link' description"
570
+ };
571
+ }
572
+ if (isEventDateMissing(wiki)) {
573
+ return {
574
+ isValid: false,
575
+ error: 'Please open the "Edit Wiki Details Modal" and enter a valid event date'
576
+ };
577
+ }
578
+ if (!isMediaValid(wiki)) {
579
+ return { isValid: false, error: "Media is invalid" };
580
+ }
581
+ return { isValid: true };
582
+ };
583
+
584
+ exports.BaseCategory = BaseCategory;
585
+ exports.BaseEvents = BaseEvents;
586
+ exports.CITATIONS_SCORE_WEIGHT = CITATIONS_SCORE_WEIGHT;
587
+ exports.CONTENT_SCORE_WEIGHT = CONTENT_SCORE_WEIGHT;
588
+ exports.Category = Category;
589
+ exports.CommonMetaIds = CommonMetaIds;
590
+ exports.CreateNewWikiSlug = CreateNewWikiSlug;
591
+ exports.EditSpecificMetaIds = EditSpecificMetaIds;
592
+ exports.EditorContentOverride = EditorContentOverride;
593
+ exports.EventType = EventType;
594
+ exports.GOOD_CONTENT_WORD_COUNT = GOOD_CONTENT_WORD_COUNT;
595
+ exports.IDEAL_CITATIONS_COUNT = IDEAL_CITATIONS_COUNT;
596
+ exports.IDEAL_CONTENT_WORD_COUNT = IDEAL_CONTENT_WORD_COUNT;
597
+ exports.IDEAL_INTERNAL_LINKS_COUNT = IDEAL_INTERNAL_LINKS_COUNT;
598
+ exports.IDEAL_MEDIA_COUNT = IDEAL_MEDIA_COUNT;
599
+ exports.IDEAL_SOCIAL_MEDIA_COUNT = IDEAL_SOCIAL_MEDIA_COUNT;
600
+ exports.IDEAL_SUMMARY_LENGTH = IDEAL_SUMMARY_LENGTH;
601
+ exports.IDEAL_TAGS_COUNT = IDEAL_TAGS_COUNT;
602
+ exports.INTERNAL_LINKS_SCORE_WEIGHT = INTERNAL_LINKS_SCORE_WEIGHT;
603
+ exports.IPFS_HASH_LENGTH = IPFS_HASH_LENGTH;
604
+ exports.Image = Image;
605
+ exports.LanguagesISO = LanguagesISO;
606
+ exports.LinkedWikiKey = LinkedWikiKey;
607
+ exports.MAX_MEDIA_COUNT = MAX_MEDIA_COUNT;
608
+ exports.MEDIA_SCORE_WEIGHT = MEDIA_SCORE_WEIGHT;
609
+ exports.MEDIA_UPLOAD_PENDING_SUFFIX = MEDIA_UPLOAD_PENDING_SUFFIX;
610
+ exports.MIN_CONTENT_WORD_COUNT = MIN_CONTENT_WORD_COUNT;
611
+ exports.Media = Media;
612
+ exports.MediaSource = MediaSource;
613
+ exports.MediaType = MediaType;
614
+ exports.ProfileData = ProfileData;
615
+ exports.ProfileLinks = ProfileLinks;
616
+ exports.Reference = Reference;
617
+ exports.SOCIAL_SCORE_WEIGHT = SOCIAL_SCORE_WEIGHT;
618
+ exports.SUMMARY_SCORE_WEIGHT = SUMMARY_SCORE_WEIGHT;
619
+ exports.TAGS_SCORE_WEIGHT = TAGS_SCORE_WEIGHT;
620
+ exports.Tag = Tag;
621
+ exports.ValidatorCodes = ValidatorCodes;
622
+ exports.WHITELISTED_DOMAINS = WHITELISTED_DOMAINS;
623
+ exports.WHITELISTED_LINK_NAMES = WHITELISTED_LINK_NAMES;
624
+ exports.WIKI_CONTENT_MIN_WORDS = WIKI_CONTENT_MIN_WORDS;
625
+ exports.WIKI_SUMMARY_MAX_LENGTH = WIKI_SUMMARY_MAX_LENGTH;
626
+ exports.WIKI_TITLE_MAX_LENGTH = WIKI_TITLE_MAX_LENGTH;
627
+ exports.Wiki = Wiki;
628
+ exports.areContentLinksVerified = areContentLinksVerified;
629
+ exports.calculateWikiScore = calculateWikiScore;
630
+ exports.countWords = countWords2;
631
+ exports.hasNoCitations = hasNoCitations;
632
+ exports.isAnyMediaUploading = isAnyMediaUploading;
633
+ exports.isEventDateMissing = isEventDateMissing;
634
+ exports.isEventUrlMissing = isEventUrlMissing;
635
+ exports.isMediaValid = isMediaValid;
636
+ exports.isSummaryTooLong = isSummaryTooLong;
637
+ exports.isValidUrl = isValidUrl2;
638
+ exports.validateWiki = validateWiki;
639
+ //# sourceMappingURL=index.js.map
640
+ //# sourceMappingURL=index.js.map