gitlatex 1.0.8__tar.gz → 1.2.0__tar.gz
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.
- {gitlatex-1.0.8 → gitlatex-1.2.0}/PKG-INFO +1 -1
- {gitlatex-1.0.8 → gitlatex-1.2.0}/gitlatex/__init__.py +1 -1
- {gitlatex-1.0.8 → gitlatex-1.2.0}/gitlatex/public/app.js +193 -4
- gitlatex-1.2.0/gitlatex/public/index.html +573 -0
- {gitlatex-1.0.8 → gitlatex-1.2.0}/gitlatex/public/style.css +415 -0
- {gitlatex-1.0.8 → gitlatex-1.2.0}/gitlatex/server.py +72 -1
- {gitlatex-1.0.8 → gitlatex-1.2.0}/gitlatex.egg-info/PKG-INFO +1 -1
- {gitlatex-1.0.8 → gitlatex-1.2.0}/pyproject.toml +1 -1
- gitlatex-1.0.8/gitlatex/public/index.html +0 -265
- {gitlatex-1.0.8 → gitlatex-1.2.0}/README.md +0 -0
- {gitlatex-1.0.8 → gitlatex-1.2.0}/gitlatex/__main__.py +0 -0
- {gitlatex-1.0.8 → gitlatex-1.2.0}/gitlatex/public/bib-commands.json +0 -0
- {gitlatex-1.0.8 → gitlatex-1.2.0}/gitlatex/public/favicon.svg +0 -0
- {gitlatex-1.0.8 → gitlatex-1.2.0}/gitlatex/public/latex-commands.json +0 -0
- {gitlatex-1.0.8 → gitlatex-1.2.0}/gitlatex.egg-info/SOURCES.txt +0 -0
- {gitlatex-1.0.8 → gitlatex-1.2.0}/gitlatex.egg-info/dependency_links.txt +0 -0
- {gitlatex-1.0.8 → gitlatex-1.2.0}/gitlatex.egg-info/entry_points.txt +0 -0
- {gitlatex-1.0.8 → gitlatex-1.2.0}/gitlatex.egg-info/requires.txt +0 -0
- {gitlatex-1.0.8 → gitlatex-1.2.0}/gitlatex.egg-info/top_level.txt +0 -0
- {gitlatex-1.0.8 → gitlatex-1.2.0}/setup.cfg +0 -0
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
"""GitLaTeX IDE - LaTeX projects with Git support."""
|
|
2
|
-
__version__ = "1.0
|
|
2
|
+
__version__ = "1.2.0"
|
|
@@ -107,7 +107,7 @@ function applyTheme(theme) {
|
|
|
107
107
|
|
|
108
108
|
function getMonacoTheme() {
|
|
109
109
|
const t = document.documentElement.getAttribute("data-theme");
|
|
110
|
-
return t === "light" ? "
|
|
110
|
+
return t === "light" ? "gitlatex-light" : "gitlatex-dark";
|
|
111
111
|
}
|
|
112
112
|
|
|
113
113
|
function setTheme(theme) {
|
|
@@ -183,6 +183,66 @@ function setInfoLink(el, url, label) {
|
|
|
183
183
|
}
|
|
184
184
|
}
|
|
185
185
|
|
|
186
|
+
// ----- Update check (PyPI) -----
|
|
187
|
+
let updateInfo = null;
|
|
188
|
+
|
|
189
|
+
/** Ask the server whether a newer gitlatex is on PyPI. Never throws. */
|
|
190
|
+
async function checkForUpdate(force) {
|
|
191
|
+
try {
|
|
192
|
+
const res = await fetchApi("/api/update-check" + (force ? "?force=1" : ""));
|
|
193
|
+
const data = await res.json();
|
|
194
|
+
updateInfo = data && typeof data === "object" ? data : null;
|
|
195
|
+
} catch (_) {
|
|
196
|
+
updateInfo = null;
|
|
197
|
+
}
|
|
198
|
+
renderUpdateState();
|
|
199
|
+
return updateInfo;
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
/** Dot on every Settings gear, plus the notice inside Settings itself. */
|
|
203
|
+
function renderUpdateState() {
|
|
204
|
+
const available = !!(updateInfo && updateInfo.updateAvailable && updateInfo.latest);
|
|
205
|
+
document.querySelectorAll('.icon-btn[href="#/settings"]').forEach(function (el) {
|
|
206
|
+
el.classList.toggle("has-update", available);
|
|
207
|
+
if (available) el.title = "Settings — version " + updateInfo.latest + " available";
|
|
208
|
+
else el.title = "Settings";
|
|
209
|
+
});
|
|
210
|
+
|
|
211
|
+
const notice = document.getElementById("update-notice");
|
|
212
|
+
if (notice) {
|
|
213
|
+
notice.classList.toggle("hidden", !available);
|
|
214
|
+
if (available) {
|
|
215
|
+
const latestEl = document.getElementById("update-notice-latest");
|
|
216
|
+
const currentEl = document.getElementById("update-notice-current");
|
|
217
|
+
const linkEl = document.getElementById("update-notice-link");
|
|
218
|
+
if (latestEl) latestEl.textContent = updateInfo.latest;
|
|
219
|
+
if (currentEl) currentEl.textContent = updateInfo.current || "—";
|
|
220
|
+
if (linkEl && updateInfo.pypi) linkEl.href = updateInfo.pypi;
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
const versionEl = document.getElementById("settings-info-version");
|
|
225
|
+
if (versionEl) {
|
|
226
|
+
const pill = versionEl.querySelector(".version-pill");
|
|
227
|
+
if (pill) pill.remove();
|
|
228
|
+
if (available) {
|
|
229
|
+
const el = document.createElement("span");
|
|
230
|
+
el.className = "version-pill";
|
|
231
|
+
el.textContent = "update available";
|
|
232
|
+
versionEl.appendChild(el);
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
const status = document.getElementById("update-status");
|
|
237
|
+
if (status) {
|
|
238
|
+
if (available || !updateInfo) status.textContent = "";
|
|
239
|
+
else if (updateInfo.disabled) status.textContent = "Update checks are disabled.";
|
|
240
|
+
else if (updateInfo.error) status.textContent = "Could not reach PyPI to check for updates.";
|
|
241
|
+
else if (updateInfo.latest) status.textContent = "You are on the latest version.";
|
|
242
|
+
else status.textContent = "";
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
|
|
186
246
|
async function populateSettingsTechInfo() {
|
|
187
247
|
const versionEl = document.getElementById("settings-info-version");
|
|
188
248
|
const urlEl = document.getElementById("settings-info-url");
|
|
@@ -200,6 +260,9 @@ async function populateSettingsTechInfo() {
|
|
|
200
260
|
if (repoEl) repoEl.textContent = "—";
|
|
201
261
|
if (pypiEl) pypiEl.textContent = "—";
|
|
202
262
|
}
|
|
263
|
+
// Re-apply first (setting version wipes the pill), then refresh from PyPI.
|
|
264
|
+
renderUpdateState();
|
|
265
|
+
checkForUpdate();
|
|
203
266
|
}
|
|
204
267
|
|
|
205
268
|
function setConsole(text) {
|
|
@@ -332,6 +395,7 @@ function getRoute() {
|
|
|
332
395
|
const parts = hash.split("/").filter(Boolean);
|
|
333
396
|
if (parts[0] === "editor" && parts[1]) return { page: "editor", repo: parts[1] };
|
|
334
397
|
if (parts[0] === "settings") return { page: "settings" };
|
|
398
|
+
if (parts[0] === "compiler-api") return { page: "compiler-api" };
|
|
335
399
|
return { page: "home" };
|
|
336
400
|
}
|
|
337
401
|
|
|
@@ -354,6 +418,12 @@ function route() {
|
|
|
354
418
|
populateSettings();
|
|
355
419
|
return;
|
|
356
420
|
}
|
|
421
|
+
if (r.page === "compiler-api") {
|
|
422
|
+
showView("compiler-api-view");
|
|
423
|
+
const content = document.querySelector("#compiler-api-view .settings-content");
|
|
424
|
+
if (content) content.scrollTop = 0;
|
|
425
|
+
return;
|
|
426
|
+
}
|
|
357
427
|
showView("editor-view");
|
|
358
428
|
document.getElementById("editor-repo-name").textContent = decodeURIComponent(r.repo);
|
|
359
429
|
openEditorPage(r.repo);
|
|
@@ -619,9 +689,108 @@ function ensureMonacoReady(callback) {
|
|
|
619
689
|
monacoApi = monaco;
|
|
620
690
|
// Register LaTeX so completion provider and options apply
|
|
621
691
|
monaco.languages.register({ id: "latex" });
|
|
622
|
-
// Word pattern so that "\" and "\section" are "words" for suggest filtering (prefix matches our filterText "\\" + label)
|
|
623
692
|
monaco.languages.setLanguageConfiguration("latex", {
|
|
624
|
-
wordPattern: /\\[a-zA-Z*]
|
|
693
|
+
wordPattern: /\\[a-zA-Z*]*/,
|
|
694
|
+
brackets: [["{", "}"], ["[", "]"], ["\\begin{", "\\end{"], ["\\left(", "\\right)"], ["\\left[", "\\right]"], ["\\left\\{", "\\right\\}"]],
|
|
695
|
+
autoClosingPairs: [{ open: "{", close: "}" }, { open: "[", close: "]" }, { open: "(", close: ")" }, { open: "$", close: "$" }]
|
|
696
|
+
});
|
|
697
|
+
monaco.languages.setMonarchTokensProvider("latex", {
|
|
698
|
+
tokenizer: {
|
|
699
|
+
root: [
|
|
700
|
+
[/%[^\n]*/, "comment"],
|
|
701
|
+
[/\\begin\{[^}]*\}/, { token: "keyword", next: "@texBody" }],
|
|
702
|
+
[/\\end\{[^}]*\}/, { token: "keyword" }],
|
|
703
|
+
[/\\(usepackage|documentclass|include|input|bibliography|bibliographystyle|usepackage)(\{[^}]*\})?/, "keyword"],
|
|
704
|
+
[/\\(section|subsection|subsubsection|chapter|paragraph|subparagraph|part)\*?/, "keyword.strong"],
|
|
705
|
+
[/\\(textbf|textit|texttt|textsf|textsc|emph|underline|textmd|textrm|textup|textnormal|textsl|textbf)\{/, "keyword", "@texArgBold"],
|
|
706
|
+
[/\\(newcommand|renewcommand|providecommand|DeclareMathOperator|def|let|newenvironment|renewenvironment)/, "keyword"],
|
|
707
|
+
[/\\(caption|label|ref|pageref|eqref|autoref|cite|citep|citet|nocite|footnote|thanks|maketitle|tableofcontents|listoffigures|listoftables|appendix|addcontentsline|addtocontents|clearpage|newpage|pagebreak|linebreak|nolinebreak|newline|today|TeX|LaTeX|LaTeXe)/, "keyword"],
|
|
708
|
+
[/\\(begin|end|item|hspace|vspace|hfill|vfill|centering|raggedright|raggedleft|noindent|indent|par|smallskip|medskip|bigskip)/, "keyword"],
|
|
709
|
+
[/\\(title|author|date|address|email|institute|thanks|and)/, "keyword"],
|
|
710
|
+
[/\\(alpha|beta|gamma|delta|epsilon|zeta|eta|theta|iota|kappa|lambda|mu|nu|xi|omicron|pi|rho|sigma|tau|upsilon|phi|chi|psi|omega|Gamma|Delta|Theta|Lambda|Xi|Pi|Sigma|Upsilon|Phi|Psi|Omega|varepsilon|vartheta|varpi|varrho|varsigma|varphi)/, "type"],
|
|
711
|
+
[/\\(int|sum|prod|oint|coprod|bigcup|bigcap|bigvee|bigwedge|bigoplus|bigotimes|bigodot|biguplus|lim|log|ln|sin|cos|tan|cot|sec|csc|arcsin|arccos|arctan|sinh|cosh|tanh|coth|det|dim|gcd|hom|inf|ker|lg|max|min|Pr|sup|exp|deg|mod|bmod|pmod|pm|mp|times|div|ast|star|circ|bullet|cdot|cap|cup|uplus|sqcap|sqcup|vee|wedge|setminus|wr|diamond|bigtriangleup|bigtriangledown|triangleleft|triangleright|lhd|rhd|unlhd|unrhd|oplus|ominus|otimes|oslash|odot|bigcirc|dagger|ddagger|amalg|leq|geq|neq|equiv|approx|cong|propto|sim|simeq|asymp|doteq|parallel|models|bot|mid|prec|succ|preceq|succeq|ll|gg|subset|supset|subseteq|supseteq|sqsubset|sqsupseteq|in|ni|notin|vdash|dashv|smile|frown|perp|bowtie|Join|propto|mapsto|to|gets|leftarrow|rightarrow|uparrow|downarrow|updownarrow|Leftarrow|Rightarrow|Uparrow|Downarrow|Updownarrow|longleftarrow|longrightarrow|longleftrightarrow|Longleftarrow|Longrightarrow|Longleftrightarrow|nearrow|searrow|swarrow|nwarrow|leftharpoonup|leftharpoondown|rightharpoonup|rightharpoondown|rightleftharpoons|leadsto|iff)/, "type"],
|
|
712
|
+
[/\\[a-zA-Z@*]+/, "keyword"],
|
|
713
|
+
[/\$\$/, { token: "delimiter.math", next: "@mathDisplay" }],
|
|
714
|
+
[/\$/, { token: "delimiter.math", next: "@mathInline" }],
|
|
715
|
+
[/[{}]/, "delimiter.bracket"]
|
|
716
|
+
],
|
|
717
|
+
texBody: [
|
|
718
|
+
[/%[^\n]*/, "comment"],
|
|
719
|
+
[/\\end\{[^}]*\}/, { token: "keyword", next: "@pop" }],
|
|
720
|
+
[/\\[a-zA-Z@*]+/, "keyword"],
|
|
721
|
+
[/[{}]/, "delimiter.bracket"],
|
|
722
|
+
[/\$\$/, { token: "delimiter.math", next: "@mathDisplay" }],
|
|
723
|
+
[/\$/, { token: "delimiter.math", next: "@mathInline" }]
|
|
724
|
+
],
|
|
725
|
+
texArgBold: [
|
|
726
|
+
[/[^}]+/, "string"],
|
|
727
|
+
[/\}/, "delimiter.bracket", "@pop"]
|
|
728
|
+
],
|
|
729
|
+
mathDisplay: [
|
|
730
|
+
[/\$\$/, { token: "delimiter.math", next: "@pop" }],
|
|
731
|
+
[/\\[a-zA-Z@*]+/, "type"],
|
|
732
|
+
[/[{}]/, "delimiter.bracket"],
|
|
733
|
+
[/[0-9]+/, "number"],
|
|
734
|
+
[/[_^]/, "operator"],
|
|
735
|
+
[/\w+/, "identifier"]
|
|
736
|
+
],
|
|
737
|
+
mathInline: [
|
|
738
|
+
[/\$/, { token: "delimiter.math", next: "@pop" }],
|
|
739
|
+
[/\\[a-zA-Z@*]+/, "type"],
|
|
740
|
+
[/[{}]/, "delimiter.bracket"],
|
|
741
|
+
[/[0-9]+/, "number"],
|
|
742
|
+
[/[_^]/, "operator"],
|
|
743
|
+
[/\w+/, "identifier"]
|
|
744
|
+
]
|
|
745
|
+
}
|
|
746
|
+
});
|
|
747
|
+
|
|
748
|
+
// === Editor color themes so LaTeX + BibTeX tokens are visible ===
|
|
749
|
+
monaco.editor.defineTheme("gitlatex-dark", {
|
|
750
|
+
base: "vs-dark",
|
|
751
|
+
inherit: true,
|
|
752
|
+
rules: [
|
|
753
|
+
{ token: "comment", foreground: "6a9955", fontStyle: "italic" },
|
|
754
|
+
{ token: "keyword", foreground: "569cd6" },
|
|
755
|
+
{ token: "keyword.strong", foreground: "4ec9b0", fontStyle: "bold" },
|
|
756
|
+
{ token: "type", foreground: "c586c0" },
|
|
757
|
+
{ token: "string", foreground: "ce9178" },
|
|
758
|
+
{ token: "number", foreground: "b5cea8" },
|
|
759
|
+
{ token: "delimiter.bracket", foreground: "808080" },
|
|
760
|
+
{ token: "delimiter.math", foreground: "e8ab53", fontStyle: "bold" },
|
|
761
|
+
{ token: "operator", foreground: "d4d4d4" },
|
|
762
|
+
{ token: "identifier", foreground: "9cdcfe" }
|
|
763
|
+
],
|
|
764
|
+
colors: {
|
|
765
|
+
"editor.background": "#0d1117",
|
|
766
|
+
"editor.foreground": "#e6edf3",
|
|
767
|
+
"editorCursor.foreground": "#e6edf3",
|
|
768
|
+
"editorLineNumber.foreground": "#484f58",
|
|
769
|
+
"editorLineNumber.activeForeground": "#8b949e"
|
|
770
|
+
}
|
|
771
|
+
});
|
|
772
|
+
monaco.editor.defineTheme("gitlatex-light", {
|
|
773
|
+
base: "vs",
|
|
774
|
+
inherit: true,
|
|
775
|
+
rules: [
|
|
776
|
+
{ token: "comment", foreground: "6a9955", fontStyle: "italic" },
|
|
777
|
+
{ token: "keyword", foreground: "0000ff" },
|
|
778
|
+
{ token: "keyword.strong", foreground: "795e26", fontStyle: "bold" },
|
|
779
|
+
{ token: "type", foreground: "af00db" },
|
|
780
|
+
{ token: "string", foreground: "a31515" },
|
|
781
|
+
{ token: "number", foreground: "098658" },
|
|
782
|
+
{ token: "delimiter.bracket", foreground: "808080" },
|
|
783
|
+
{ token: "delimiter.math", foreground: "d16969", fontStyle: "bold" },
|
|
784
|
+
{ token: "operator", foreground: "000000" },
|
|
785
|
+
{ token: "identifier", foreground: "001080" }
|
|
786
|
+
],
|
|
787
|
+
colors: {
|
|
788
|
+
"editor.background": "#ffffff",
|
|
789
|
+
"editor.foreground": "#1f2328",
|
|
790
|
+
"editorCursor.foreground": "#1f2328",
|
|
791
|
+
"editorLineNumber.foreground": "#8c959f",
|
|
792
|
+
"editorLineNumber.activeForeground": "#656d76"
|
|
793
|
+
}
|
|
625
794
|
});
|
|
626
795
|
|
|
627
796
|
// Register BibTeX for .bib files
|
|
@@ -1138,7 +1307,7 @@ async function loadFile(path) {
|
|
|
1138
1307
|
if (monacoApi) {
|
|
1139
1308
|
const model = editor.getModel();
|
|
1140
1309
|
if (model) {
|
|
1141
|
-
const lang = path.endsWith(".tex") ? "latex" : path.endsWith(".bib") ? "bib" : "plaintext";
|
|
1310
|
+
const lang = (path.endsWith(".tex") || path.endsWith(".sty") || path.endsWith(".cls")) ? "latex" : path.endsWith(".bib") ? "bib" : "plaintext";
|
|
1142
1311
|
monacoApi.editor.setModelLanguage(model, lang);
|
|
1143
1312
|
}
|
|
1144
1313
|
}
|
|
@@ -1790,6 +1959,25 @@ document.addEventListener("click", function (e) {
|
|
|
1790
1959
|
}
|
|
1791
1960
|
});
|
|
1792
1961
|
|
|
1962
|
+
// Copy buttons on the Compiler API docs code samples
|
|
1963
|
+
document.addEventListener("click", function (e) {
|
|
1964
|
+
const btn = e.target.closest(".docs-copy");
|
|
1965
|
+
if (!btn) return;
|
|
1966
|
+
const code = btn.parentElement && btn.parentElement.querySelector("code");
|
|
1967
|
+
if (!code || !navigator.clipboard) return;
|
|
1968
|
+
navigator.clipboard.writeText(code.textContent).then(function () {
|
|
1969
|
+
btn.textContent = "Copied";
|
|
1970
|
+
btn.classList.add("copied");
|
|
1971
|
+
setTimeout(function () {
|
|
1972
|
+
btn.textContent = "Copy";
|
|
1973
|
+
btn.classList.remove("copied");
|
|
1974
|
+
}, 1500);
|
|
1975
|
+
}).catch(function () {
|
|
1976
|
+
btn.textContent = "Press Ctrl+C";
|
|
1977
|
+
setTimeout(function () { btn.textContent = "Copy"; }, 1500);
|
|
1978
|
+
});
|
|
1979
|
+
});
|
|
1980
|
+
|
|
1793
1981
|
document.getElementById("settings-save")?.addEventListener("click", function () {
|
|
1794
1982
|
const apiInput = document.getElementById("settings-compiler-api");
|
|
1795
1983
|
const keyInput = document.getElementById("settings-compiler-api-key");
|
|
@@ -1889,4 +2077,5 @@ window.addEventListener("hashchange", route);
|
|
|
1889
2077
|
window.addEventListener("load", function () {
|
|
1890
2078
|
route();
|
|
1891
2079
|
setupResizers();
|
|
2080
|
+
checkForUpdate();
|
|
1892
2081
|
});
|