texlite 0.7.6 → 0.7.7

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.
@@ -1 +1 @@
1
- import{j as e}from"./index-DRShM2ob.js";const n=e("Maximize2",[["polyline",{points:"15 3 21 3 21 9",key:"mznyad"}],["polyline",{points:"9 21 3 21 3 15",key:"1avn1i"}],["line",{x1:"21",x2:"14",y1:"3",y2:"10",key:"ota7mn"}],["line",{x1:"3",x2:"10",y1:"21",y2:"14",key:"1atl0r"}]]);const a=e("Minus",[["path",{d:"M5 12h14",key:"1ays0h"}]]);export{a as M,n as a};
1
+ import{j as e}from"./index-zIjCeZFK.js";const n=e("Maximize2",[["polyline",{points:"15 3 21 3 21 9",key:"mznyad"}],["polyline",{points:"9 21 3 21 3 15",key:"1avn1i"}],["line",{x1:"21",x2:"14",y1:"3",y2:"10",key:"ota7mn"}],["line",{x1:"3",x2:"10",y1:"21",y2:"14",key:"1atl0r"}]]);const a=e("Minus",[["path",{d:"M5 12h14",key:"1ays0h"}]]);export{a as M,n as a};
@@ -1,4 +1,4 @@
1
- import{a as z}from"./index-DRShM2ob.js";import"./react-BoEjKzFZ.js";const R=/([A-Za-z][A-Za-z0-9_.:/-]*(?:\s+[A-Za-z][A-Za-z0-9_.:/-]*){0,7})\s*$/,C=new Set(["tabular","tabularx","tabulary","longtable","array","matrix","pmatrix","bmatrix","Bmatrix","vmatrix","Vmatrix"]),q=new Set(["math","displaymath","equation","equation*","align","align*","alignat","alignat*","gather","gather*","multline","multline*","flalign","flalign*","tikzpicture","axis","scope","pgfonlayer","pgfpicture","tabular","tabularx","tabulary","longtable","array","matrix","pmatrix","bmatrix","Bmatrix","vmatrix","Vmatrix","verbatim","Verbatim","lstlisting","minted","comment","algorithmic","alignat"]),w=new Set(["documentclass","usepackage","RequirePackage","includegraphics","tikzset","pgfplotsset","hypersetup","lstset","definecolor","colorlet","setlength","setcounter","draw","path","fill","filldraw","shade","node","addplot","color","textcolor","colorbox","pagecolor"]),E=new Set(["label","hypertarget","ref","pageref","autoref","nameref","hyperref","index","gls","Gls","glspl","Glspl","cite","citep","citet","citeauthor","citeyear","citenum","parencite","textcite","autocite","footcite"]),$=5,p=new Map,Z=12;let y=!1,x=null;class b extends Error{constructor(){super("A newer writing check replaced this request."),this.name="HarperLintSupersededError"}}function D(t){return t instanceof b}function m(t,n,e){e>n&&t.push({from:n,to:e})}function g(t,n,e,o){if(t[n]!==e)return null;let i=0;for(let r=n;r<t.length;r+=1){const s=t[r-1]==="\\"&&t[r-2]!=="\\";if(!s&&t[r]===e&&(i+=1),!s&&t[r]===o&&(i-=1,i===0))return{from:n,to:r+1,end:r+1}}return null}function u(t,n){let e=n;for(;e<t.length&&/[ \t\r\n]/.test(t[e]);)e+=1;return e}function O(t,n){if(t[n]!=="%")return!1;let e=0;for(let o=n-1;o>=0&&t[o]==="\\";o-=1)e+=1;return e%2===0}function j(t){return/[=,!/]/.test(t)||/\b(?:colorbar|legend|width|height|draw|fill|style|domain|samples|anchor|at|axis)\b/.test(t)}function P(t){return E.has(t)||/^cite[A-Za-z]*/.test(t)}function I(t,n){for(let e=t.indexOf("=");e>=0;e=t.indexOf("=",e+1)){const i=Math.max(...[`
1
+ import{a as z}from"./index-zIjCeZFK.js";import"./react-BoEjKzFZ.js";const R=/([A-Za-z][A-Za-z0-9_.:/-]*(?:\s+[A-Za-z][A-Za-z0-9_.:/-]*){0,7})\s*$/,C=new Set(["tabular","tabularx","tabulary","longtable","array","matrix","pmatrix","bmatrix","Bmatrix","vmatrix","Vmatrix"]),q=new Set(["math","displaymath","equation","equation*","align","align*","alignat","alignat*","gather","gather*","multline","multline*","flalign","flalign*","tikzpicture","axis","scope","pgfonlayer","pgfpicture","tabular","tabularx","tabulary","longtable","array","matrix","pmatrix","bmatrix","Bmatrix","vmatrix","Vmatrix","verbatim","Verbatim","lstlisting","minted","comment","algorithmic","alignat"]),w=new Set(["documentclass","usepackage","RequirePackage","includegraphics","tikzset","pgfplotsset","hypersetup","lstset","definecolor","colorlet","setlength","setcounter","draw","path","fill","filldraw","shade","node","addplot","color","textcolor","colorbox","pagecolor"]),E=new Set(["label","hypertarget","ref","pageref","autoref","nameref","hyperref","index","gls","Gls","glspl","Glspl","cite","citep","citet","citeauthor","citeyear","citenum","parencite","textcite","autocite","footcite"]),$=5,p=new Map,Z=12;let y=!1,x=null;class b extends Error{constructor(){super("A newer writing check replaced this request."),this.name="HarperLintSupersededError"}}function D(t){return t instanceof b}function m(t,n,e){e>n&&t.push({from:n,to:e})}function g(t,n,e,o){if(t[n]!==e)return null;let i=0;for(let r=n;r<t.length;r+=1){const s=t[r-1]==="\\"&&t[r-2]!=="\\";if(!s&&t[r]===e&&(i+=1),!s&&t[r]===o&&(i-=1,i===0))return{from:n,to:r+1,end:r+1}}return null}function u(t,n){let e=n;for(;e<t.length&&/[ \t\r\n]/.test(t[e]);)e+=1;return e}function O(t,n){if(t[n]!=="%")return!1;let e=0;for(let o=n-1;o>=0&&t[o]==="\\";o-=1)e+=1;return e%2===0}function j(t){return/[=,!/]/.test(t)||/\b(?:colorbar|legend|width|height|draw|fill|style|domain|samples|anchor|at|axis)\b/.test(t)}function P(t){return E.has(t)||/^cite[A-Za-z]*/.test(t)}function I(t,n){for(let e=t.indexOf("=");e>=0;e=t.indexOf("=",e+1)){const i=Math.max(...[`
2
2
  `,"[","{","]","}",",",";"].map(a=>t.lastIndexOf(a,e-1)+1)),s=t.slice(i,e).match(R);s?.index!==void 0&&m(n,i+s.index,e);let l=e+1;for(;l<t.length&&/\s/.test(t[l]);)l+=1;let f=l;if(t[l]==="{")f=g(t,l,"{","}")?.end??l;else for(;f<t.length&&!/[,\]\}\n]/.test(t[f]);)f+=1;m(n,l,f)}}function B(t,n,e){const o=/\\(begin|end)\s*\{\s*([^{}]+?)\s*\}/g;o.lastIndex=n;let i=1;for(let r=o.exec(t);r;r=o.exec(t))if(r[2].trim()===e){if(r[1]==="begin")i+=1;else if(--i===0)return o.lastIndex}return null}function H(t,n){for(const e of t.matchAll(/\\\((?:\\.|[^])*?\\\)|\\\[(?:\\.|[^])*?\\\]/g))e.index!==void 0&&m(n,e.index,e.index+e[0].length);for(let e=0;e<t.length;e+=1){if(t[e]!=="$"||t[e-1]==="\\")continue;const o=t[e+1]==="$"?"$$":"$",i=t.indexOf(o,e+o.length);i>=0&&(m(n,e,i+o.length),e=i+o.length-1)}}function M(t){const n=[],e=/[A-Za-z@]/;for(let i=0;i<t.length;i+=1){if(O(t,i)){const a=t.indexOf(`
3
3
  `,i);m(n,i,a<0?t.length:a),i=a<0?t.length:a;continue}if(t[i]!=="\\")continue;const r=i;let s=i+1;if(e.test(t[s]??""))for(;s<t.length&&/[A-Za-z@0-9:_]/.test(t[s]);)s+=1;else s<t.length&&(s+=1);const l=t.slice(i+1,s);m(n,r,s);let f=u(t,s);if(l==="begin"||l==="end"){const a=g(t,f,"{","}");if(a){m(n,a.from,a.to);const d=t.slice(a.from+1,a.to-1).trim();if(f=u(t,a.end),l==="begin"){const h=g(t,f,"[","]");if(h&&(m(n,h.from,h.to),f=u(t,h.end)),C.has(d)){const c=g(t,f,"{","}");c&&m(n,c.from,c.to)}if(q.has(d)){const c=B(t,a.end,d);if(c!==null){m(n,r,c),i=c-1;continue}}}}i=s-1;continue}if(P(l))for(t[f]==="*"&&(f=u(t,f+1));;){const a=g(t,f,"[","]")??g(t,f,"{","}");if(!a)break;m(n,a.from,a.to),f=u(t,a.end)}else{const a=g(t,f,"[","]");if(a&&(w.has(l)||j(t.slice(a.from+1,a.to-1)))&&(m(n,a.from,a.to),f=u(t,a.end)),w.has(l)){const d=l==="definecolor"||l==="colorlet"?3:1;for(let h=0;h<d;h+=1){const c=g(t,f,"{","}");if(!c)break;m(n,c.from,c.to),f=u(t,c.end)}}}i=s-1}H(t,n),I(t,n);for(const i of t.matchAll(/(?:https?|ftp):\/\/[^\s]+/gi))i.index!==void 0&&m(n,i.index,i.index+i[0].length);n.sort((i,r)=>i.from-r.from||i.to-r.to);const o=[];for(const i of n){const r=o.at(-1);r&&i.from<=r.to?r.to=Math.max(r.to,i.to):o.push({...i})}return o}function k(t){const n=M(t),e=[];let o=0,i=0;for(const r of t){for(;i<n.length&&n[i].to<=o;)i+=1;const s=n[i];e.push(s&&s.from<=o&&o<s.to&&r!==`
4
4
  `&&r!=="\r"?" ":r),o+=r.length}return e.join("")}function T(t){const n=[0];let e=0;for(const o of t)e+=o.length,n.push(e);return n}function L(t){return[...new Set(t.map(n=>n.trim()).filter(Boolean))].sort((n,e)=>n.localeCompare(e)).join("\0")}async function V(t,n,e){return(await z(`/api/projects/${t}/spellcheck`,{method:"POST",body:JSON.stringify({path:n,source:e})})).lints}function K(t,n,e,o){const i={from:e.start,to:e.end},r={from:o[e.start]??-1,to:o[e.end]??-1},s=[i,r].filter((l,f,a)=>l.from>=0&&l.to>l.from&&l.to<=t.length&&a.findIndex(d=>d.from===l.from&&d.to===l.to)===f);return s.length===0?null:s.find(l=>n.slice(l.from,l.to)===e.problem)??s.find(l=>/[A-Za-z]/.test(n.slice(l.from,l.to)))??s[0]??null}function N(t,n,e,o){const i=K(t,n,e,o);if(!i)return null;const{from:r,to:s}=i;if(!/[A-Za-z]/.test(n.slice(r,s)))return null;const l=t.slice(r,s);if(!l.trim()||/[\\%$]/.test(l))return null;const f=e.kind==="Spelling"||e.kind==="Typo"?"spelling":"grammar",a=e.suggestions.filter((d,h,c)=>h<$&&c.indexOf(d)===h);return{from:r,to:s,word:l,kind:f,message:e.message,suggestions:a}}function S(t){let n=2166136261;for(let e=0;e<t.length;e+=1)n^=t.charCodeAt(e),n=Math.imul(n,16777619);return`${t.length}:${n>>>0}`}function v(t,n){const e=S(t),o=p.get(e);return!o||o.source!==t||o.dictionary!==n?null:(p.delete(e),p.set(e,o),o.issues)}function _(t,n,e){const o=S(t);for(p.set(o,{source:t,dictionary:n,issues:e});p.size>Z;){const i=p.keys().next().value;if(i===void 0)break;p.delete(i)}}async function G(t,n,e){const o=L(n),i=v(t,o);if(i)return i;const r=k(t),s=T(t),l=new Set(n.map(a=>a.trim().toLocaleLowerCase("en-US")).filter(Boolean)),f=e.map(a=>N(t,r,a,s)).filter(a=>!!a).filter(a=>a.kind!=="spelling"||!l.has(a.word.trim().toLocaleLowerCase("en-US"))).sort((a,d)=>a.from-d.from||a.to-d.to);return _(t,o,f),f}async function U(t,n,e,o){const i=L(o),r=v(e,i);if(r)return r;const s=k(e),l=await V(t,n,s);return G(e,o,l)}async function A(){if(y||!x)return;const t=x;x=null,y=!0;try{t.resolve(await U(t.projectId,t.path,t.source,t.customWords))}catch(n){t.reject(n)}finally{y=!1,A()}}function F(t,n,e,o=[]){return new Promise((i,r)=>{x?.reject(new b),x={projectId:t,path:n,source:e,customWords:[...o],resolve:i,reject:r},A()})}export{b as HarperLintSupersededError,M as ignoredRanges,D as isHarperLintSupersededError,F as lintLatex,G as mapLatexLints,k as maskLatexSource};
@@ -10,9 +10,9 @@
10
10
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource/iosevka@5.2.5/400.css" />
11
11
  <link rel="icon" type="image/svg+xml" href="/logo.svg" />
12
12
  <title>TexLite</title>
13
- <script type="module" crossorigin src="/assets/index-DRShM2ob.js"></script>
13
+ <script type="module" crossorigin src="/assets/index-zIjCeZFK.js"></script>
14
14
  <link rel="modulepreload" crossorigin href="/assets/react-BoEjKzFZ.js">
15
- <link rel="stylesheet" crossorigin href="/assets/index-DzcH7hBu.css">
15
+ <link rel="stylesheet" crossorigin href="/assets/index-MDwr9W9R.css">
16
16
  </head>
17
17
  <body>
18
18
  <div id="root"></div>
@@ -43,6 +43,10 @@ const STATE_SAVE_DELAY_MS = 750;
43
43
  const ROOM_IDLE_MS = 30_000;
44
44
  const FORMAT_LEASE_TTL_MS = 45_000;
45
45
  const MAX_FORMAT_LEASE_WAITERS = MAX_PROJECT_SESSIONS * 2;
46
+ // Completion notifications are useful only to browsers that were already
47
+ // present when the operation finished. The database and retained manifests
48
+ // are the authority for a later workspace open.
49
+ const COMPLETED_COMPILE_STATE_TTL_MS = 60_000;
46
50
  const EPHEMERAL_META_KEYS = ["compileStates", "filesEvent", "commentsRevision", "dictionaryRevision"];
47
51
  const COLORS = [
48
52
  ["#1677c8", "#1677c833"], ["#d65745", "#d6574533"], ["#16866a", "#16866a33"],
@@ -413,13 +417,10 @@ export class CollaborationService {
413
417
  room.doc.transact(() => room.meta.set("compileStates", retained), META_ORIGIN);
414
418
  }
415
419
  /**
416
- * Drop compile states that no longer describe an active database run.
417
- *
418
- * `compileStates` is intentionally only a live UI signal. A browser can
419
- * nevertheless replay an old IndexedDB update while reconnecting, so the
420
- * server must not let an old `queued`/`running` value become authoritative
421
- * again after a restart. Completed states are retained for the current room
422
- * because they are useful to the UI and cannot disable a new compile.
420
+ * Keep collaboration compile metadata strictly ephemeral and database
421
+ * backed. A browser can replay old IndexedDB updates after reconnecting;
422
+ * completed states must therefore not override the retained-PDF lookup for
423
+ * a newly opened workspace.
423
424
  */
424
425
  sanitizeCompileStates(room) {
425
426
  const current = room.meta.get("compileStates");
@@ -430,19 +431,42 @@ export class CollaborationService {
430
431
  }
431
432
  const retained = {};
432
433
  let changed = false;
434
+ const checkedAt = Date.now();
435
+ const findRun = this.db.prepare(`SELECT id, status, main_file FROM compile_runs
436
+ WHERE id = ? AND project_id = ?`);
437
+ const findLatestRun = this.db.prepare(`SELECT id, status FROM compile_runs
438
+ WHERE project_id = ? AND main_file = ? ORDER BY created_at DESC LIMIT 1`);
433
439
  for (const [mainFile, value] of Object.entries(current)) {
434
440
  if (!isSharedCompileState(mainFile, value)) {
435
441
  changed = true;
436
442
  continue;
437
443
  }
438
444
  if (value.status === "queued" || value.status === "running") {
439
- const run = this.db.prepare(`SELECT status, main_file FROM compile_runs
440
- WHERE id = ? AND project_id = ?`).get(value.runId, room.projectId);
445
+ const run = findRun.get(value.runId, room.projectId);
441
446
  if (!run || run.main_file !== mainFile || (run.status !== "queued" && run.status !== "running")) {
442
447
  changed = true;
443
448
  continue;
444
449
  }
445
450
  }
451
+ else {
452
+ const updatedAt = Date.parse(value.updatedAt);
453
+ const fresh = Number.isFinite(updatedAt)
454
+ && updatedAt <= checkedAt + COMPLETED_COMPILE_STATE_TTL_MS
455
+ && checkedAt - updatedAt <= COMPLETED_COMPILE_STATE_TTL_MS;
456
+ if (!fresh) {
457
+ changed = true;
458
+ continue;
459
+ }
460
+ if (value.status !== "cleaned") {
461
+ const run = findRun.get(value.runId, room.projectId);
462
+ const latest = findLatestRun.get(room.projectId, mainFile);
463
+ if (!run || run.main_file !== mainFile || run.status !== value.status
464
+ || !latest || latest.id !== value.runId || latest.status !== value.status) {
465
+ changed = true;
466
+ continue;
467
+ }
468
+ }
469
+ }
446
470
  retained[mainFile] = value;
447
471
  }
448
472
  if (!changed && Object.keys(retained).length === Object.keys(current).length)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "texlite",
3
- "version": "0.7.6",
3
+ "version": "0.7.7",
4
4
  "description": "A lightweight local-first collaborative LaTeX workspace",
5
5
  "license": "AGPL-3.0-only",
6
6
  "repository": {