@code.store/arcxp-sdk-ts 5.1.8 → 5.3.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/dist/api/author/index.d.ts +1 -1
- package/dist/api/content/index.d.ts +1 -1
- package/dist/api/content-ops/index.d.ts +1 -1
- package/dist/api/custom/index.d.ts +1 -1
- package/dist/api/developer-retail/index.d.ts +1 -1
- package/dist/api/draft/index.d.ts +3 -2
- package/dist/api/global-settings/index.d.ts +1 -1
- package/dist/api/identity/index.d.ts +1 -1
- package/dist/api/ifx/index.d.ts +1 -1
- package/dist/api/index.d.ts +2 -2
- package/dist/api/migration-center/index.d.ts +1 -1
- package/dist/api/photo-center/index.d.ts +1 -1
- package/dist/api/redirect/index.d.ts +2 -2
- package/dist/api/sales/index.d.ts +1 -1
- package/dist/api/signing-service/index.d.ts +1 -1
- package/dist/api/site/index.d.ts +2 -1
- package/dist/api/tags/index.d.ts +1 -1
- package/dist/api/websked/index.d.ts +1 -1
- package/dist/content-elements/html/html.utils.d.ts +0 -3
- package/dist/content-elements/xml/index.d.ts +3 -0
- package/dist/content-elements/xml/xml.constants.d.ts +1 -0
- package/dist/content-elements/xml/xml.processor.d.ts +45 -0
- package/dist/content-elements/xml/xml.utils.d.ts +5 -0
- package/dist/index.cjs +925 -917
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +4 -4
- package/dist/index.js +923 -915
- package/dist/index.js.map +1 -1
- package/dist/types/index.d.ts +2 -2
- package/dist/utils/arc/content.d.ts +3 -1
- package/package.json +12 -5
package/dist/index.js
CHANGED
|
@@ -5,11 +5,11 @@ import fs from 'node:fs';
|
|
|
5
5
|
import path from 'node:path';
|
|
6
6
|
import FormData from 'form-data';
|
|
7
7
|
import * as ws from 'ws';
|
|
8
|
+
import { TextNode, HTMLElement, CommentNode, parse } from 'node-html-parser';
|
|
9
|
+
import { decode } from 'html-entities';
|
|
8
10
|
import encode from 'base32-encode';
|
|
9
11
|
import { v5 } from 'uuid';
|
|
10
12
|
import assert from 'node:assert';
|
|
11
|
-
import { TextNode, HTMLElement, CommentNode, parse } from 'node-html-parser';
|
|
12
|
-
import { decode } from 'html-entities';
|
|
13
13
|
|
|
14
14
|
const safeJSONStringify = (data) => {
|
|
15
15
|
try {
|
|
@@ -113,28 +113,6 @@ class ArcAuthor extends ArcAbstractAPI {
|
|
|
113
113
|
}
|
|
114
114
|
}
|
|
115
115
|
|
|
116
|
-
class ArcContentOps extends ArcAbstractAPI {
|
|
117
|
-
constructor(options) {
|
|
118
|
-
super({ ...options, apiPath: 'contentops/v1' });
|
|
119
|
-
}
|
|
120
|
-
async schedulePublish(payload) {
|
|
121
|
-
const { data } = await this.client.put('/publish', payload);
|
|
122
|
-
return data;
|
|
123
|
-
}
|
|
124
|
-
async scheduleUnpublish(payload) {
|
|
125
|
-
const { data } = await this.client.put('/unpublish', payload);
|
|
126
|
-
return data;
|
|
127
|
-
}
|
|
128
|
-
async unscheduleUnpublish(payload) {
|
|
129
|
-
const { data } = await this.client.put('/unschedule_unpublish', payload);
|
|
130
|
-
return data;
|
|
131
|
-
}
|
|
132
|
-
async unschedulePublish(payload) {
|
|
133
|
-
const { data } = await this.client.put('/unschedule_publish', payload);
|
|
134
|
-
return data;
|
|
135
|
-
}
|
|
136
|
-
}
|
|
137
|
-
|
|
138
116
|
class ArcContent extends ArcAbstractAPI {
|
|
139
117
|
constructor(options) {
|
|
140
118
|
super({ ...options, apiPath: 'content/v4' });
|
|
@@ -159,6 +137,28 @@ class ArcContent extends ArcAbstractAPI {
|
|
|
159
137
|
}
|
|
160
138
|
}
|
|
161
139
|
|
|
140
|
+
class ArcContentOps extends ArcAbstractAPI {
|
|
141
|
+
constructor(options) {
|
|
142
|
+
super({ ...options, apiPath: 'contentops/v1' });
|
|
143
|
+
}
|
|
144
|
+
async schedulePublish(payload) {
|
|
145
|
+
const { data } = await this.client.put('/publish', payload);
|
|
146
|
+
return data;
|
|
147
|
+
}
|
|
148
|
+
async scheduleUnpublish(payload) {
|
|
149
|
+
const { data } = await this.client.put('/unpublish', payload);
|
|
150
|
+
return data;
|
|
151
|
+
}
|
|
152
|
+
async unscheduleUnpublish(payload) {
|
|
153
|
+
const { data } = await this.client.put('/unschedule_unpublish', payload);
|
|
154
|
+
return data;
|
|
155
|
+
}
|
|
156
|
+
async unschedulePublish(payload) {
|
|
157
|
+
const { data } = await this.client.put('/unschedule_publish', payload);
|
|
158
|
+
return data;
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
|
|
162
162
|
class Custom extends ArcAbstractAPI {
|
|
163
163
|
constructor(options) {
|
|
164
164
|
super({ ...options, apiPath: '' });
|
|
@@ -172,6 +172,128 @@ class Custom extends ArcAbstractAPI {
|
|
|
172
172
|
}
|
|
173
173
|
}
|
|
174
174
|
|
|
175
|
+
class ArcDeveloperRetail extends ArcAbstractAPI {
|
|
176
|
+
constructor(options) {
|
|
177
|
+
super({ ...options, apiPath: 'retail/api/v1' });
|
|
178
|
+
}
|
|
179
|
+
// ============================================
|
|
180
|
+
// Product Methods
|
|
181
|
+
// ============================================
|
|
182
|
+
async getProductById(id, params) {
|
|
183
|
+
const { data } = await this.client.get(`/product/${id}`, { params });
|
|
184
|
+
return data;
|
|
185
|
+
}
|
|
186
|
+
async getProductBySku(sku, params) {
|
|
187
|
+
const { data } = await this.client.get(`/product/sku/${sku}`, { params });
|
|
188
|
+
return data;
|
|
189
|
+
}
|
|
190
|
+
async getProductByPriceCode(priceCode, params) {
|
|
191
|
+
const { data } = await this.client.get(`/product/pricecode/${priceCode}`, { params });
|
|
192
|
+
return data;
|
|
193
|
+
}
|
|
194
|
+
async getAllProducts(params) {
|
|
195
|
+
const { data } = await this.client.get('/product', { params });
|
|
196
|
+
return data;
|
|
197
|
+
}
|
|
198
|
+
// ============================================
|
|
199
|
+
// Pricing Strategy Methods
|
|
200
|
+
// ============================================
|
|
201
|
+
async getPricingStrategyById(id, params) {
|
|
202
|
+
const { data } = await this.client.get(`/pricing/strategy/${id}`, { params });
|
|
203
|
+
return data;
|
|
204
|
+
}
|
|
205
|
+
async getAllPricingStrategies(params) {
|
|
206
|
+
const { data } = await this.client.get('/pricing/strategy', { params });
|
|
207
|
+
return data;
|
|
208
|
+
}
|
|
209
|
+
// ============================================
|
|
210
|
+
// Pricing Rate Methods
|
|
211
|
+
// ============================================
|
|
212
|
+
async getPricingRateById(id, params) {
|
|
213
|
+
const { data } = await this.client.get(`/pricing/rate/${id}`, { params });
|
|
214
|
+
return data;
|
|
215
|
+
}
|
|
216
|
+
async getAllPricingRates(params) {
|
|
217
|
+
const { data } = await this.client.get('/pricing/rate', { params });
|
|
218
|
+
return data;
|
|
219
|
+
}
|
|
220
|
+
// ============================================
|
|
221
|
+
// Pricing Cycle Methods
|
|
222
|
+
// ============================================
|
|
223
|
+
async getPricingCycle(priceCode, cycleIndex, startDate, params) {
|
|
224
|
+
const { data } = await this.client.get(`/pricing/cycle/${priceCode}/${cycleIndex}/${startDate}`, {
|
|
225
|
+
params,
|
|
226
|
+
});
|
|
227
|
+
return data;
|
|
228
|
+
}
|
|
229
|
+
// ============================================
|
|
230
|
+
// Campaign Methods
|
|
231
|
+
// ============================================
|
|
232
|
+
async getCampaignById(id, params) {
|
|
233
|
+
const { data } = await this.client.get(`/campaign/${id}`, { params });
|
|
234
|
+
return data;
|
|
235
|
+
}
|
|
236
|
+
async getCampaignByName(campaignName, params) {
|
|
237
|
+
const { data } = await this.client.get(`/campaign/${campaignName}/get`, { params });
|
|
238
|
+
return data;
|
|
239
|
+
}
|
|
240
|
+
async getAllCampaigns(params) {
|
|
241
|
+
const { data } = await this.client.get('/campaign', { params });
|
|
242
|
+
return data;
|
|
243
|
+
}
|
|
244
|
+
// ============================================
|
|
245
|
+
// Campaign Category Methods
|
|
246
|
+
// ============================================
|
|
247
|
+
async getCampaignCategoryById(id, params) {
|
|
248
|
+
const { data } = await this.client.get(`/campaign/category/${id}`, { params });
|
|
249
|
+
return data;
|
|
250
|
+
}
|
|
251
|
+
async getAllCampaignCategories(params) {
|
|
252
|
+
const { data } = await this.client.get('/campaign/category', { params });
|
|
253
|
+
return data;
|
|
254
|
+
}
|
|
255
|
+
// ============================================
|
|
256
|
+
// Offer Methods
|
|
257
|
+
// ============================================
|
|
258
|
+
async getOfferById(id, params) {
|
|
259
|
+
const { data } = await this.client.get(`/offer/${id}`, { params });
|
|
260
|
+
return data;
|
|
261
|
+
}
|
|
262
|
+
async getAllOffers(params) {
|
|
263
|
+
const { data } = await this.client.get('/offer', { params });
|
|
264
|
+
return data;
|
|
265
|
+
}
|
|
266
|
+
// ============================================
|
|
267
|
+
// Offer Attribute Methods
|
|
268
|
+
// ============================================
|
|
269
|
+
async getOfferAttributeById(id, params) {
|
|
270
|
+
const { data } = await this.client.get(`/offer/attribute/${id}`, { params });
|
|
271
|
+
return data;
|
|
272
|
+
}
|
|
273
|
+
async getAllOfferAttributes(params) {
|
|
274
|
+
const { data } = await this.client.get('/offer/attribute', { params });
|
|
275
|
+
return data;
|
|
276
|
+
}
|
|
277
|
+
// ============================================
|
|
278
|
+
// Product Attribute Methods
|
|
279
|
+
// ============================================
|
|
280
|
+
async getProductAttributeById(id, params) {
|
|
281
|
+
const { data } = await this.client.get(`/product/attribute/${id}`, { params });
|
|
282
|
+
return data;
|
|
283
|
+
}
|
|
284
|
+
async getAllProductAttributes(params) {
|
|
285
|
+
const { data } = await this.client.get('/product/attribute', { params });
|
|
286
|
+
return data;
|
|
287
|
+
}
|
|
288
|
+
// ============================================
|
|
289
|
+
// Condition Category Methods
|
|
290
|
+
// ============================================
|
|
291
|
+
async getAllConditionCategories(params) {
|
|
292
|
+
const { data } = await this.client.get('/condition/categories', { params });
|
|
293
|
+
return data;
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
|
|
175
297
|
class ArcDraft extends ArcAbstractAPI {
|
|
176
298
|
constructor(options) {
|
|
177
299
|
super({ ...options, apiPath: 'draft/v1' });
|
|
@@ -208,6 +330,10 @@ class ArcDraft extends ArcAbstractAPI {
|
|
|
208
330
|
const { data } = await this.client.get(`/${type}/${id}/circulation`, { params: { after } });
|
|
209
331
|
return data;
|
|
210
332
|
}
|
|
333
|
+
async deleteCirculation(id, website, type = 'story') {
|
|
334
|
+
const { data } = await this.client.delete(`/${type}/${id}/circulation/${website}`);
|
|
335
|
+
return data;
|
|
336
|
+
}
|
|
211
337
|
async getRevisions(id, type = 'story', after) {
|
|
212
338
|
const { data } = await this.client.get(`/${type}/${id}/revision`, { params: { after } });
|
|
213
339
|
return data;
|
|
@@ -564,190 +690,68 @@ class ArcRetailEvents {
|
|
|
564
690
|
}
|
|
565
691
|
}
|
|
566
692
|
|
|
567
|
-
class
|
|
693
|
+
class ArcSales extends ArcAbstractAPI {
|
|
568
694
|
constructor(options) {
|
|
569
|
-
super({ ...options, apiPath: '
|
|
695
|
+
super({ ...options, apiPath: 'sales/api/v1' });
|
|
570
696
|
}
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
const { data } = await this.client.
|
|
697
|
+
async migrate(params, payload) {
|
|
698
|
+
const FormData = await platform.form_data();
|
|
699
|
+
const form = new FormData();
|
|
700
|
+
form.append('file', JSON.stringify(payload), { filename: 'subs.json', contentType: 'application/json' });
|
|
701
|
+
const { data } = await this.client.post('/migrate', form, {
|
|
702
|
+
params,
|
|
703
|
+
headers: {
|
|
704
|
+
...form.getHeaders(),
|
|
705
|
+
},
|
|
706
|
+
});
|
|
576
707
|
return data;
|
|
577
708
|
}
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
709
|
+
}
|
|
710
|
+
class ArcSalesV2 extends ArcAbstractAPI {
|
|
711
|
+
constructor(options) {
|
|
712
|
+
super({ ...options, apiPath: 'sales/api/v2' });
|
|
581
713
|
}
|
|
582
|
-
async
|
|
583
|
-
const { data } = await this.client.get(
|
|
714
|
+
async getEnterpriseGroups(params) {
|
|
715
|
+
const { data } = await this.client.get('/subscriptions/enterprise', {
|
|
716
|
+
params: {
|
|
717
|
+
'arc-site': params.site,
|
|
718
|
+
},
|
|
719
|
+
});
|
|
584
720
|
return data;
|
|
585
721
|
}
|
|
586
|
-
async
|
|
587
|
-
const { data } = await this.client.
|
|
722
|
+
async createEnterpriseGroup(params, payload) {
|
|
723
|
+
const { data } = await this.client.post('/subscriptions/enterprise', payload, {
|
|
724
|
+
params: {
|
|
725
|
+
'arc-site': params.site,
|
|
726
|
+
},
|
|
727
|
+
});
|
|
588
728
|
return data;
|
|
589
729
|
}
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
const { data } = await this.client.get(`/pricing/strategy/${id}`, { params });
|
|
730
|
+
async createNonce(website, enterpriseGroupId) {
|
|
731
|
+
const { data } = await this.client.get(`/subscriptions/enterprise/${enterpriseGroupId}`, {
|
|
732
|
+
params: { 'arc-site': website },
|
|
733
|
+
});
|
|
595
734
|
return data;
|
|
596
735
|
}
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
736
|
+
}
|
|
737
|
+
|
|
738
|
+
class ArcSigningService extends ArcAbstractAPI {
|
|
739
|
+
constructor(options) {
|
|
740
|
+
super({ ...options, apiPath: 'signing-service' });
|
|
600
741
|
}
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
// ============================================
|
|
604
|
-
async getPricingRateById(id, params) {
|
|
605
|
-
const { data } = await this.client.get(`/pricing/rate/${id}`, { params });
|
|
742
|
+
async sign(service, serviceVersion, imageId) {
|
|
743
|
+
const { data } = await this.client.get(`/v2/sign/${service}/${serviceVersion}?value=${encodeURI(imageId)}`);
|
|
606
744
|
return data;
|
|
607
745
|
}
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
746
|
+
}
|
|
747
|
+
|
|
748
|
+
class ArcSite extends ArcAbstractAPI {
|
|
749
|
+
constructor(options) {
|
|
750
|
+
super({ ...options, apiPath: 'site/v3' });
|
|
611
751
|
}
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
async getPricingCycle(priceCode, cycleIndex, startDate, params) {
|
|
616
|
-
const { data } = await this.client.get(`/pricing/cycle/${priceCode}/${cycleIndex}/${startDate}`, {
|
|
617
|
-
params,
|
|
618
|
-
});
|
|
619
|
-
return data;
|
|
620
|
-
}
|
|
621
|
-
// ============================================
|
|
622
|
-
// Campaign Methods
|
|
623
|
-
// ============================================
|
|
624
|
-
async getCampaignById(id, params) {
|
|
625
|
-
const { data } = await this.client.get(`/campaign/${id}`, { params });
|
|
626
|
-
return data;
|
|
627
|
-
}
|
|
628
|
-
async getCampaignByName(campaignName, params) {
|
|
629
|
-
const { data } = await this.client.get(`/campaign/${campaignName}/get`, { params });
|
|
630
|
-
return data;
|
|
631
|
-
}
|
|
632
|
-
async getAllCampaigns(params) {
|
|
633
|
-
const { data } = await this.client.get('/campaign', { params });
|
|
634
|
-
return data;
|
|
635
|
-
}
|
|
636
|
-
// ============================================
|
|
637
|
-
// Campaign Category Methods
|
|
638
|
-
// ============================================
|
|
639
|
-
async getCampaignCategoryById(id, params) {
|
|
640
|
-
const { data } = await this.client.get(`/campaign/category/${id}`, { params });
|
|
641
|
-
return data;
|
|
642
|
-
}
|
|
643
|
-
async getAllCampaignCategories(params) {
|
|
644
|
-
const { data } = await this.client.get('/campaign/category', { params });
|
|
645
|
-
return data;
|
|
646
|
-
}
|
|
647
|
-
// ============================================
|
|
648
|
-
// Offer Methods
|
|
649
|
-
// ============================================
|
|
650
|
-
async getOfferById(id, params) {
|
|
651
|
-
const { data } = await this.client.get(`/offer/${id}`, { params });
|
|
652
|
-
return data;
|
|
653
|
-
}
|
|
654
|
-
async getAllOffers(params) {
|
|
655
|
-
const { data } = await this.client.get('/offer', { params });
|
|
656
|
-
return data;
|
|
657
|
-
}
|
|
658
|
-
// ============================================
|
|
659
|
-
// Offer Attribute Methods
|
|
660
|
-
// ============================================
|
|
661
|
-
async getOfferAttributeById(id, params) {
|
|
662
|
-
const { data } = await this.client.get(`/offer/attribute/${id}`, { params });
|
|
663
|
-
return data;
|
|
664
|
-
}
|
|
665
|
-
async getAllOfferAttributes(params) {
|
|
666
|
-
const { data } = await this.client.get('/offer/attribute', { params });
|
|
667
|
-
return data;
|
|
668
|
-
}
|
|
669
|
-
// ============================================
|
|
670
|
-
// Product Attribute Methods
|
|
671
|
-
// ============================================
|
|
672
|
-
async getProductAttributeById(id, params) {
|
|
673
|
-
const { data } = await this.client.get(`/product/attribute/${id}`, { params });
|
|
674
|
-
return data;
|
|
675
|
-
}
|
|
676
|
-
async getAllProductAttributes(params) {
|
|
677
|
-
const { data } = await this.client.get('/product/attribute', { params });
|
|
678
|
-
return data;
|
|
679
|
-
}
|
|
680
|
-
// ============================================
|
|
681
|
-
// Condition Category Methods
|
|
682
|
-
// ============================================
|
|
683
|
-
async getAllConditionCategories(params) {
|
|
684
|
-
const { data } = await this.client.get('/condition/categories', { params });
|
|
685
|
-
return data;
|
|
686
|
-
}
|
|
687
|
-
}
|
|
688
|
-
|
|
689
|
-
class ArcSales extends ArcAbstractAPI {
|
|
690
|
-
constructor(options) {
|
|
691
|
-
super({ ...options, apiPath: 'sales/api/v1' });
|
|
692
|
-
}
|
|
693
|
-
async migrate(params, payload) {
|
|
694
|
-
const FormData = await platform.form_data();
|
|
695
|
-
const form = new FormData();
|
|
696
|
-
form.append('file', JSON.stringify(payload), { filename: 'subs.json', contentType: 'application/json' });
|
|
697
|
-
const { data } = await this.client.post('/migrate', form, {
|
|
698
|
-
params,
|
|
699
|
-
headers: {
|
|
700
|
-
...form.getHeaders(),
|
|
701
|
-
},
|
|
702
|
-
});
|
|
703
|
-
return data;
|
|
704
|
-
}
|
|
705
|
-
}
|
|
706
|
-
class ArcSalesV2 extends ArcAbstractAPI {
|
|
707
|
-
constructor(options) {
|
|
708
|
-
super({ ...options, apiPath: 'sales/api/v2' });
|
|
709
|
-
}
|
|
710
|
-
async getEnterpriseGroups(params) {
|
|
711
|
-
const { data } = await this.client.get('/subscriptions/enterprise', {
|
|
712
|
-
params: {
|
|
713
|
-
'arc-site': params.site,
|
|
714
|
-
},
|
|
715
|
-
});
|
|
716
|
-
return data;
|
|
717
|
-
}
|
|
718
|
-
async createEnterpriseGroup(params, payload) {
|
|
719
|
-
const { data } = await this.client.post('/subscriptions/enterprise', payload, {
|
|
720
|
-
params: {
|
|
721
|
-
'arc-site': params.site,
|
|
722
|
-
},
|
|
723
|
-
});
|
|
724
|
-
return data;
|
|
725
|
-
}
|
|
726
|
-
async createNonce(website, enterpriseGroupId) {
|
|
727
|
-
const { data } = await this.client.get(`/subscriptions/enterprise/${enterpriseGroupId}`, {
|
|
728
|
-
params: { 'arc-site': website },
|
|
729
|
-
});
|
|
730
|
-
return data;
|
|
731
|
-
}
|
|
732
|
-
}
|
|
733
|
-
|
|
734
|
-
class ArcSigningService extends ArcAbstractAPI {
|
|
735
|
-
constructor(options) {
|
|
736
|
-
super({ ...options, apiPath: 'signing-service' });
|
|
737
|
-
}
|
|
738
|
-
async sign(service, serviceVersion, imageId) {
|
|
739
|
-
const { data } = await this.client.get(`/v2/sign/${service}/${serviceVersion}?value=${encodeURI(imageId)}`);
|
|
740
|
-
return data;
|
|
741
|
-
}
|
|
742
|
-
}
|
|
743
|
-
|
|
744
|
-
class ArcSite extends ArcAbstractAPI {
|
|
745
|
-
constructor(options) {
|
|
746
|
-
super({ ...options, apiPath: 'site/v3' });
|
|
747
|
-
}
|
|
748
|
-
async getSections(params) {
|
|
749
|
-
const { data } = await this.client.get(`/website/${params.website}/section`, {
|
|
750
|
-
params: { _website: params.website, ...params },
|
|
752
|
+
async getSections(params) {
|
|
753
|
+
const { data } = await this.client.get(`/website/${params.website}/section`, {
|
|
754
|
+
params: { _website: params.website, ...params },
|
|
751
755
|
});
|
|
752
756
|
return data;
|
|
753
757
|
}
|
|
@@ -766,6 +770,10 @@ class ArcSite extends ArcAbstractAPI {
|
|
|
766
770
|
const { data } = await this.client.get('/website');
|
|
767
771
|
return data;
|
|
768
772
|
}
|
|
773
|
+
async deleteWebsite(website) {
|
|
774
|
+
const { data } = await this.client.delete(`/website/${website}`);
|
|
775
|
+
return data;
|
|
776
|
+
}
|
|
769
777
|
async putLink(link) {
|
|
770
778
|
const { data } = await this.client.put(`/website/${link._website}/link/${link._id}`, link);
|
|
771
779
|
return data;
|
|
@@ -881,84 +889,6 @@ const ArcAPI = (options) => {
|
|
|
881
889
|
return API;
|
|
882
890
|
};
|
|
883
891
|
|
|
884
|
-
/* eslint-disable */
|
|
885
|
-
/**
|
|
886
|
-
* This file was automatically generated by json-schema-to-typescript.
|
|
887
|
-
* DO NOT MODIFY IT BY HAND. Instead, modify the source JSONSchema file,
|
|
888
|
-
* and run json-schema-to-typescript to regenerate this file.
|
|
889
|
-
*/
|
|
890
|
-
|
|
891
|
-
var ansTypes = /*#__PURE__*/Object.freeze({
|
|
892
|
-
__proto__: null
|
|
893
|
-
});
|
|
894
|
-
|
|
895
|
-
var utils = /*#__PURE__*/Object.freeze({
|
|
896
|
-
__proto__: null
|
|
897
|
-
});
|
|
898
|
-
|
|
899
|
-
var ANSType;
|
|
900
|
-
(function (ANSType) {
|
|
901
|
-
ANSType["Story"] = "story";
|
|
902
|
-
ANSType["Video"] = "video";
|
|
903
|
-
ANSType["Tag"] = "tag";
|
|
904
|
-
ANSType["Author"] = "author";
|
|
905
|
-
ANSType["Gallery"] = "gallery";
|
|
906
|
-
ANSType["Image"] = "image";
|
|
907
|
-
ANSType["Redirect"] = "redirect";
|
|
908
|
-
})(ANSType || (ANSType = {}));
|
|
909
|
-
var MigrationStatus;
|
|
910
|
-
(function (MigrationStatus) {
|
|
911
|
-
MigrationStatus["Success"] = "Success";
|
|
912
|
-
MigrationStatus["Queued"] = "Queued";
|
|
913
|
-
MigrationStatus["Circulated"] = "Circulated";
|
|
914
|
-
MigrationStatus["Published"] = "Published";
|
|
915
|
-
MigrationStatus["Scheduled"] = "Scheduled";
|
|
916
|
-
MigrationStatus["FailVideo"] = "FailVideo";
|
|
917
|
-
MigrationStatus["FailImage"] = "FailImage";
|
|
918
|
-
MigrationStatus["FailPhoto"] = "FailPhoto";
|
|
919
|
-
MigrationStatus["FailStory"] = "FailStory";
|
|
920
|
-
MigrationStatus["FailGallery"] = "FailGallery";
|
|
921
|
-
MigrationStatus["FailAuthor"] = "FailAuthor";
|
|
922
|
-
MigrationStatus["FailTag"] = "FailTag";
|
|
923
|
-
MigrationStatus["ValidationFailed"] = "ValidationFailed";
|
|
924
|
-
})(MigrationStatus || (MigrationStatus = {}));
|
|
925
|
-
var SummarySortBy;
|
|
926
|
-
(function (SummarySortBy) {
|
|
927
|
-
SummarySortBy["CreateDate"] = "createDate";
|
|
928
|
-
SummarySortBy["UpdateDate"] = "updateDate";
|
|
929
|
-
SummarySortBy["Id"] = "id";
|
|
930
|
-
})(SummarySortBy || (SummarySortBy = {}));
|
|
931
|
-
var SummarySortOrder;
|
|
932
|
-
(function (SummarySortOrder) {
|
|
933
|
-
SummarySortOrder["ASC"] = "ASC";
|
|
934
|
-
SummarySortOrder["DESC"] = "DESC";
|
|
935
|
-
})(SummarySortOrder || (SummarySortOrder = {}));
|
|
936
|
-
|
|
937
|
-
var index$3 = /*#__PURE__*/Object.freeze({
|
|
938
|
-
__proto__: null,
|
|
939
|
-
ANS: ansTypes,
|
|
940
|
-
get ANSType () { return ANSType; },
|
|
941
|
-
get MigrationStatus () { return MigrationStatus; },
|
|
942
|
-
get SummarySortBy () { return SummarySortBy; },
|
|
943
|
-
get SummarySortOrder () { return SummarySortOrder; },
|
|
944
|
-
TypeUtils: utils
|
|
945
|
-
});
|
|
946
|
-
|
|
947
|
-
const reference = (ref) => {
|
|
948
|
-
return {
|
|
949
|
-
_id: ref.id,
|
|
950
|
-
type: 'reference',
|
|
951
|
-
referent: {
|
|
952
|
-
...ref,
|
|
953
|
-
},
|
|
954
|
-
};
|
|
955
|
-
};
|
|
956
|
-
|
|
957
|
-
var ANS = /*#__PURE__*/Object.freeze({
|
|
958
|
-
__proto__: null,
|
|
959
|
-
reference: reference
|
|
960
|
-
});
|
|
961
|
-
|
|
962
892
|
const ContentElement = {
|
|
963
893
|
divider: () => {
|
|
964
894
|
return {
|
|
@@ -1191,18 +1121,60 @@ const ContentElement = {
|
|
|
1191
1121
|
},
|
|
1192
1122
|
};
|
|
1193
1123
|
|
|
1124
|
+
const BLOCK_ELEMENT_TAGS = [
|
|
1125
|
+
'ADDRESS',
|
|
1126
|
+
'ARTICLE',
|
|
1127
|
+
'ASIDE',
|
|
1128
|
+
'BLOCKQUOTE',
|
|
1129
|
+
'DETAILS',
|
|
1130
|
+
'DIV',
|
|
1131
|
+
'DL',
|
|
1132
|
+
'FIELDSET',
|
|
1133
|
+
'FIGCAPTION',
|
|
1134
|
+
'FIGURE',
|
|
1135
|
+
'FOOTER',
|
|
1136
|
+
'FORM',
|
|
1137
|
+
'H1',
|
|
1138
|
+
'H2',
|
|
1139
|
+
'H3',
|
|
1140
|
+
'H4',
|
|
1141
|
+
'H5',
|
|
1142
|
+
'H6',
|
|
1143
|
+
'HEADER',
|
|
1144
|
+
'HR',
|
|
1145
|
+
'LINE',
|
|
1146
|
+
'MAIN',
|
|
1147
|
+
'MENU',
|
|
1148
|
+
'NAV',
|
|
1149
|
+
'OL',
|
|
1150
|
+
'P',
|
|
1151
|
+
'PARAGRAPH',
|
|
1152
|
+
'PRE',
|
|
1153
|
+
'SECTION',
|
|
1154
|
+
'TABLE',
|
|
1155
|
+
'UL',
|
|
1156
|
+
'LI',
|
|
1157
|
+
'BODY',
|
|
1158
|
+
'HTML',
|
|
1159
|
+
];
|
|
1160
|
+
|
|
1161
|
+
var html_constants = /*#__PURE__*/Object.freeze({
|
|
1162
|
+
__proto__: null,
|
|
1163
|
+
BLOCK_ELEMENT_TAGS: BLOCK_ELEMENT_TAGS
|
|
1164
|
+
});
|
|
1165
|
+
|
|
1194
1166
|
const socialRegExps = {
|
|
1195
|
-
instagram: /(?:https?:\/\/)?(?:www.)?instagram.com\/?([a-zA-Z0-9
|
|
1196
|
-
twitter: /https:\/\/(?:www\.)?twitter\.com\/[
|
|
1197
|
-
tiktok: /https:\/\/(?:m|www|vm)?\.?tiktok\.com\/((?:.*\b(?:(?:usr|v|embed|user|video)\/|\?shareId
|
|
1198
|
-
facebookPost: /https:\/\/www\.facebook\.com\/(photo(\.php|s)|permalink\.php|media|questions|notes|[
|
|
1199
|
-
facebookVideo: /https:\/\/www\.facebook\.com\/([
|
|
1167
|
+
instagram: /(?:https?:\/\/)?(?:www.)?instagram.com\/?([a-zA-Z0-9._-]+)?\/([p]+)?([reel]+)?([tv]+)?([stories]+)?\/([a-zA-Z0-9\-_.]+)\/?([0-9]+)?/,
|
|
1168
|
+
twitter: /https:\/\/(?:www\.)?twitter\.com\/[^/]+\/status(?:es)?\/(\d+)/,
|
|
1169
|
+
tiktok: /https:\/\/(?:m|www|vm)?\.?tiktok\.com\/((?:.*\b(?:(?:usr|v|embed|user|video)\/|\?shareId=|&item_id=)(\d+))|\w+)/,
|
|
1170
|
+
facebookPost: /https:\/\/www\.facebook\.com\/(photo(\.php|s)|permalink\.php|media|questions|notes|[^/]+\/(activity|posts))[/?].*$/,
|
|
1171
|
+
facebookVideo: /https:\/\/www\.facebook\.com\/([^/?].+\/)?video(s|\.php)[/?].*/,
|
|
1200
1172
|
};
|
|
1201
1173
|
function match(url, regex) {
|
|
1202
1174
|
return url.match(regex)?.[0];
|
|
1203
1175
|
}
|
|
1204
1176
|
function youtubeURLParser(url = '') {
|
|
1205
|
-
const regExp = /(?:youtube(?:-nocookie)?\.com\/(?:[
|
|
1177
|
+
const regExp = /(?:youtube(?:-nocookie)?\.com\/(?:[^/\n\s]+\/\S+\/|(?:v|e(?:mbed)?)\/|\S*?[?&]vi?=)|youtu\.be\/)([a-zA-Z0-9_-]{11})/;
|
|
1206
1178
|
const id = url?.match(regExp)?.[1];
|
|
1207
1179
|
if (id) {
|
|
1208
1180
|
return `https://youtu.be/${id}`;
|
|
@@ -1257,249 +1229,451 @@ function createSocial(url = '') {
|
|
|
1257
1229
|
return embeds;
|
|
1258
1230
|
}
|
|
1259
1231
|
const randomId = () => `${new Date().toISOString()}-${Math.random()}`;
|
|
1260
|
-
|
|
1261
|
-
|
|
1232
|
+
const isTextCE = (ce) => {
|
|
1233
|
+
return ce?.type === 'text';
|
|
1234
|
+
};
|
|
1235
|
+
const decodeHTMLEntities = (str) => decode(str);
|
|
1236
|
+
|
|
1237
|
+
var ContentElements = /*#__PURE__*/Object.freeze({
|
|
1262
1238
|
__proto__: null,
|
|
1263
1239
|
createSocial: createSocial,
|
|
1240
|
+
decodeHTMLEntities: decodeHTMLEntities,
|
|
1264
1241
|
facebookPostURLParser: facebookPostURLParser,
|
|
1265
1242
|
facebookVideoURLParser: facebookVideoURLParser,
|
|
1266
1243
|
instagramURLParser: instagramURLParser,
|
|
1244
|
+
isTextCE: isTextCE,
|
|
1267
1245
|
randomId: randomId,
|
|
1268
1246
|
tiktokURLParser: tiktokURLParser,
|
|
1269
1247
|
twitterURLParser: twitterURLParser,
|
|
1270
1248
|
youtubeURLParser: youtubeURLParser
|
|
1271
1249
|
});
|
|
1272
1250
|
|
|
1273
|
-
const
|
|
1274
|
-
|
|
1275
|
-
const buffer = v5(identifier, namespace, Buffer.alloc(16));
|
|
1276
|
-
return encode(buffer, 'RFC4648', { padding: false });
|
|
1251
|
+
const isTextNode = (node) => {
|
|
1252
|
+
return node instanceof TextNode;
|
|
1277
1253
|
};
|
|
1278
|
-
|
|
1279
|
-
|
|
1280
|
-
*
|
|
1281
|
-
* @example
|
|
1282
|
-
* ```ts
|
|
1283
|
-
* const generator = new IdGenerator(['my-org']);
|
|
1284
|
-
* const arcId = generator.getArcId('123'); // Generates a unique for 'my-org' Arc ID
|
|
1285
|
-
* const sourceId = generator.getSourceId('123', ['my-site']); // Generates 'my-site-123'
|
|
1286
|
-
* ```
|
|
1287
|
-
*/
|
|
1288
|
-
class IdGenerator {
|
|
1289
|
-
constructor(namespaces) {
|
|
1290
|
-
if (!namespaces.length) {
|
|
1291
|
-
throw new Error('At least 1 namespace is required');
|
|
1292
|
-
}
|
|
1293
|
-
this.namespace = namespaces.join('-');
|
|
1294
|
-
}
|
|
1295
|
-
getArcId(id) {
|
|
1296
|
-
return generateArcId(id.toString(), this.namespace);
|
|
1297
|
-
}
|
|
1298
|
-
getSourceId(id, prefixes = []) {
|
|
1299
|
-
return [...prefixes, id].join('-');
|
|
1300
|
-
}
|
|
1301
|
-
}
|
|
1302
|
-
|
|
1303
|
-
var Id = /*#__PURE__*/Object.freeze({
|
|
1304
|
-
__proto__: null,
|
|
1305
|
-
IdGenerator: IdGenerator,
|
|
1306
|
-
generateArcId: generateArcId
|
|
1307
|
-
});
|
|
1308
|
-
|
|
1309
|
-
const buildTree = (items) => {
|
|
1310
|
-
const tree = [
|
|
1311
|
-
{
|
|
1312
|
-
id: '/',
|
|
1313
|
-
children: [],
|
|
1314
|
-
meta: new Proxy({}, {
|
|
1315
|
-
get: () => {
|
|
1316
|
-
throw new Error('Root node meta is not accessible');
|
|
1317
|
-
},
|
|
1318
|
-
}),
|
|
1319
|
-
parent: null,
|
|
1320
|
-
},
|
|
1321
|
-
];
|
|
1322
|
-
// Track nodes at each level to maintain parent-child relationships
|
|
1323
|
-
// stores last node at each level
|
|
1324
|
-
const currLevelNodes = {
|
|
1325
|
-
0: tree[0],
|
|
1326
|
-
};
|
|
1327
|
-
for (const item of items) {
|
|
1328
|
-
const node = {
|
|
1329
|
-
id: item.id,
|
|
1330
|
-
parent: null,
|
|
1331
|
-
children: [],
|
|
1332
|
-
meta: item,
|
|
1333
|
-
};
|
|
1334
|
-
// Determine the level of this node
|
|
1335
|
-
const levelKey = Object.keys(item).find((key) => key.startsWith('N') && item[key]);
|
|
1336
|
-
const level = Number(levelKey?.replace('N', '')) || 0;
|
|
1337
|
-
if (!level) {
|
|
1338
|
-
throw new Error(`Invalid level for section ${item.id}`);
|
|
1339
|
-
}
|
|
1340
|
-
// This is a child node - attach to its parent
|
|
1341
|
-
const parentLevel = level - 1;
|
|
1342
|
-
const parentNode = currLevelNodes[parentLevel];
|
|
1343
|
-
if (parentNode) {
|
|
1344
|
-
node.parent = parentNode;
|
|
1345
|
-
parentNode.children.push(node);
|
|
1346
|
-
}
|
|
1347
|
-
else {
|
|
1348
|
-
throw new Error(`Parent node not found for section ${item.id}`);
|
|
1349
|
-
}
|
|
1350
|
-
// Set this as the current node for its level
|
|
1351
|
-
currLevelNodes[level] = node;
|
|
1352
|
-
}
|
|
1353
|
-
// return root nodes children
|
|
1354
|
-
return tree[0].children;
|
|
1254
|
+
const isHTMLElement = (node) => {
|
|
1255
|
+
return node instanceof HTMLElement;
|
|
1355
1256
|
};
|
|
1356
|
-
const
|
|
1357
|
-
|
|
1358
|
-
const traverse = (node) => {
|
|
1359
|
-
flatten.push(node);
|
|
1360
|
-
for (const child of node.children) {
|
|
1361
|
-
traverse(child);
|
|
1362
|
-
}
|
|
1363
|
-
};
|
|
1364
|
-
// traverse all root nodes and their children
|
|
1365
|
-
for (const node of tree) {
|
|
1366
|
-
traverse(node);
|
|
1367
|
-
}
|
|
1368
|
-
return flatten;
|
|
1257
|
+
const isCommentNode = (node) => {
|
|
1258
|
+
return node instanceof CommentNode;
|
|
1369
1259
|
};
|
|
1370
|
-
const
|
|
1371
|
-
|
|
1372
|
-
return sections.reduce((acc, section) => {
|
|
1373
|
-
const website = section._website;
|
|
1374
|
-
if (!acc[website])
|
|
1375
|
-
acc[website] = [];
|
|
1376
|
-
acc[website].push(section);
|
|
1377
|
-
return acc;
|
|
1378
|
-
}, {});
|
|
1260
|
+
const nodeTagIs = (node, name) => {
|
|
1261
|
+
return isHTMLElement(node) && node.tagName?.toLowerCase() === name.toLowerCase();
|
|
1379
1262
|
};
|
|
1380
|
-
const
|
|
1381
|
-
return
|
|
1382
|
-
id: s._id,
|
|
1383
|
-
website: s._website,
|
|
1384
|
-
type: 'section',
|
|
1385
|
-
}));
|
|
1263
|
+
const nodeTagIn = (node, names) => {
|
|
1264
|
+
return isHTMLElement(node) && names.includes(node.tagName?.toLowerCase());
|
|
1386
1265
|
};
|
|
1387
|
-
const
|
|
1388
|
-
|
|
1266
|
+
const htmlToText = (html, parseOptions) => {
|
|
1267
|
+
if (!html)
|
|
1268
|
+
return '';
|
|
1269
|
+
const doc = parse(html, parseOptions);
|
|
1270
|
+
return decodeHTMLEntities(doc.innerText);
|
|
1389
1271
|
};
|
|
1390
|
-
const
|
|
1391
|
-
const
|
|
1392
|
-
|
|
1393
|
-
|
|
1394
|
-
|
|
1395
|
-
}
|
|
1396
|
-
else {
|
|
1397
|
-
map.set(`${s._id}${s._website}`, s);
|
|
1398
|
-
}
|
|
1399
|
-
});
|
|
1400
|
-
return [...map.values()];
|
|
1272
|
+
const getHTMLElementAttribute = (e, key) => {
|
|
1273
|
+
const value = e.getAttribute(key);
|
|
1274
|
+
if (value)
|
|
1275
|
+
return value;
|
|
1276
|
+
return new URLSearchParams(e.rawAttrs.replaceAll(' ', '&')).get(key);
|
|
1401
1277
|
};
|
|
1402
|
-
class SectionsRepository {
|
|
1403
|
-
constructor(arc) {
|
|
1404
|
-
this.arc = arc;
|
|
1405
|
-
this.sectionsByWebsite = {};
|
|
1406
|
-
this.websitesAreLoaded = false;
|
|
1407
|
-
}
|
|
1408
|
-
async put(ans) {
|
|
1409
|
-
await this.arc.Site.putSection(ans);
|
|
1410
|
-
const created = await this.arc.Site.getSection(ans._id, ans.website);
|
|
1411
|
-
this.save(created);
|
|
1412
|
-
}
|
|
1413
|
-
async loadWebsite(website) {
|
|
1414
|
-
const sections = [];
|
|
1415
|
-
let next = true;
|
|
1416
|
-
let offset = 0;
|
|
1417
|
-
while (next) {
|
|
1418
|
-
const migrated = await this.arc.Site.getSections({ website, offset }).catch((_) => {
|
|
1419
|
-
return { q_results: [] };
|
|
1420
|
-
});
|
|
1421
|
-
if (migrated.q_results.length) {
|
|
1422
|
-
sections.push(...migrated.q_results);
|
|
1423
|
-
offset += migrated.q_results.length;
|
|
1424
|
-
}
|
|
1425
|
-
else {
|
|
1426
|
-
next = false;
|
|
1427
|
-
}
|
|
1428
|
-
}
|
|
1429
|
-
return sections;
|
|
1430
|
-
}
|
|
1431
|
-
async loadWebsites(websites) {
|
|
1432
|
-
for (const website of websites) {
|
|
1433
|
-
this.sectionsByWebsite[website] = await this.loadWebsite(website);
|
|
1434
|
-
}
|
|
1435
|
-
this.websitesAreLoaded = true;
|
|
1436
|
-
}
|
|
1437
|
-
save(section) {
|
|
1438
|
-
const website = section._website;
|
|
1439
|
-
assert.ok(website, 'Section must have a website');
|
|
1440
|
-
this.sectionsByWebsite[website] = this.sectionsByWebsite[website] || [];
|
|
1441
|
-
if (!this.sectionsByWebsite[website].find((s) => s._id === section._id)) {
|
|
1442
|
-
this.sectionsByWebsite[website].push(section);
|
|
1443
|
-
}
|
|
1444
|
-
}
|
|
1445
|
-
getById(id, website) {
|
|
1446
|
-
this.ensureWebsitesLoaded();
|
|
1447
|
-
const section = this.sectionsByWebsite[website]?.find((s) => s._id === id);
|
|
1448
|
-
return section;
|
|
1449
|
-
}
|
|
1450
|
-
getByWebsite(website) {
|
|
1451
|
-
this.ensureWebsitesLoaded();
|
|
1452
|
-
return this.sectionsByWebsite[website];
|
|
1453
|
-
}
|
|
1454
|
-
getParentSections(section) {
|
|
1455
|
-
this.ensureWebsitesLoaded();
|
|
1456
|
-
const parents = [];
|
|
1457
|
-
let current = section;
|
|
1458
|
-
while (current.parent?.default && current.parent.default !== '/') {
|
|
1459
|
-
const parent = this.getById(current.parent.default, section._website);
|
|
1460
|
-
if (!parent)
|
|
1461
|
-
break;
|
|
1462
|
-
parents.push(parent);
|
|
1463
|
-
current = parent;
|
|
1464
|
-
}
|
|
1465
|
-
return parents;
|
|
1466
|
-
}
|
|
1467
|
-
ensureWebsitesLoaded() {
|
|
1468
|
-
assert.ok(this.websitesAreLoaded, 'call .loadWebsites() first');
|
|
1469
|
-
}
|
|
1470
|
-
}
|
|
1471
1278
|
|
|
1472
|
-
var
|
|
1279
|
+
var html_utils = /*#__PURE__*/Object.freeze({
|
|
1473
1280
|
__proto__: null,
|
|
1474
|
-
|
|
1475
|
-
|
|
1476
|
-
|
|
1477
|
-
|
|
1478
|
-
|
|
1479
|
-
|
|
1480
|
-
|
|
1481
|
-
removeDuplicates: removeDuplicates
|
|
1281
|
+
getHTMLElementAttribute: getHTMLElementAttribute,
|
|
1282
|
+
htmlToText: htmlToText,
|
|
1283
|
+
isCommentNode: isCommentNode,
|
|
1284
|
+
isHTMLElement: isHTMLElement,
|
|
1285
|
+
isTextNode: isTextNode,
|
|
1286
|
+
nodeTagIn: nodeTagIn,
|
|
1287
|
+
nodeTagIs: nodeTagIs
|
|
1482
1288
|
});
|
|
1483
1289
|
|
|
1484
|
-
const ArcUtils = {
|
|
1485
|
-
Id,
|
|
1486
|
-
ANS,
|
|
1487
|
-
ContentElements,
|
|
1488
|
-
Section,
|
|
1489
|
-
};
|
|
1490
|
-
|
|
1491
1290
|
/**
|
|
1492
|
-
*
|
|
1493
|
-
*
|
|
1291
|
+
* HTMLProcessor is responsible for parsing HTML content into structured content elements.
|
|
1292
|
+
* It provides a flexible way to handle different HTML nodes and wrap text content.
|
|
1494
1293
|
*
|
|
1495
|
-
*
|
|
1496
|
-
*
|
|
1497
|
-
* Then you can override the specific methods to enrich the story with the data from BBC
|
|
1294
|
+
* The processor can be extended with custom handlers for specific node types and
|
|
1295
|
+
* wrappers for text content.
|
|
1498
1296
|
*
|
|
1499
|
-
*
|
|
1500
|
-
|
|
1501
|
-
|
|
1502
|
-
|
|
1297
|
+
* @example
|
|
1298
|
+
* ```ts
|
|
1299
|
+
* // Create and initialize processor
|
|
1300
|
+
* const processor = new HTMLProcessor();
|
|
1301
|
+
* processor.init();
|
|
1302
|
+
*
|
|
1303
|
+
* // Parse HTML content
|
|
1304
|
+
* const html = '<div><p>Some text</p><img src="image.jpg"></div>';
|
|
1305
|
+
* const elements = await processor.parse(html);
|
|
1306
|
+
* ```
|
|
1307
|
+
*
|
|
1308
|
+
* The processor comes with built-in handlers for common HTML elements like links,
|
|
1309
|
+
* text formatting (i, u, strong), and block elements. Custom handlers can be added
|
|
1310
|
+
* using the `handle()` and `wrap()` methods.
|
|
1311
|
+
*/
|
|
1312
|
+
class HTMLProcessor {
|
|
1313
|
+
constructor() {
|
|
1314
|
+
this.parallelProcessing = true;
|
|
1315
|
+
this.handlers = {
|
|
1316
|
+
node: new Map(),
|
|
1317
|
+
wrap: new Map(),
|
|
1318
|
+
};
|
|
1319
|
+
}
|
|
1320
|
+
init() {
|
|
1321
|
+
// wrappers are used to wrap the content of nested text nodes
|
|
1322
|
+
// in a specific way
|
|
1323
|
+
this.wrap('link', (node, text) => {
|
|
1324
|
+
if (nodeTagIn(node, ['a'])) {
|
|
1325
|
+
const attributes = ['href', 'target', 'rel']
|
|
1326
|
+
.map((attr) => [attr, getHTMLElementAttribute(node, attr)])
|
|
1327
|
+
.filter(([_, value]) => value)
|
|
1328
|
+
.map(([key, value]) => `${key}="${value}"`)
|
|
1329
|
+
.join(' ');
|
|
1330
|
+
return {
|
|
1331
|
+
...text,
|
|
1332
|
+
content: `<a ${attributes}>${text.content}</a>`,
|
|
1333
|
+
};
|
|
1334
|
+
}
|
|
1335
|
+
});
|
|
1336
|
+
this.wrap('i', (node, text) => {
|
|
1337
|
+
if (nodeTagIn(node, ['i'])) {
|
|
1338
|
+
return {
|
|
1339
|
+
...text,
|
|
1340
|
+
content: `<i>${text.content}</i>`,
|
|
1341
|
+
};
|
|
1342
|
+
}
|
|
1343
|
+
});
|
|
1344
|
+
this.wrap('u', (node, text) => {
|
|
1345
|
+
if (nodeTagIn(node, ['u'])) {
|
|
1346
|
+
return {
|
|
1347
|
+
...text,
|
|
1348
|
+
content: `<u>${text.content}</u>`,
|
|
1349
|
+
};
|
|
1350
|
+
}
|
|
1351
|
+
});
|
|
1352
|
+
this.wrap('sup/sub', (node, text) => {
|
|
1353
|
+
if (nodeTagIn(node, ['sup', 'sub'])) {
|
|
1354
|
+
return {
|
|
1355
|
+
...text,
|
|
1356
|
+
content: `<mark class="${node.tagName.toLowerCase()}">${text.content}</mark>`,
|
|
1357
|
+
};
|
|
1358
|
+
}
|
|
1359
|
+
});
|
|
1360
|
+
this.wrap('strong', (node, text) => {
|
|
1361
|
+
if (nodeTagIn(node, ['strong', 'b'])) {
|
|
1362
|
+
return {
|
|
1363
|
+
...text,
|
|
1364
|
+
content: `<b>${text.content}</b>`,
|
|
1365
|
+
};
|
|
1366
|
+
}
|
|
1367
|
+
});
|
|
1368
|
+
this.wrap('center', (node, text) => {
|
|
1369
|
+
if (nodeTagIn(node, ['center'])) {
|
|
1370
|
+
return {
|
|
1371
|
+
...text,
|
|
1372
|
+
alignment: 'center',
|
|
1373
|
+
};
|
|
1374
|
+
}
|
|
1375
|
+
});
|
|
1376
|
+
this.wrap('aligned-paragraph', (node, text) => {
|
|
1377
|
+
if (nodeTagIn(node, ['p'])) {
|
|
1378
|
+
const styleAttribute = getHTMLElementAttribute(node, 'style') || '';
|
|
1379
|
+
if (!styleAttribute)
|
|
1380
|
+
return text;
|
|
1381
|
+
if (styleAttribute.includes('text-align: right;')) {
|
|
1382
|
+
return {
|
|
1383
|
+
...text,
|
|
1384
|
+
alignment: 'right',
|
|
1385
|
+
};
|
|
1386
|
+
}
|
|
1387
|
+
if (styleAttribute.includes('text-align: left;')) {
|
|
1388
|
+
return {
|
|
1389
|
+
...text,
|
|
1390
|
+
alignment: 'left',
|
|
1391
|
+
};
|
|
1392
|
+
}
|
|
1393
|
+
if (styleAttribute.includes('text-align: center;')) {
|
|
1394
|
+
return {
|
|
1395
|
+
...text,
|
|
1396
|
+
alignment: 'center',
|
|
1397
|
+
};
|
|
1398
|
+
}
|
|
1399
|
+
return text;
|
|
1400
|
+
}
|
|
1401
|
+
});
|
|
1402
|
+
// handlers are used to handle specific nodes
|
|
1403
|
+
// and return a list of content elements
|
|
1404
|
+
this.handle('default', (node) => {
|
|
1405
|
+
const noTag = isHTMLElement(node) && !node.tagName;
|
|
1406
|
+
if (noTag ||
|
|
1407
|
+
nodeTagIn(node, [
|
|
1408
|
+
'p',
|
|
1409
|
+
'a',
|
|
1410
|
+
'b',
|
|
1411
|
+
'sup',
|
|
1412
|
+
'sub',
|
|
1413
|
+
'span',
|
|
1414
|
+
'strong',
|
|
1415
|
+
'em',
|
|
1416
|
+
'i',
|
|
1417
|
+
'u',
|
|
1418
|
+
'section',
|
|
1419
|
+
'main',
|
|
1420
|
+
'div',
|
|
1421
|
+
'li',
|
|
1422
|
+
'center',
|
|
1423
|
+
])) {
|
|
1424
|
+
return this.handleNested(node);
|
|
1425
|
+
}
|
|
1426
|
+
});
|
|
1427
|
+
this.handle('headers', (node) => {
|
|
1428
|
+
if (nodeTagIn(node, ['h1', 'h2', 'h3', 'h4', 'h5', 'h6'])) {
|
|
1429
|
+
return this.createHeader(node);
|
|
1430
|
+
}
|
|
1431
|
+
});
|
|
1432
|
+
this.handle('text', (node) => {
|
|
1433
|
+
if (isTextNode(node)) {
|
|
1434
|
+
return this.createText(node);
|
|
1435
|
+
}
|
|
1436
|
+
});
|
|
1437
|
+
this.handle('comment', (node) => {
|
|
1438
|
+
if (isCommentNode(node)) {
|
|
1439
|
+
return this.handleComment(node);
|
|
1440
|
+
}
|
|
1441
|
+
});
|
|
1442
|
+
this.handle('list', async (node) => {
|
|
1443
|
+
if (nodeTagIn(node, ['ul', 'ol'])) {
|
|
1444
|
+
const listType = node.tagName === 'UL' ? 'unordered' : 'ordered';
|
|
1445
|
+
return this.createList(node, listType);
|
|
1446
|
+
}
|
|
1447
|
+
});
|
|
1448
|
+
this.handle('table', (node) => {
|
|
1449
|
+
if (nodeTagIs(node, 'table')) {
|
|
1450
|
+
return this.handleTable(node);
|
|
1451
|
+
}
|
|
1452
|
+
});
|
|
1453
|
+
this.handle('iframe', (node) => {
|
|
1454
|
+
if (nodeTagIs(node, 'iframe')) {
|
|
1455
|
+
return this.handleIframe(node);
|
|
1456
|
+
}
|
|
1457
|
+
});
|
|
1458
|
+
this.handle('img', (node) => {
|
|
1459
|
+
if (nodeTagIs(node, 'img')) {
|
|
1460
|
+
return this.handleImage(node);
|
|
1461
|
+
}
|
|
1462
|
+
});
|
|
1463
|
+
this.handle('br', (node) => {
|
|
1464
|
+
if (nodeTagIs(node, 'br')) {
|
|
1465
|
+
return this.handleBreak(node);
|
|
1466
|
+
}
|
|
1467
|
+
});
|
|
1468
|
+
}
|
|
1469
|
+
handle(name, handler) {
|
|
1470
|
+
if (this.handlers.node.has(name)) {
|
|
1471
|
+
this.warn({ name }, `${name} node handler already set`);
|
|
1472
|
+
}
|
|
1473
|
+
this.handlers.node.set(name, handler);
|
|
1474
|
+
}
|
|
1475
|
+
wrap(name, handler) {
|
|
1476
|
+
if (this.handlers.wrap.has(name)) {
|
|
1477
|
+
this.warn({ name }, `${name} wrap handler already set`);
|
|
1478
|
+
}
|
|
1479
|
+
this.handlers.wrap.set(name, handler);
|
|
1480
|
+
}
|
|
1481
|
+
async parse(html) {
|
|
1482
|
+
const doc = parse(html, { comment: true });
|
|
1483
|
+
doc.removeWhitespace();
|
|
1484
|
+
const elements = await this.process(doc);
|
|
1485
|
+
const filtered = elements?.filter((e) => e.type !== 'divider');
|
|
1486
|
+
return filtered || [];
|
|
1487
|
+
}
|
|
1488
|
+
addTextAdditionalProperties(c, parent) {
|
|
1489
|
+
const additionalProperties = c.additional_properties || {};
|
|
1490
|
+
const parentNodeIsBlockElement = this.isBlockElement(parent);
|
|
1491
|
+
c.additional_properties = {
|
|
1492
|
+
...c.additional_properties,
|
|
1493
|
+
isBlockElement: additionalProperties.isBlockElement || parentNodeIsBlockElement,
|
|
1494
|
+
};
|
|
1495
|
+
return c;
|
|
1496
|
+
}
|
|
1497
|
+
/**
|
|
1498
|
+
* Wraps text content elements with additional properties and handlers.
|
|
1499
|
+
* This method iterates through an array of content elements and applies
|
|
1500
|
+
* wrappers to text elements.
|
|
1501
|
+
*
|
|
1502
|
+
* @param node - The HTML node containing the text elements
|
|
1503
|
+
**/
|
|
1504
|
+
wrapChildrenTextNodes(node, elements) {
|
|
1505
|
+
const wrapped = [];
|
|
1506
|
+
const wrappers = [...this.handlers.wrap.values()];
|
|
1507
|
+
for (const c of elements) {
|
|
1508
|
+
if (!isTextCE(c)) {
|
|
1509
|
+
wrapped.push(c);
|
|
1510
|
+
continue;
|
|
1511
|
+
}
|
|
1512
|
+
this.addTextAdditionalProperties(c, node);
|
|
1513
|
+
const handled = wrappers.map((wrapper) => wrapper(node, c)).find(Boolean);
|
|
1514
|
+
wrapped.push(handled || c);
|
|
1515
|
+
}
|
|
1516
|
+
return wrapped;
|
|
1517
|
+
}
|
|
1518
|
+
/**
|
|
1519
|
+
* Handles nested nodes by processing their children and merging text elements.
|
|
1520
|
+
* This method recursively processes the children of a given HTML node and
|
|
1521
|
+
* returns a list of content elements.
|
|
1522
|
+
*
|
|
1523
|
+
* @param node - The HTML node to process
|
|
1524
|
+
**/
|
|
1525
|
+
async handleNested(node) {
|
|
1526
|
+
const children = await this.processChildNodes(node);
|
|
1527
|
+
const filtered = children.filter(Boolean).flat();
|
|
1528
|
+
const merged = this.mergeParagraphs(filtered);
|
|
1529
|
+
const wrapped = this.wrapChildrenTextNodes(node, merged);
|
|
1530
|
+
return wrapped;
|
|
1531
|
+
}
|
|
1532
|
+
async processChildNodes(node) {
|
|
1533
|
+
if (this.parallelProcessing) {
|
|
1534
|
+
return await Promise.all(node.childNodes.map((child) => this.process(child)));
|
|
1535
|
+
}
|
|
1536
|
+
const children = [];
|
|
1537
|
+
for (const child of node.childNodes) {
|
|
1538
|
+
children.push(await this.process(child));
|
|
1539
|
+
}
|
|
1540
|
+
return children;
|
|
1541
|
+
}
|
|
1542
|
+
/**
|
|
1543
|
+
* Processes a single HTML node and converts it into content elements.
|
|
1544
|
+
* This method iterates through registered node handlers and attempts to process the node.
|
|
1545
|
+
* If a handler successfully processes the node, it returns an array of content elements.
|
|
1546
|
+
*
|
|
1547
|
+
* @param node - The HTML node to process
|
|
1548
|
+
* @returns Promise resolving to an array of content elements, or undefined if node cannot be processed
|
|
1549
|
+
*/
|
|
1550
|
+
async process(node) {
|
|
1551
|
+
let isKnownNode = false;
|
|
1552
|
+
const elements = [];
|
|
1553
|
+
for (const [name, handler] of this.handlers.node.entries()) {
|
|
1554
|
+
try {
|
|
1555
|
+
const result = await handler(node);
|
|
1556
|
+
if (result) {
|
|
1557
|
+
// if handler returns an array of elements, it means that the node was handled properly, even if there is no elements inside
|
|
1558
|
+
isKnownNode = true;
|
|
1559
|
+
elements.push(...result);
|
|
1560
|
+
break;
|
|
1561
|
+
}
|
|
1562
|
+
}
|
|
1563
|
+
catch (error) {
|
|
1564
|
+
this.warn({ node: node.toString(), error: error.toString(), name }, 'HandlerError');
|
|
1565
|
+
}
|
|
1566
|
+
}
|
|
1567
|
+
if (isKnownNode)
|
|
1568
|
+
return elements;
|
|
1569
|
+
this.warn({ node: node.toString() }, 'UnknownNodeError');
|
|
1570
|
+
}
|
|
1571
|
+
/**
|
|
1572
|
+
* Merges adjacent text content elements into a single paragraph.
|
|
1573
|
+
* This method iterates through an array of content elements and combines
|
|
1574
|
+
* adjacent text elements into a single paragraph.
|
|
1575
|
+
*
|
|
1576
|
+
* @param items - The array of content elements to merge
|
|
1577
|
+
**/
|
|
1578
|
+
mergeParagraphs(items) {
|
|
1579
|
+
const merged = [];
|
|
1580
|
+
let toMerge = [];
|
|
1581
|
+
const merge = () => {
|
|
1582
|
+
if (!toMerge.length)
|
|
1583
|
+
return;
|
|
1584
|
+
const paragraph = toMerge.reduce((acc, p) => {
|
|
1585
|
+
return {
|
|
1586
|
+
...p,
|
|
1587
|
+
content: acc.content + p.content,
|
|
1588
|
+
};
|
|
1589
|
+
}, { type: 'text', content: '' });
|
|
1590
|
+
merged.push(paragraph);
|
|
1591
|
+
toMerge = [];
|
|
1592
|
+
};
|
|
1593
|
+
for (let i = 0; i < items.length; i++) {
|
|
1594
|
+
const item = items[i];
|
|
1595
|
+
const isBlockElement = item.additional_properties?.isBlockElement;
|
|
1596
|
+
if (isTextCE(item) && !isBlockElement) {
|
|
1597
|
+
toMerge.push(item);
|
|
1598
|
+
}
|
|
1599
|
+
else {
|
|
1600
|
+
merge();
|
|
1601
|
+
merged.push(item);
|
|
1602
|
+
}
|
|
1603
|
+
}
|
|
1604
|
+
merge();
|
|
1605
|
+
return merged;
|
|
1606
|
+
}
|
|
1607
|
+
handleComment(_) {
|
|
1608
|
+
return [];
|
|
1609
|
+
}
|
|
1610
|
+
async handleTable(node) {
|
|
1611
|
+
return [ContentElement.raw_html(node.toString())];
|
|
1612
|
+
}
|
|
1613
|
+
async handleIframe(node) {
|
|
1614
|
+
return [ContentElement.raw_html(node.toString())];
|
|
1615
|
+
}
|
|
1616
|
+
async handleImage(node) {
|
|
1617
|
+
return [ContentElement.raw_html(node.toString())];
|
|
1618
|
+
}
|
|
1619
|
+
async handleBreak(_) {
|
|
1620
|
+
return [ContentElement.divider()];
|
|
1621
|
+
}
|
|
1622
|
+
async createQuote(node) {
|
|
1623
|
+
const items = await this.handleNested(node);
|
|
1624
|
+
return [ContentElement.quote(items)];
|
|
1625
|
+
}
|
|
1626
|
+
async createText(node) {
|
|
1627
|
+
const text = ContentElement.text(node.text);
|
|
1628
|
+
return [text];
|
|
1629
|
+
}
|
|
1630
|
+
filterListItems(items) {
|
|
1631
|
+
return items.filter((i) => ['text', 'list'].includes(i.type));
|
|
1632
|
+
}
|
|
1633
|
+
async createList(node, type) {
|
|
1634
|
+
const items = await this.handleNested(node);
|
|
1635
|
+
return [ContentElement.list(type, this.filterListItems(items))];
|
|
1636
|
+
}
|
|
1637
|
+
async createHeader(node) {
|
|
1638
|
+
const level = +node.tagName.split('H')[1] || 3;
|
|
1639
|
+
return [ContentElement.header(node.innerText, level)];
|
|
1640
|
+
}
|
|
1641
|
+
isBlockElement(node) {
|
|
1642
|
+
if (!isHTMLElement(node))
|
|
1643
|
+
return false;
|
|
1644
|
+
const defaultBlockElements = new Set(BLOCK_ELEMENT_TAGS);
|
|
1645
|
+
return defaultBlockElements.has(node.tagName);
|
|
1646
|
+
}
|
|
1647
|
+
warn(metadata, message) {
|
|
1648
|
+
console.warn(metadata, message);
|
|
1649
|
+
}
|
|
1650
|
+
}
|
|
1651
|
+
|
|
1652
|
+
var index$3 = /*#__PURE__*/Object.freeze({
|
|
1653
|
+
__proto__: null,
|
|
1654
|
+
Constants: html_constants,
|
|
1655
|
+
HTMLProcessor: HTMLProcessor,
|
|
1656
|
+
Utils: html_utils
|
|
1657
|
+
});
|
|
1658
|
+
|
|
1659
|
+
var index$2 = /*#__PURE__*/Object.freeze({
|
|
1660
|
+
__proto__: null,
|
|
1661
|
+
ContentElement: ContentElement,
|
|
1662
|
+
HTML: index$3
|
|
1663
|
+
});
|
|
1664
|
+
|
|
1665
|
+
/**
|
|
1666
|
+
* Base class for all arc entities, it provides common methods and properties
|
|
1667
|
+
* If you want to create a new entity subtype you should extend this class
|
|
1668
|
+
*
|
|
1669
|
+
* Use case: You want to migrate stories from BBC
|
|
1670
|
+
* You define `class BBCStory extends ArcDocument<ANS.AStory>` and implement all abstract methods
|
|
1671
|
+
* Then you can override the specific methods to enrich the story with the data from BBC
|
|
1672
|
+
*
|
|
1673
|
+
* To migrate it call .migrate() method
|
|
1674
|
+
*/
|
|
1675
|
+
class Document {
|
|
1676
|
+
constructor() {
|
|
1503
1677
|
this.ans = null;
|
|
1504
1678
|
this.circulations = [];
|
|
1505
1679
|
}
|
|
@@ -1736,473 +1910,307 @@ class Story extends Document {
|
|
|
1736
1910
|
}
|
|
1737
1911
|
}
|
|
1738
1912
|
|
|
1739
|
-
var index$
|
|
1913
|
+
var index$1 = /*#__PURE__*/Object.freeze({
|
|
1740
1914
|
__proto__: null,
|
|
1741
1915
|
Document: Document,
|
|
1742
1916
|
Story: Story
|
|
1743
1917
|
});
|
|
1744
1918
|
|
|
1745
|
-
|
|
1746
|
-
|
|
1747
|
-
|
|
1748
|
-
|
|
1749
|
-
|
|
1750
|
-
|
|
1751
|
-
|
|
1752
|
-
|
|
1753
|
-
|
|
1754
|
-
|
|
1755
|
-
|
|
1756
|
-
|
|
1757
|
-
|
|
1758
|
-
|
|
1759
|
-
|
|
1760
|
-
|
|
1761
|
-
|
|
1762
|
-
|
|
1763
|
-
|
|
1764
|
-
|
|
1765
|
-
|
|
1766
|
-
|
|
1767
|
-
|
|
1768
|
-
|
|
1769
|
-
|
|
1770
|
-
|
|
1771
|
-
|
|
1772
|
-
|
|
1773
|
-
|
|
1774
|
-
|
|
1775
|
-
|
|
1776
|
-
|
|
1777
|
-
|
|
1778
|
-
|
|
1779
|
-
|
|
1780
|
-
];
|
|
1919
|
+
var ANSType;
|
|
1920
|
+
(function (ANSType) {
|
|
1921
|
+
ANSType["Story"] = "story";
|
|
1922
|
+
ANSType["Video"] = "video";
|
|
1923
|
+
ANSType["Tag"] = "tag";
|
|
1924
|
+
ANSType["Author"] = "author";
|
|
1925
|
+
ANSType["Gallery"] = "gallery";
|
|
1926
|
+
ANSType["Image"] = "image";
|
|
1927
|
+
ANSType["Redirect"] = "redirect";
|
|
1928
|
+
})(ANSType || (ANSType = {}));
|
|
1929
|
+
var MigrationStatus;
|
|
1930
|
+
(function (MigrationStatus) {
|
|
1931
|
+
MigrationStatus["Success"] = "Success";
|
|
1932
|
+
MigrationStatus["Queued"] = "Queued";
|
|
1933
|
+
MigrationStatus["Circulated"] = "Circulated";
|
|
1934
|
+
MigrationStatus["Published"] = "Published";
|
|
1935
|
+
MigrationStatus["Scheduled"] = "Scheduled";
|
|
1936
|
+
MigrationStatus["FailVideo"] = "FailVideo";
|
|
1937
|
+
MigrationStatus["FailImage"] = "FailImage";
|
|
1938
|
+
MigrationStatus["FailPhoto"] = "FailPhoto";
|
|
1939
|
+
MigrationStatus["FailStory"] = "FailStory";
|
|
1940
|
+
MigrationStatus["FailGallery"] = "FailGallery";
|
|
1941
|
+
MigrationStatus["FailAuthor"] = "FailAuthor";
|
|
1942
|
+
MigrationStatus["FailTag"] = "FailTag";
|
|
1943
|
+
MigrationStatus["ValidationFailed"] = "ValidationFailed";
|
|
1944
|
+
})(MigrationStatus || (MigrationStatus = {}));
|
|
1945
|
+
var SummarySortBy;
|
|
1946
|
+
(function (SummarySortBy) {
|
|
1947
|
+
SummarySortBy["CreateDate"] = "createDate";
|
|
1948
|
+
SummarySortBy["UpdateDate"] = "updateDate";
|
|
1949
|
+
SummarySortBy["Id"] = "id";
|
|
1950
|
+
})(SummarySortBy || (SummarySortBy = {}));
|
|
1951
|
+
var SummarySortOrder;
|
|
1952
|
+
(function (SummarySortOrder) {
|
|
1953
|
+
SummarySortOrder["ASC"] = "ASC";
|
|
1954
|
+
SummarySortOrder["DESC"] = "DESC";
|
|
1955
|
+
})(SummarySortOrder || (SummarySortOrder = {}));
|
|
1781
1956
|
|
|
1782
|
-
|
|
1957
|
+
/* eslint-disable */
|
|
1958
|
+
/**
|
|
1959
|
+
* This file was automatically generated by json-schema-to-typescript.
|
|
1960
|
+
* DO NOT MODIFY IT BY HAND. Instead, modify the source JSONSchema file,
|
|
1961
|
+
* and run json-schema-to-typescript to regenerate this file.
|
|
1962
|
+
*/
|
|
1963
|
+
|
|
1964
|
+
var ansTypes = /*#__PURE__*/Object.freeze({
|
|
1965
|
+
__proto__: null
|
|
1966
|
+
});
|
|
1967
|
+
|
|
1968
|
+
var utils = /*#__PURE__*/Object.freeze({
|
|
1969
|
+
__proto__: null
|
|
1970
|
+
});
|
|
1971
|
+
|
|
1972
|
+
var index = /*#__PURE__*/Object.freeze({
|
|
1783
1973
|
__proto__: null,
|
|
1784
|
-
|
|
1974
|
+
ANS: ansTypes,
|
|
1975
|
+
get ANSType () { return ANSType; },
|
|
1976
|
+
get MigrationStatus () { return MigrationStatus; },
|
|
1977
|
+
get SummarySortBy () { return SummarySortBy; },
|
|
1978
|
+
get SummarySortOrder () { return SummarySortOrder; },
|
|
1979
|
+
TypeUtils: utils
|
|
1785
1980
|
});
|
|
1786
1981
|
|
|
1787
|
-
const
|
|
1788
|
-
return
|
|
1789
|
-
|
|
1790
|
-
|
|
1791
|
-
|
|
1792
|
-
|
|
1793
|
-
|
|
1794
|
-
|
|
1795
|
-
};
|
|
1796
|
-
const nodeTagIs = (node, name) => {
|
|
1797
|
-
return isHTMLElement(node) && node.tagName?.toLowerCase() === name.toLowerCase();
|
|
1798
|
-
};
|
|
1799
|
-
const nodeTagIn = (node, names) => {
|
|
1800
|
-
return isHTMLElement(node) && names.includes(node.tagName?.toLowerCase());
|
|
1801
|
-
};
|
|
1802
|
-
const isTextCE = (ce) => {
|
|
1803
|
-
return ce?.type === 'text';
|
|
1804
|
-
};
|
|
1805
|
-
const decodeHTMLEntities = (str) => decode(str);
|
|
1806
|
-
const htmlToText = (html, parseOptions) => {
|
|
1807
|
-
if (!html)
|
|
1808
|
-
return '';
|
|
1809
|
-
const doc = parse(html, parseOptions);
|
|
1810
|
-
return decodeHTMLEntities(doc.innerText);
|
|
1811
|
-
};
|
|
1812
|
-
const getHTMLElementAttribute = (e, key) => {
|
|
1813
|
-
const value = e.getAttribute(key);
|
|
1814
|
-
if (value)
|
|
1815
|
-
return value;
|
|
1816
|
-
return new URLSearchParams(e.rawAttrs.replaceAll(' ', '&')).get(key);
|
|
1982
|
+
const reference = (ref) => {
|
|
1983
|
+
return {
|
|
1984
|
+
_id: ref.id,
|
|
1985
|
+
type: 'reference',
|
|
1986
|
+
referent: {
|
|
1987
|
+
...ref,
|
|
1988
|
+
},
|
|
1989
|
+
};
|
|
1817
1990
|
};
|
|
1818
1991
|
|
|
1819
|
-
var
|
|
1992
|
+
var ANS = /*#__PURE__*/Object.freeze({
|
|
1820
1993
|
__proto__: null,
|
|
1821
|
-
|
|
1822
|
-
getHTMLElementAttribute: getHTMLElementAttribute,
|
|
1823
|
-
htmlToText: htmlToText,
|
|
1824
|
-
isCommentNode: isCommentNode,
|
|
1825
|
-
isHTMLElement: isHTMLElement,
|
|
1826
|
-
isTextCE: isTextCE,
|
|
1827
|
-
isTextNode: isTextNode,
|
|
1828
|
-
nodeTagIn: nodeTagIn,
|
|
1829
|
-
nodeTagIs: nodeTagIs
|
|
1994
|
+
reference: reference
|
|
1830
1995
|
});
|
|
1831
1996
|
|
|
1997
|
+
const generateArcId = (identifier, orgHostname) => {
|
|
1998
|
+
const namespace = v5(orgHostname, v5.DNS);
|
|
1999
|
+
const buffer = v5(identifier, namespace, Buffer.alloc(16));
|
|
2000
|
+
return encode(buffer, 'RFC4648', { padding: false });
|
|
2001
|
+
};
|
|
1832
2002
|
/**
|
|
1833
|
-
*
|
|
1834
|
-
* It provides a flexible way to handle different HTML nodes and wrap text content.
|
|
1835
|
-
*
|
|
1836
|
-
* The processor can be extended with custom handlers for specific node types and
|
|
1837
|
-
* wrappers for text content.
|
|
2003
|
+
* Utility class for generating Arc IDs and source IDs
|
|
1838
2004
|
*
|
|
1839
2005
|
* @example
|
|
1840
2006
|
* ```ts
|
|
1841
|
-
*
|
|
1842
|
-
* const
|
|
1843
|
-
*
|
|
1844
|
-
*
|
|
1845
|
-
* // Parse HTML content
|
|
1846
|
-
* const html = '<div><p>Some text</p><img src="image.jpg"></div>';
|
|
1847
|
-
* const elements = await processor.parse(html);
|
|
2007
|
+
* const generator = new IdGenerator(['my-org']);
|
|
2008
|
+
* const arcId = generator.getArcId('123'); // Generates a unique for 'my-org' Arc ID
|
|
2009
|
+
* const sourceId = generator.getSourceId('123', ['my-site']); // Generates 'my-site-123'
|
|
1848
2010
|
* ```
|
|
1849
|
-
*
|
|
1850
|
-
* The processor comes with built-in handlers for common HTML elements like links,
|
|
1851
|
-
* text formatting (i, u, strong), and block elements. Custom handlers can be added
|
|
1852
|
-
* using the `handle()` and `wrap()` methods.
|
|
1853
2011
|
*/
|
|
1854
|
-
class
|
|
1855
|
-
constructor() {
|
|
1856
|
-
|
|
1857
|
-
|
|
1858
|
-
node: new Map(),
|
|
1859
|
-
wrap: new Map(),
|
|
1860
|
-
};
|
|
1861
|
-
}
|
|
1862
|
-
init() {
|
|
1863
|
-
// wrappers are used to wrap the content of nested text nodes
|
|
1864
|
-
// in a specific way
|
|
1865
|
-
this.wrap('link', (node, text) => {
|
|
1866
|
-
if (nodeTagIn(node, ['a'])) {
|
|
1867
|
-
const attributes = ['href', 'target', 'rel']
|
|
1868
|
-
.map((attr) => [attr, getHTMLElementAttribute(node, attr)])
|
|
1869
|
-
.filter(([_, value]) => value)
|
|
1870
|
-
.map(([key, value]) => `${key}="${value}"`)
|
|
1871
|
-
.join(' ');
|
|
1872
|
-
return {
|
|
1873
|
-
...text,
|
|
1874
|
-
content: `<a ${attributes}>${text.content}</a>`,
|
|
1875
|
-
};
|
|
1876
|
-
}
|
|
1877
|
-
});
|
|
1878
|
-
this.wrap('i', (node, text) => {
|
|
1879
|
-
if (nodeTagIn(node, ['i'])) {
|
|
1880
|
-
return {
|
|
1881
|
-
...text,
|
|
1882
|
-
content: `<i>${text.content}</i>`,
|
|
1883
|
-
};
|
|
1884
|
-
}
|
|
1885
|
-
});
|
|
1886
|
-
this.wrap('u', (node, text) => {
|
|
1887
|
-
if (nodeTagIn(node, ['u'])) {
|
|
1888
|
-
return {
|
|
1889
|
-
...text,
|
|
1890
|
-
content: `<u>${text.content}</u>`,
|
|
1891
|
-
};
|
|
1892
|
-
}
|
|
1893
|
-
});
|
|
1894
|
-
this.wrap('sup/sub', (node, text) => {
|
|
1895
|
-
if (nodeTagIn(node, ['sup', 'sub'])) {
|
|
1896
|
-
return {
|
|
1897
|
-
...text,
|
|
1898
|
-
content: `<mark class="${node.tagName.toLowerCase()}">${text.content}</mark>`,
|
|
1899
|
-
};
|
|
1900
|
-
}
|
|
1901
|
-
});
|
|
1902
|
-
this.wrap('strong', (node, text) => {
|
|
1903
|
-
if (nodeTagIn(node, ['strong', 'b'])) {
|
|
1904
|
-
return {
|
|
1905
|
-
...text,
|
|
1906
|
-
content: `<b>${text.content}</b>`,
|
|
1907
|
-
};
|
|
1908
|
-
}
|
|
1909
|
-
});
|
|
1910
|
-
this.wrap('center', (node, text) => {
|
|
1911
|
-
if (nodeTagIn(node, ['center'])) {
|
|
1912
|
-
return {
|
|
1913
|
-
...text,
|
|
1914
|
-
alignment: 'center',
|
|
1915
|
-
};
|
|
1916
|
-
}
|
|
1917
|
-
});
|
|
1918
|
-
this.wrap('aligned-paragraph', (node, text) => {
|
|
1919
|
-
if (nodeTagIn(node, ['p'])) {
|
|
1920
|
-
const styleAttribute = getHTMLElementAttribute(node, 'style') || '';
|
|
1921
|
-
if (!styleAttribute)
|
|
1922
|
-
return text;
|
|
1923
|
-
if (styleAttribute.includes('text-align: right;')) {
|
|
1924
|
-
return {
|
|
1925
|
-
...text,
|
|
1926
|
-
alignment: 'right',
|
|
1927
|
-
};
|
|
1928
|
-
}
|
|
1929
|
-
if (styleAttribute.includes('text-align: left;')) {
|
|
1930
|
-
return {
|
|
1931
|
-
...text,
|
|
1932
|
-
alignment: 'left',
|
|
1933
|
-
};
|
|
1934
|
-
}
|
|
1935
|
-
if (styleAttribute.includes('text-align: center;')) {
|
|
1936
|
-
return {
|
|
1937
|
-
...text,
|
|
1938
|
-
alignment: 'center',
|
|
1939
|
-
};
|
|
1940
|
-
}
|
|
1941
|
-
return text;
|
|
1942
|
-
}
|
|
1943
|
-
});
|
|
1944
|
-
// handlers are used to handle specific nodes
|
|
1945
|
-
// and return a list of content elements
|
|
1946
|
-
this.handle('default', (node) => {
|
|
1947
|
-
const noTag = isHTMLElement(node) && !node.tagName;
|
|
1948
|
-
if (noTag ||
|
|
1949
|
-
nodeTagIn(node, [
|
|
1950
|
-
'p',
|
|
1951
|
-
'a',
|
|
1952
|
-
'b',
|
|
1953
|
-
'sup',
|
|
1954
|
-
'sub',
|
|
1955
|
-
'span',
|
|
1956
|
-
'strong',
|
|
1957
|
-
'em',
|
|
1958
|
-
'i',
|
|
1959
|
-
'u',
|
|
1960
|
-
'section',
|
|
1961
|
-
'main',
|
|
1962
|
-
'div',
|
|
1963
|
-
'li',
|
|
1964
|
-
'center',
|
|
1965
|
-
])) {
|
|
1966
|
-
return this.handleNested(node);
|
|
1967
|
-
}
|
|
1968
|
-
});
|
|
1969
|
-
this.handle('headers', (node) => {
|
|
1970
|
-
if (nodeTagIn(node, ['h1', 'h2', 'h3', 'h4', 'h5', 'h6'])) {
|
|
1971
|
-
return this.createHeader(node);
|
|
1972
|
-
}
|
|
1973
|
-
});
|
|
1974
|
-
this.handle('text', (node) => {
|
|
1975
|
-
if (isTextNode(node)) {
|
|
1976
|
-
return this.createText(node);
|
|
1977
|
-
}
|
|
1978
|
-
});
|
|
1979
|
-
this.handle('comment', (node) => {
|
|
1980
|
-
if (isCommentNode(node)) {
|
|
1981
|
-
return this.handleComment(node);
|
|
1982
|
-
}
|
|
1983
|
-
});
|
|
1984
|
-
this.handle('list', async (node) => {
|
|
1985
|
-
if (nodeTagIn(node, ['ul', 'ol'])) {
|
|
1986
|
-
const listType = node.tagName === 'UL' ? 'unordered' : 'ordered';
|
|
1987
|
-
return this.createList(node, listType);
|
|
1988
|
-
}
|
|
1989
|
-
});
|
|
1990
|
-
this.handle('table', (node) => {
|
|
1991
|
-
if (nodeTagIs(node, 'table')) {
|
|
1992
|
-
return this.handleTable(node);
|
|
1993
|
-
}
|
|
1994
|
-
});
|
|
1995
|
-
this.handle('iframe', (node) => {
|
|
1996
|
-
if (nodeTagIs(node, 'iframe')) {
|
|
1997
|
-
return this.handleIframe(node);
|
|
1998
|
-
}
|
|
1999
|
-
});
|
|
2000
|
-
this.handle('img', (node) => {
|
|
2001
|
-
if (nodeTagIs(node, 'img')) {
|
|
2002
|
-
return this.handleImage(node);
|
|
2003
|
-
}
|
|
2004
|
-
});
|
|
2005
|
-
this.handle('br', (node) => {
|
|
2006
|
-
if (nodeTagIs(node, 'br')) {
|
|
2007
|
-
return this.handleBreak(node);
|
|
2008
|
-
}
|
|
2009
|
-
});
|
|
2010
|
-
}
|
|
2011
|
-
handle(name, handler) {
|
|
2012
|
-
if (this.handlers.node.has(name)) {
|
|
2013
|
-
this.warn({ name }, `${name} node handler already set`);
|
|
2012
|
+
class IdGenerator {
|
|
2013
|
+
constructor(namespaces) {
|
|
2014
|
+
if (!namespaces.length) {
|
|
2015
|
+
throw new Error('At least 1 namespace is required');
|
|
2014
2016
|
}
|
|
2015
|
-
this.
|
|
2017
|
+
this.namespace = namespaces.join('-');
|
|
2016
2018
|
}
|
|
2017
|
-
|
|
2018
|
-
|
|
2019
|
-
this.warn({ name }, `${name} wrap handler already set`);
|
|
2020
|
-
}
|
|
2021
|
-
this.handlers.wrap.set(name, handler);
|
|
2019
|
+
getArcId(id) {
|
|
2020
|
+
return generateArcId(id.toString(), this.namespace);
|
|
2022
2021
|
}
|
|
2023
|
-
|
|
2024
|
-
|
|
2025
|
-
doc.removeWhitespace();
|
|
2026
|
-
const elements = await this.process(doc);
|
|
2027
|
-
const filtered = elements?.filter((e) => e.type !== 'divider');
|
|
2028
|
-
return filtered || [];
|
|
2022
|
+
getSourceId(id, prefixes = []) {
|
|
2023
|
+
return [...prefixes, id].join('-');
|
|
2029
2024
|
}
|
|
2030
|
-
|
|
2031
|
-
|
|
2032
|
-
|
|
2033
|
-
|
|
2034
|
-
|
|
2035
|
-
|
|
2025
|
+
}
|
|
2026
|
+
|
|
2027
|
+
var Id = /*#__PURE__*/Object.freeze({
|
|
2028
|
+
__proto__: null,
|
|
2029
|
+
IdGenerator: IdGenerator,
|
|
2030
|
+
generateArcId: generateArcId
|
|
2031
|
+
});
|
|
2032
|
+
|
|
2033
|
+
const buildTree = (items) => {
|
|
2034
|
+
const tree = [
|
|
2035
|
+
{
|
|
2036
|
+
id: '/',
|
|
2037
|
+
children: [],
|
|
2038
|
+
meta: new Proxy({}, {
|
|
2039
|
+
get: () => {
|
|
2040
|
+
throw new Error('Root node meta is not accessible');
|
|
2041
|
+
},
|
|
2042
|
+
}),
|
|
2043
|
+
parent: null,
|
|
2044
|
+
},
|
|
2045
|
+
];
|
|
2046
|
+
// Track nodes at each level to maintain parent-child relationships
|
|
2047
|
+
// stores last node at each level
|
|
2048
|
+
const currLevelNodes = {
|
|
2049
|
+
0: tree[0],
|
|
2050
|
+
};
|
|
2051
|
+
for (const item of items) {
|
|
2052
|
+
const node = {
|
|
2053
|
+
id: item.id,
|
|
2054
|
+
parent: null,
|
|
2055
|
+
children: [],
|
|
2056
|
+
meta: item,
|
|
2036
2057
|
};
|
|
2037
|
-
|
|
2038
|
-
|
|
2039
|
-
|
|
2040
|
-
|
|
2041
|
-
|
|
2042
|
-
* wrappers to text elements.
|
|
2043
|
-
*
|
|
2044
|
-
* @param node - The HTML node containing the text elements
|
|
2045
|
-
**/
|
|
2046
|
-
wrapChildrenTextNodes(node, elements) {
|
|
2047
|
-
const wrapped = [];
|
|
2048
|
-
const wrappers = [...this.handlers.wrap.values()];
|
|
2049
|
-
for (const c of elements) {
|
|
2050
|
-
if (!isTextCE(c)) {
|
|
2051
|
-
wrapped.push(c);
|
|
2052
|
-
continue;
|
|
2053
|
-
}
|
|
2054
|
-
this.addTextAdditionalProperties(c, node);
|
|
2055
|
-
const handled = wrappers.map((wrapper) => wrapper(node, c)).find(Boolean);
|
|
2056
|
-
wrapped.push(handled || c);
|
|
2058
|
+
// Determine the level of this node
|
|
2059
|
+
const levelKey = Object.keys(item).find((key) => key.startsWith('N') && item[key]);
|
|
2060
|
+
const level = Number(levelKey?.replace('N', '')) || 0;
|
|
2061
|
+
if (!level) {
|
|
2062
|
+
throw new Error(`Invalid level for section ${item.id}`);
|
|
2057
2063
|
}
|
|
2058
|
-
|
|
2064
|
+
// This is a child node - attach to its parent
|
|
2065
|
+
const parentLevel = level - 1;
|
|
2066
|
+
const parentNode = currLevelNodes[parentLevel];
|
|
2067
|
+
if (parentNode) {
|
|
2068
|
+
node.parent = parentNode;
|
|
2069
|
+
parentNode.children.push(node);
|
|
2070
|
+
}
|
|
2071
|
+
else {
|
|
2072
|
+
throw new Error(`Parent node not found for section ${item.id}`);
|
|
2073
|
+
}
|
|
2074
|
+
// Set this as the current node for its level
|
|
2075
|
+
currLevelNodes[level] = node;
|
|
2059
2076
|
}
|
|
2060
|
-
|
|
2061
|
-
|
|
2062
|
-
|
|
2063
|
-
|
|
2064
|
-
|
|
2065
|
-
|
|
2066
|
-
|
|
2067
|
-
|
|
2068
|
-
|
|
2069
|
-
|
|
2070
|
-
|
|
2071
|
-
|
|
2072
|
-
|
|
2077
|
+
// return root nodes children
|
|
2078
|
+
return tree[0].children;
|
|
2079
|
+
};
|
|
2080
|
+
const flattenTree = (tree) => {
|
|
2081
|
+
const flatten = [];
|
|
2082
|
+
const traverse = (node) => {
|
|
2083
|
+
flatten.push(node);
|
|
2084
|
+
for (const child of node.children) {
|
|
2085
|
+
traverse(child);
|
|
2086
|
+
}
|
|
2087
|
+
};
|
|
2088
|
+
// traverse all root nodes and their children
|
|
2089
|
+
for (const node of tree) {
|
|
2090
|
+
traverse(node);
|
|
2073
2091
|
}
|
|
2074
|
-
|
|
2075
|
-
|
|
2076
|
-
|
|
2092
|
+
return flatten;
|
|
2093
|
+
};
|
|
2094
|
+
const buildAndFlattenTree = (items) => flattenTree(buildTree(items));
|
|
2095
|
+
const groupByWebsites = (sections) => {
|
|
2096
|
+
return sections.reduce((acc, section) => {
|
|
2097
|
+
const website = section._website;
|
|
2098
|
+
if (!acc[website])
|
|
2099
|
+
acc[website] = [];
|
|
2100
|
+
acc[website].push(section);
|
|
2101
|
+
return acc;
|
|
2102
|
+
}, {});
|
|
2103
|
+
};
|
|
2104
|
+
const references = (sections) => {
|
|
2105
|
+
return sections.map((s) => reference({
|
|
2106
|
+
id: s._id,
|
|
2107
|
+
website: s._website,
|
|
2108
|
+
type: 'section',
|
|
2109
|
+
}));
|
|
2110
|
+
};
|
|
2111
|
+
const isReference = (section) => {
|
|
2112
|
+
return section?.type === 'reference' && section?.referent?.type === 'section';
|
|
2113
|
+
};
|
|
2114
|
+
const removeDuplicates = (sections) => {
|
|
2115
|
+
const map = new Map();
|
|
2116
|
+
sections.forEach((s) => {
|
|
2117
|
+
if (isReference(s)) {
|
|
2118
|
+
map.set(`${s.referent.id}${s.referent.website}`, s);
|
|
2077
2119
|
}
|
|
2078
|
-
|
|
2079
|
-
|
|
2080
|
-
children.push(await this.process(child));
|
|
2120
|
+
else {
|
|
2121
|
+
map.set(`${s._id}${s._website}`, s);
|
|
2081
2122
|
}
|
|
2082
|
-
|
|
2123
|
+
});
|
|
2124
|
+
return [...map.values()];
|
|
2125
|
+
};
|
|
2126
|
+
class SectionsRepository {
|
|
2127
|
+
constructor(arc) {
|
|
2128
|
+
this.arc = arc;
|
|
2129
|
+
this.sectionsByWebsite = {};
|
|
2130
|
+
this.websitesAreLoaded = false;
|
|
2083
2131
|
}
|
|
2084
|
-
|
|
2085
|
-
|
|
2086
|
-
|
|
2087
|
-
|
|
2088
|
-
*
|
|
2089
|
-
* @param node - The HTML node to process
|
|
2090
|
-
* @returns Promise resolving to an array of content elements, or undefined if node cannot be processed
|
|
2091
|
-
*/
|
|
2092
|
-
async process(node) {
|
|
2093
|
-
let isKnownNode = false;
|
|
2094
|
-
const elements = [];
|
|
2095
|
-
for (const [name, handler] of this.handlers.node.entries()) {
|
|
2096
|
-
try {
|
|
2097
|
-
const result = await handler(node);
|
|
2098
|
-
if (result) {
|
|
2099
|
-
// if handler returns an array of elements, it means that the node was handled properly, even if there is no elements inside
|
|
2100
|
-
isKnownNode = true;
|
|
2101
|
-
elements.push(...result);
|
|
2102
|
-
break;
|
|
2103
|
-
}
|
|
2104
|
-
}
|
|
2105
|
-
catch (error) {
|
|
2106
|
-
this.warn({ node: node.toString(), error: error.toString(), name }, 'HandlerError');
|
|
2107
|
-
}
|
|
2108
|
-
}
|
|
2109
|
-
if (isKnownNode)
|
|
2110
|
-
return elements;
|
|
2111
|
-
this.warn({ node: node.toString() }, 'UnknownNodeError');
|
|
2132
|
+
async put(ans) {
|
|
2133
|
+
await this.arc.Site.putSection(ans);
|
|
2134
|
+
const created = await this.arc.Site.getSection(ans._id, ans.website);
|
|
2135
|
+
this.save(created);
|
|
2112
2136
|
}
|
|
2113
|
-
|
|
2114
|
-
|
|
2115
|
-
|
|
2116
|
-
|
|
2117
|
-
|
|
2118
|
-
|
|
2119
|
-
|
|
2120
|
-
|
|
2121
|
-
|
|
2122
|
-
|
|
2123
|
-
|
|
2124
|
-
if (!toMerge.length)
|
|
2125
|
-
return;
|
|
2126
|
-
const paragraph = toMerge.reduce((acc, p) => {
|
|
2127
|
-
return {
|
|
2128
|
-
...p,
|
|
2129
|
-
content: acc.content + p.content,
|
|
2130
|
-
};
|
|
2131
|
-
}, { type: 'text', content: '' });
|
|
2132
|
-
merged.push(paragraph);
|
|
2133
|
-
toMerge = [];
|
|
2134
|
-
};
|
|
2135
|
-
for (let i = 0; i < items.length; i++) {
|
|
2136
|
-
const item = items[i];
|
|
2137
|
-
const isBlockElement = item.additional_properties?.isBlockElement;
|
|
2138
|
-
if (isTextCE(item) && !isBlockElement) {
|
|
2139
|
-
toMerge.push(item);
|
|
2137
|
+
async loadWebsite(website) {
|
|
2138
|
+
const sections = [];
|
|
2139
|
+
let next = true;
|
|
2140
|
+
let offset = 0;
|
|
2141
|
+
while (next) {
|
|
2142
|
+
const migrated = await this.arc.Site.getSections({ website, offset }).catch((_) => {
|
|
2143
|
+
return { q_results: [] };
|
|
2144
|
+
});
|
|
2145
|
+
if (migrated.q_results.length) {
|
|
2146
|
+
sections.push(...migrated.q_results);
|
|
2147
|
+
offset += migrated.q_results.length;
|
|
2140
2148
|
}
|
|
2141
2149
|
else {
|
|
2142
|
-
|
|
2143
|
-
merged.push(item);
|
|
2150
|
+
next = false;
|
|
2144
2151
|
}
|
|
2145
2152
|
}
|
|
2146
|
-
|
|
2147
|
-
return merged;
|
|
2148
|
-
}
|
|
2149
|
-
handleComment(_) {
|
|
2150
|
-
return [];
|
|
2151
|
-
}
|
|
2152
|
-
async handleTable(node) {
|
|
2153
|
-
return [ContentElement.raw_html(node.toString())];
|
|
2154
|
-
}
|
|
2155
|
-
async handleIframe(node) {
|
|
2156
|
-
return [ContentElement.raw_html(node.toString())];
|
|
2157
|
-
}
|
|
2158
|
-
async handleImage(node) {
|
|
2159
|
-
return [ContentElement.raw_html(node.toString())];
|
|
2160
|
-
}
|
|
2161
|
-
async handleBreak(_) {
|
|
2162
|
-
return [ContentElement.divider()];
|
|
2163
|
-
}
|
|
2164
|
-
async createQuote(node) {
|
|
2165
|
-
const items = await this.handleNested(node);
|
|
2166
|
-
return [ContentElement.quote(items)];
|
|
2153
|
+
return sections;
|
|
2167
2154
|
}
|
|
2168
|
-
async
|
|
2169
|
-
const
|
|
2170
|
-
|
|
2155
|
+
async loadWebsites(websites) {
|
|
2156
|
+
for (const website of websites) {
|
|
2157
|
+
this.sectionsByWebsite[website] = await this.loadWebsite(website);
|
|
2158
|
+
}
|
|
2159
|
+
this.websitesAreLoaded = true;
|
|
2171
2160
|
}
|
|
2172
|
-
|
|
2173
|
-
|
|
2161
|
+
save(section) {
|
|
2162
|
+
const website = section._website;
|
|
2163
|
+
assert.ok(website, 'Section must have a website');
|
|
2164
|
+
this.sectionsByWebsite[website] = this.sectionsByWebsite[website] || [];
|
|
2165
|
+
if (!this.sectionsByWebsite[website].find((s) => s._id === section._id)) {
|
|
2166
|
+
this.sectionsByWebsite[website].push(section);
|
|
2167
|
+
}
|
|
2174
2168
|
}
|
|
2175
|
-
|
|
2176
|
-
|
|
2177
|
-
|
|
2169
|
+
getById(id, website) {
|
|
2170
|
+
this.ensureWebsitesLoaded();
|
|
2171
|
+
const section = this.sectionsByWebsite[website]?.find((s) => s._id === id);
|
|
2172
|
+
return section;
|
|
2178
2173
|
}
|
|
2179
|
-
|
|
2180
|
-
|
|
2181
|
-
return [
|
|
2174
|
+
getByWebsite(website) {
|
|
2175
|
+
this.ensureWebsitesLoaded();
|
|
2176
|
+
return this.sectionsByWebsite[website];
|
|
2182
2177
|
}
|
|
2183
|
-
|
|
2184
|
-
|
|
2185
|
-
|
|
2186
|
-
|
|
2187
|
-
|
|
2178
|
+
getParentSections(section) {
|
|
2179
|
+
this.ensureWebsitesLoaded();
|
|
2180
|
+
const parents = [];
|
|
2181
|
+
let current = section;
|
|
2182
|
+
while (current.parent?.default && current.parent.default !== '/') {
|
|
2183
|
+
const parent = this.getById(current.parent.default, section._website);
|
|
2184
|
+
if (!parent)
|
|
2185
|
+
break;
|
|
2186
|
+
parents.push(parent);
|
|
2187
|
+
current = parent;
|
|
2188
|
+
}
|
|
2189
|
+
return parents;
|
|
2188
2190
|
}
|
|
2189
|
-
|
|
2190
|
-
|
|
2191
|
+
ensureWebsitesLoaded() {
|
|
2192
|
+
assert.ok(this.websitesAreLoaded, 'call .loadWebsites() first');
|
|
2191
2193
|
}
|
|
2192
2194
|
}
|
|
2193
2195
|
|
|
2194
|
-
var
|
|
2196
|
+
var Section = /*#__PURE__*/Object.freeze({
|
|
2195
2197
|
__proto__: null,
|
|
2196
|
-
|
|
2197
|
-
|
|
2198
|
-
|
|
2198
|
+
SectionsRepository: SectionsRepository,
|
|
2199
|
+
buildAndFlattenTree: buildAndFlattenTree,
|
|
2200
|
+
buildTree: buildTree,
|
|
2201
|
+
flattenTree: flattenTree,
|
|
2202
|
+
groupByWebsites: groupByWebsites,
|
|
2203
|
+
isReference: isReference,
|
|
2204
|
+
references: references,
|
|
2205
|
+
removeDuplicates: removeDuplicates
|
|
2199
2206
|
});
|
|
2200
2207
|
|
|
2201
|
-
|
|
2202
|
-
|
|
2203
|
-
|
|
2204
|
-
|
|
2205
|
-
|
|
2208
|
+
const ArcUtils = {
|
|
2209
|
+
Id,
|
|
2210
|
+
ANS,
|
|
2211
|
+
ContentElements,
|
|
2212
|
+
Section,
|
|
2213
|
+
};
|
|
2206
2214
|
|
|
2207
|
-
export { index$
|
|
2215
|
+
export { index$1 as AnsMapper, ArcAPI, ArcError, index as ArcTypes, ArcUtils, index$2 as ContentElements, WsClient, ArcAPI as default };
|
|
2208
2216
|
//# sourceMappingURL=index.js.map
|