@tricoteuses/tisseuse 0.13.9 → 0.13.11

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/README.md CHANGED
@@ -96,6 +96,17 @@ npm run index:postgres:assemblee -- --all
96
96
 
97
97
  La première commande consomme la file des documents à acquérir, simplifier et enrichir. La seconde indexe dans `tisseuse.assemblee_text_search` les articles et les exposés des motifs comme résultats distincts. Les déclencheurs sur `assemblee.documents`, le hash du contenu et les files PostgreSQL permettent les mises à jour ciblées ; les options `--all` demandent une réconciliation complète.
98
98
 
99
+ Pour acquérir et indexer immédiatement quelques documents indépendamment de leur position dans les files durables :
100
+
101
+ ```sh
102
+ npm run sync:postgres:assemblee-content -- \
103
+ --document-uids PRJLANR5L17BTC2765,PRJLANR5L17BTC3067
104
+ npm run index:postgres:assemblee -- \
105
+ --document-uids PRJLANR5L17BTC2765,PRJLANR5L17BTC3067
106
+ ```
107
+
108
+ Le mode ciblé refuse les UID absents de `assemblee.documents` et ne peut pas être combiné avec `--all`.
109
+
99
110
  Exploratrice et Moulineuse ne téléchargent jamais un document pendant une lecture. Lorsqu’un document source existe mais que son contenu n’est pas encore disponible, son état est conservé en base et l’interface doit l’indiquer au lieu de servir une copie locale périmée.
100
111
 
101
112
  ### Première itération de recherche plein texte Sénat
package/dist/server.js CHANGED
@@ -247,7 +247,7 @@ function ge(e, t) {
247
247
  }
248
248
  function P(e) {
249
249
  let t = [], n = /* @__PURE__ */ new Set(), r = /* @__PURE__ */ new Set();
250
- return e("a[id], span[id], h1[id], h2[id], h3[id], h4[id], h5[id], h6[id]").each((i, a) => {
250
+ e("a[id], span[id], h1[id], h2[id], h3[id], h4[id], h5[id], h6[id]").each((i, a) => {
251
251
  let o = M(E(e(a).text()));
252
252
  if (!o) return;
253
253
  let s = e(a).attr("id");
@@ -259,7 +259,20 @@ function P(e) {
259
259
  element: a,
260
260
  container: c
261
261
  }));
262
- }), t;
262
+ }), e("h1:not([id]), h2:not([id]), h3:not([id]), h4:not([id]), h5:not([id]), h6:not([id])").each((i, a) => {
263
+ if (n.has(a)) return;
264
+ let o = M(E(e(a).text()));
265
+ if (!o) return;
266
+ let s = `_TocArt${(o.num ?? o.label.replace(/^Article\s+/iu, "")).replace(/\s+/gu, "")}`;
267
+ r.has(s) || (r.add(s), n.add(a), t.push({
268
+ id: s,
269
+ ...o,
270
+ element: a,
271
+ container: a
272
+ }));
273
+ });
274
+ let i = e("body *");
275
+ return t.sort((e, t) => i.index(e.container) - i.index(t.container)), t;
263
276
  }
264
277
  function F(e) {
265
278
  let t = e.next;
@@ -269,7 +282,7 @@ function F(e) {
269
282
  }
270
283
  return null;
271
284
  }
272
- function _e(e, t, n) {
285
+ function I(e, t, n) {
273
286
  let r = [t.container], i = n?.container;
274
287
  for (let e = F(t.container); e !== null && e !== i; e = F(e)) r.push(e);
275
288
  if (r.length > 1) return r;
@@ -279,7 +292,7 @@ function _e(e, t, n) {
279
292
  return n >= a && (o === -1 || n < o);
280
293
  });
281
294
  }
282
- function ve(e, t) {
295
+ function _e(e, t) {
283
296
  let n = [], r = /* @__PURE__ */ new Set();
284
297
  for (let i of t) {
285
298
  let t = "p,li,table", a = e(i).is(t) ? [i] : e(i).find(t).get();
@@ -287,9 +300,9 @@ function ve(e, t) {
287
300
  }
288
301
  return n;
289
302
  }
290
- function I(e, t, n) {
303
+ function L(e, t, n) {
291
304
  let r = [], i = !1;
292
- for (let a of ve(e, n)) {
305
+ for (let a of _e(e, n)) {
293
306
  let n = E(e(a).text());
294
307
  if (!n) continue;
295
308
  T.test(n) && (i = !0);
@@ -305,52 +318,64 @@ function I(e, t, n) {
305
318
  }
306
319
  return r;
307
320
  }
308
- function L(e, t) {
321
+ function R(e, t) {
309
322
  if (t.length === 0) return e;
310
323
  let n = `<div style="display: none;">\n${t.map((e) => `<p class="assnatTOC6"><a href="#${`_TocArt${(e.num ?? e.label.replace(/^Article\s+/iu, "")).replace(/\s+/gu, "")}`}"><span class="assnatHyperlink" style="font-weight:bold; text-decoration:none; color:#000000">${e.label.toUpperCase()}</span></a></p>`).join("\n")}\n</div>`;
311
324
  return e.includes("class=\"assnatSection3\"") ? e.replace(/(<div class="assnatSection3">)/u, `${n}$1`) : e.includes("id=\"formCorrection:panel:1:table\"") ? e.replace(/(<div id="formCorrection:panel:1:table">)/u, `${n}$1`) : `${n}\n${e}`;
312
325
  }
313
- function ye(t) {
326
+ function ve(t) {
314
327
  let n = e(t);
315
328
  for (let e of P(n)) {
316
329
  let t = `_TocArt${(e.num ?? e.label.replace(/^Article\s+/iu, "")).replace(/\s+/gu, "")}`, r = n(e.element), i = r.attr("id");
317
- i?.startsWith("_TocArt") || (i?.startsWith("_Toc") && !be(n, i, e.element) && r.before(n("<span></span>").attr("id", i)), r.attr("id", t));
330
+ i?.startsWith("_TocArt") || (i?.startsWith("_Toc") && !z(n, i, e.element) && r.before(n("<span></span>").attr("id", i)), r.attr("id", t));
331
+ }
332
+ let r = P(n);
333
+ for (let [e, t] of r.entries()) {
334
+ let i = I(n, t, r[e + 1]).flatMap((e) => n(e).is("span.alinea[data-alinea]") ? [e] : n(e).find("span.alinea[data-alinea]").get());
335
+ for (let e of i) {
336
+ let r = n(e).attr("data-alinea")?.trim();
337
+ if (!r) continue;
338
+ let i = `${t.id}-alinea-${r.replace(/\s+/gu, "")}`;
339
+ if (z(n, i, e)) continue;
340
+ let a = n(e).attr("id");
341
+ a && a !== i ? n(e).before(n("<span></span>").attr("id", i)) : n(e).attr("id", i);
342
+ }
318
343
  }
319
344
  return n.html();
320
345
  }
321
- function be(e, t, n) {
346
+ function z(e, t, n) {
322
347
  for (let r of e("[id]").get()) if (r !== n && e(r).attr("id") === t) return !0;
323
348
  return !1;
324
349
  }
325
- function xe(e, t) {
350
+ function ye(e, t) {
326
351
  let n = ue("sourceText" in t ? t.sourceText : "");
327
352
  if (n) return e.filter((e) => e.kind === "directive_candidate").find((e) => {
328
353
  let t = ue(e.text);
329
354
  return t.length > 0 && (n.includes(t) || t.includes(n));
330
355
  });
331
356
  }
332
- function Se(e, t) {
357
+ function be(e, t) {
333
358
  if (t) return t.blockIds.map((t) => e.get(t)).find((e) => e?.kind === "directive_candidate");
334
359
  }
335
- function R(e) {
360
+ function xe(e) {
336
361
  return e?.links.filter((e) => !e.insideFrenchQuotes && (e.type === "article" || e.type === "division")).map((e) => e.id) ?? [];
337
362
  }
338
- var Ce = [
363
+ var Se = [
339
364
  /^([IVXLCDM]+)\s*[.).]?\s*[–—-]/iu,
340
365
  /^(\d+°)\s+/u,
341
366
  /^([a-z])\)\s+/iu,
342
367
  /^([ivxlcdm]+)\)\s+/iu
343
368
  ];
344
- function we(e) {
369
+ function Ce(e) {
345
370
  let t = E(e);
346
371
  if (!t) return;
347
- let n = Ce.findIndex((e) => e.test(t));
372
+ let n = Se.findIndex((e) => e.test(t));
348
373
  return n === -1 ? t.endsWith(":") ? 0 : void 0 : n + 1;
349
374
  }
350
- function Te(e) {
375
+ function we(e) {
351
376
  let t = /* @__PURE__ */ new Map(), n = [];
352
377
  for (let r of e) {
353
- let e = we(r.text);
378
+ let e = Ce(r.text);
354
379
  if (e === void 0) {
355
380
  t.set(r.id, [...n, r]);
356
381
  continue;
@@ -359,14 +384,14 @@ function Te(e) {
359
384
  }
360
385
  return t;
361
386
  }
362
- function Ee(e, t) {
387
+ function Te(e, t) {
363
388
  let n = [], r = /* @__PURE__ */ new Set();
364
389
  for (let i of [...e ?? [], ...t]) i !== void 0 && (r.has(i.id) || (r.add(i.id), n.push(i)));
365
390
  return n;
366
391
  }
367
- function De(e, t, n) {
392
+ function Ee(e, t, n) {
368
393
  if (!t) return;
369
- let r = Ee(e, t.blockIds.map((e) => n.get(e)).filter((e) => e !== void 0));
394
+ let r = Te(e, t.blockIds.map((e) => n.get(e)).filter((e) => e !== void 0));
370
395
  if (r.length === 0) return;
371
396
  let i = r.map((e) => e.id);
372
397
  if (i.length === t.blockIds.length && i.every((e, n) => e === t.blockIds[n])) return;
@@ -381,7 +406,7 @@ function De(e, t, n) {
381
406
  }
382
407
  };
383
408
  }
384
- function Oe(e) {
409
+ function De(e) {
385
410
  let t = [], n = 0;
386
411
  for (let r of e.blocks) {
387
412
  let i = e.directiveText.indexOf(r.text, n);
@@ -395,7 +420,7 @@ function Oe(e) {
395
420
  }
396
421
  return t;
397
422
  }
398
- function ke(e, t, n) {
423
+ function Oe(e, t, n) {
399
424
  let { start: r, stop: i } = n.sourcePosition, a = t.filter((e) => e.stop >= r && e.start <= i);
400
425
  if (a.length === 0) return;
401
426
  let o = a[0], s = a[a.length - 1], c = o.start, l = s.stop;
@@ -409,7 +434,7 @@ function ke(e, t, n) {
409
434
  }
410
435
  };
411
436
  }
412
- function Ae(e, t, n) {
437
+ function ke(e, t, n) {
413
438
  if (!t) return;
414
439
  let r = e.directiveText.indexOf(t.text);
415
440
  if (r === -1) return;
@@ -422,14 +447,14 @@ function Ae(e, t, n) {
422
447
  stop: a
423
448
  };
424
449
  }
425
- function je(e) {
426
- let t = Oe(e), n = new Map(e.blocks.map((e) => [e.id, e])), r = Te(e.blocks), a = /* @__PURE__ */ new Map(), o = [];
450
+ function Ae(e) {
451
+ let t = De(e), n = new Map(e.blocks.map((e) => [e.id, e])), r = we(e.blocks), a = /* @__PURE__ */ new Map(), o = [];
427
452
  for (let t of e.blocks) {
428
- let e = R(t);
453
+ let e = xe(t);
429
454
  e.length > 0 && (o = e), a.set(t.id, o);
430
455
  }
431
456
  return i(e.directiveText).map((i) => {
432
- let o = ke(e, t, i), s = Se(n, o) ?? xe(e.blocks, i), c = R(s), l = c.length > 0 ? c : s?.id === void 0 ? [] : a.get(s.id) ?? [], u = Ae(e, s, i), d = De(s?.id === void 0 ? void 0 : r.get(s.id), o, n);
457
+ let o = Oe(e, t, i), s = be(n, o) ?? ye(e.blocks, i), c = xe(s), l = c.length > 0 ? c : s?.id === void 0 ? [] : a.get(s.id) ?? [], u = ke(e, s, i), d = Ee(s?.id === void 0 ? void 0 : r.get(s.id), o, n);
433
458
  return {
434
459
  articleId: e.id,
435
460
  blockId: s?.id,
@@ -449,7 +474,7 @@ function je(e) {
449
474
  };
450
475
  });
451
476
  }
452
- function Me(e) {
477
+ function je(e) {
453
478
  let t = /* @__PURE__ */ new Map(), n = [], r = /* @__PURE__ */ new Set();
454
479
  for (let i of e) {
455
480
  let e = re(i.directive);
@@ -479,7 +504,7 @@ function Me(e) {
479
504
  definitions: n
480
505
  };
481
506
  }
482
- function Ne(e, t, n) {
507
+ function Me(e, t, n) {
483
508
  let r = new Map(t.map((e) => [O(e.num), e]));
484
509
  return e.map((e) => {
485
510
  let t = n.get(e), i = t?.[0], a = [...k(e.directive.reference)].map((e) => r.get(O(e))).filter((e) => e !== void 0 && e.definitionId !== i?.definitionId)[0], o = a === void 0 ? void 0 : {
@@ -498,7 +523,7 @@ function Ne(e, t, n) {
498
523
  };
499
524
  });
500
525
  }
501
- function z(e, t, n, i, a, o, s = !0) {
526
+ function Ne(e, t, n, i, a, o, s = !0) {
502
527
  let c = a.map((e) => e.directiveText).filter(Boolean).join("\n"), l = {
503
528
  sourceFormat: e,
504
529
  documentDate: i,
@@ -511,7 +536,7 @@ function z(e, t, n, i, a, o, s = !0) {
511
536
  ...l,
512
537
  directives: []
513
538
  };
514
- let u = le(a.map((e) => e.text).join("\n")), d = a.flatMap(je), { createdArticlesByDirective: f, definitions: p } = Me(d), m = Ne(d, p, f);
539
+ let u = le(a.map((e) => e.text).join("\n")), d = a.flatMap(Ae), { createdArticlesByDirective: f, definitions: p } = je(d), m = Me(d, p, f);
515
540
  return {
516
541
  ...l,
517
542
  ...u ? { globalApplicabilityDate: u } : {},
@@ -532,8 +557,8 @@ function Pe(e) {
532
557
  })) };
533
558
  }
534
559
  async function Fe(t, n) {
535
- let r = new u("parseAssembleeBillRaw"), i = n.linkedHtml === void 0 ? await r.time("linkAssembleeBillRaw", () => Ie(t, n)) : void 0, a = r.timeSync("applyArticleAnchorIds", () => ye(n.linkedHtml ?? i.linkedHtml), { inputSize: t.length }), o = r.timeSync("cheerioLoadLinkedHtml", () => e(a)), s = r.timeSync("extractArticleHeadings", () => P(o)), c = r.timeSync("extractArticlesAndBlocks", () => s.map((e, t) => {
536
- let n = _e(o, e, s[t + 1]), r = I(o, e.id, n), i = r.filter((e) => e.kind !== "noise").map((e) => e.text).join("\n");
560
+ let r = new u("parseAssembleeBillRaw"), i = n.linkedHtml === void 0 ? await r.time("linkAssembleeBillRaw", () => Ie(t, n)) : void 0, a = r.timeSync("applyArticleAnchorIds", () => ve(n.linkedHtml ?? i.linkedHtml), { inputSize: t.length }), o = r.timeSync("cheerioLoadLinkedHtml", () => e(a)), s = r.timeSync("extractArticleHeadings", () => P(o)), c = r.timeSync("extractArticlesAndBlocks", () => s.map((e, t) => {
561
+ let n = I(o, e, s[t + 1]), r = L(o, e.id, n), i = r.filter((e) => e.kind !== "noise").map((e) => e.text).join("\n");
537
562
  return {
538
563
  id: e.id,
539
564
  label: e.label,
@@ -544,7 +569,7 @@ async function Fe(t, n) {
544
569
  directiveText: i,
545
570
  blocks: r
546
571
  };
547
- }), { count: s.length }), l = r.timeSync("injectHiddenArticleSummary", () => L(o.html(), c)), d = r.timeSync("buildAssembleeTableOfContents", () => Pe(c), { count: c.length }), f = r.timeSync("buildParsedDocument", () => z("assemblee-html", t, l, n.date, c, d, n.includeDirectiveAnalysis));
572
+ }), { count: s.length }), l = r.timeSync("injectHiddenArticleSummary", () => R(o.html(), c)), d = r.timeSync("buildAssembleeTableOfContents", () => Pe(c), { count: c.length }), f = r.timeSync("buildParsedDocument", () => Ne("assemblee-html", t, l, n.date, c, d, n.includeDirectiveAnalysis));
548
573
  return r.log({
549
574
  articleCount: f.articles.length,
550
575
  blockCount: f.articles.reduce((e, t) => e + t.blocks.length, 0),
@@ -966,7 +991,7 @@ function gt(t) {
966
991
  function _t(e) {
967
992
  let t = [];
968
993
  return e("article.akn-article").each((n, r) => {
969
- let i = e(r).children("p.TCNumArticle").first().get(0), a = E(i ? e(i).text() : ""), o = M(a) ?? { label: a || `Article ${n + 1}` }, s = e(r).attr("id") ?? `akn-article-${String(n + 1).padStart(3, "0")}`, c = [r], l = I(e, s, c), u = l.filter((e) => e.kind !== "noise").map((e) => e.text).join("\n");
994
+ let i = e(r).children("p.TCNumArticle").first().get(0), a = E(i ? e(i).text() : ""), o = M(a) ?? { label: a || `Article ${n + 1}` }, s = e(r).attr("id") ?? `akn-article-${String(n + 1).padStart(3, "0")}`, c = [r], l = L(e, s, c), u = l.filter((e) => e.kind !== "noise").map((e) => e.text).join("\n");
970
995
  t.push({
971
996
  id: s,
972
997
  label: o.label,
@@ -995,7 +1020,7 @@ async function yt(t, n) {
995
1020
  } })), a = n.date ?? pt(i), o = r.timeSync("renderAknHtml", () => mt(i), { inputSize: t.length }), s = n.linkedHtml ?? await r.time("addLinksToRenderedAknHtml", () => N(o, {
996
1021
  ...n,
997
1022
  date: a
998
- }, a)), c = r.timeSync("extractRenderedAknArticles", () => gt(o)), l = r.timeSync("injectHiddenArticleSummary", () => L(s, c)), { articles: d, htmlWithLinks: f } = r.timeSync("extractLinkedAknArticlesAndTaggedHtml", () => vt(l)), p = d.length > 0 ? d : c, m = r.timeSync("extractAknTableOfContents", () => ft(i)), h = r.timeSync("buildParsedDocument", () => z("akoma-ntoso", o, d.length > 0 ? f : l, a, p, m));
1023
+ }, a)), c = r.timeSync("extractRenderedAknArticles", () => gt(o)), l = r.timeSync("injectHiddenArticleSummary", () => R(s, c)), { articles: d, htmlWithLinks: f } = r.timeSync("extractLinkedAknArticlesAndTaggedHtml", () => vt(l)), p = d.length > 0 ? d : c, m = r.timeSync("extractAknTableOfContents", () => ft(i)), h = r.timeSync("buildParsedDocument", () => Ne("akoma-ntoso", o, d.length > 0 ? f : l, a, p, m));
999
1024
  return r.log({
1000
1025
  articleCount: h.articles.length,
1001
1026
  blockCount: h.articles.reduce((e, t) => e + t.blocks.length, 0),
@@ -0,0 +1,8 @@
1
+ export declare function writeJsonAtomic(filePath: string, value: unknown, options?: {
2
+ encoding?: BufferEncoding;
3
+ spaces?: number;
4
+ stagingDirectory?: string;
5
+ }): Promise<void>;
6
+ export declare function replaceDirectoryAtomically(targetDirectory: string, build: (stagingDirectory: string) => Promise<void>, { stagingRoot, }?: {
7
+ stagingRoot?: string;
8
+ }): Promise<void>;
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,6 @@
1
+ export declare function commitAndPushDocumentCheckpoint({ branch, message, remote, repository, }: {
2
+ branch?: string;
3
+ message: string;
4
+ remote?: string;
5
+ repository: string;
6
+ }): number;
@@ -0,0 +1,3 @@
1
+ export declare const enrichedDocumentCompletionMarkerName = ".tricoteuses-complete";
2
+ export declare const legacyEnrichedDocumentRequiredOutputNames: string[];
3
+ export declare function enrichedDocumentIsComplete(directory: string): Promise<boolean>;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@tricoteuses/tisseuse",
3
3
  "description": "Find links in/to French legislative documents",
4
- "version": "0.13.9",
4
+ "version": "0.13.11",
5
5
  "keywords": [
6
6
  "Assemblée nationale",
7
7
  "France",