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