Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4eb1c0c2d8 |
No files matched your search
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
||||
|
||||
[project]
|
||||
name = "tesm"
|
||||
version = "2.3.0"
|
||||
version = "2.3.1"
|
||||
description = "TESM -- Verwaltung und Ueberwachung von PoE-Endgeraeten und Aruba-Switchen"
|
||||
requires-python = ">=3.11"
|
||||
dependencies = [
|
||||
|
||||
@@ -214,7 +214,13 @@ def save_form(token: str):
|
||||
|
||||
try:
|
||||
original = service.resolve_path(mount, relative)
|
||||
zielordner = service.resolve_path(mount, ordner) if ordner else original.parent
|
||||
# Mit Namen entscheidet das Ordnerfeld -- leer heisst Wurzelverzeichnis,
|
||||
# so wie es im Feld steht. Ohne Namen (Aufruf ohne Oberflaeche) bleibt
|
||||
# es beim Ordner des Originals.
|
||||
if wunschname:
|
||||
zielordner = service.resolve_path(mount, ordner)
|
||||
else:
|
||||
zielordner = service.resolve_path(mount, ordner) if ordner else original.parent
|
||||
if not zielordner.is_dir():
|
||||
return {"error": f"Den Ordner '{ordner}' gibt es in dieser Freigabe nicht."}, 400
|
||||
if wunschname:
|
||||
|
||||
@@ -209,7 +209,8 @@
|
||||
iPad in Originalgrösse (also einen Ausschnitt) und ein PDF auf iPadOS
|
||||
nur als Standbild -- Formularfelder liessen sich nicht anfassen. #}
|
||||
<div class="modal__body modal__body--flush" data-viewer
|
||||
data-viewer-pdfjs="{{ asset_url('vendor/pdfjs/pdf.min.js') }}">
|
||||
data-viewer-pdfjs="{{ asset_url('vendor/pdfjs/pdf.min.js') }}"
|
||||
data-viewer-pdflib="{{ asset_url('vendor/pdflib/pdf-lib.min.js') }}">
|
||||
<div class="viewer">
|
||||
<div class="viewer__stage" data-viewer-bildbuehne hidden>
|
||||
<img class="viewer__img" alt="" data-viewer-bild>
|
||||
@@ -230,7 +231,7 @@
|
||||
<label class="viewer__feld">
|
||||
<span class="field__label">Ordner</span>
|
||||
<input class="input" list="freigabe-ordner" data-viewer-ordner
|
||||
placeholder="Wurzelverzeichnis" autocomplete="off">
|
||||
placeholder="Wurzelverzeichnis der Freigabe" autocomplete="off">
|
||||
</label>
|
||||
<label class="viewer__feld">
|
||||
<span class="field__label">Dateiname</span>
|
||||
|
||||
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
||||
|
||||
[project]
|
||||
name = "tesm-core"
|
||||
version = "2.3.0"
|
||||
version = "2.3.1"
|
||||
description = "Gemeinsames Anwendungsgeruest (Auth, RBAC, Navigation, Design-System, Migrationen) fuer TESM und TESM-Lizenzserver"
|
||||
requires-python = ">=3.11"
|
||||
dependencies = [
|
||||
|
||||
@@ -135,7 +135,7 @@ def create_base_app(
|
||||
#: Wortmarke, ohne Zeile darunter; die Marke selbst zeigen beide
|
||||
#: Anwendungen.
|
||||
auth_tagline: str = "",
|
||||
app_version: str = "2.3.0",
|
||||
app_version: str = "2.3.1",
|
||||
built_in_trusted_keys: tuple[str, ...] = (),
|
||||
enable_license: bool = True,
|
||||
template_folder: str | None = None,
|
||||
|
||||
@@ -764,6 +764,14 @@
|
||||
flex: 1;
|
||||
min-height: 0;
|
||||
}
|
||||
/* pdf.js rechnet fuer die Seite mit dem Standard "content-box": ihr
|
||||
9-Pixel-Rahmen liegt *ausserhalb* der angegebenen Breite. Unser globales
|
||||
"border-box" rechnete ihn hinein -- die Leinwand wurde 18 Pixel schmaler
|
||||
als die Anmerkungsebene, und die Formularfelder wanderten nach rechts
|
||||
unten, immer weiter je weiter unten sie lagen. */
|
||||
.viewer__pdf .pdfViewer .page {
|
||||
box-sizing: content-box;
|
||||
}
|
||||
.viewer__pdfscroll {
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
@@ -781,6 +789,36 @@
|
||||
.viewer__hint {
|
||||
margin-inline-start: auto;
|
||||
}
|
||||
/* Bildfeld eines Formulars: der Kasten zeigt das gewaehlte Foto, die
|
||||
Schaltflaeche liegt darin. Acrobats eigener Knopf tut im Browser nichts --
|
||||
das hier ist der Ersatz. */
|
||||
.viewer__bildfeld [data-viewer-bildvorschau] {
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: contain;
|
||||
background: #fff;
|
||||
}
|
||||
.viewer__bildwahl {
|
||||
position: absolute;
|
||||
inset: auto 0 4px 0;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
cursor: pointer;
|
||||
}
|
||||
.viewer__bildwahl > span {
|
||||
padding: 4px 10px;
|
||||
border-radius: var(--r-sm, 6px);
|
||||
background: var(--accent);
|
||||
color: #fff;
|
||||
font-size: var(--fs-xs);
|
||||
font-weight: 600;
|
||||
box-shadow: var(--shadow-sm, 0 1px 3px rgb(0 0 0 / 0.3));
|
||||
}
|
||||
.viewer__bildfeld--belegt .viewer__bildwahl > span {
|
||||
opacity: 0.85;
|
||||
}
|
||||
.viewer__save {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
|
||||
@@ -142,6 +142,120 @@ function bildBetrachter(buehne, bild) {
|
||||
};
|
||||
}
|
||||
|
||||
/* -- Bildfelder in Formularen ---------------------------------------------- */
|
||||
|
||||
//: Groesser muss ein Foto in einem Formular nicht sein.
|
||||
const FOTO_KANTE = 1600;
|
||||
|
||||
/** Macht aus einer gewaehlten Datei ein JPEG in vertretbarer Groesse.
|
||||
*
|
||||
* Ueber eine Leinwand, nicht roh: damit wird aus allem, was der Browser
|
||||
* anzeigen kann, ein JPEG -- auf einem iPad also auch aus HEIC, das pdf-lib
|
||||
* nicht kennt. Und ein 12-Megapixel-Foto blaeht das Formular nicht auf.
|
||||
*/
|
||||
async function fotoAlsJpeg(datei) {
|
||||
// Keine Objektadresse: die CSP erlaubt Bilder nur von "self" und als data:.
|
||||
// createImageBitmap nimmt die Datei unmittelbar; wo es fehlt, tut es eine
|
||||
// data:-Adresse.
|
||||
let bild;
|
||||
if (typeof createImageBitmap === "function") {
|
||||
try {
|
||||
bild = await createImageBitmap(datei);
|
||||
} catch {
|
||||
bild = null;
|
||||
}
|
||||
}
|
||||
if (!bild) {
|
||||
const daten = await new Promise((fertig, schiefgegangen) => {
|
||||
const leser = new FileReader();
|
||||
leser.onload = () => fertig(String(leser.result));
|
||||
leser.onerror = () => schiefgegangen(new Error("Die Datei liess sich nicht lesen."));
|
||||
leser.readAsDataURL(datei);
|
||||
});
|
||||
bild = await new Promise((fertig, schiefgegangen) => {
|
||||
const el = new Image();
|
||||
el.onload = () => fertig(el);
|
||||
el.onerror = () => schiefgegangen(new Error("Dieses Bild kann der Browser nicht anzeigen."));
|
||||
el.src = daten;
|
||||
});
|
||||
}
|
||||
const breiteRoh = bild.width || bild.naturalWidth;
|
||||
const hoeheRoh = bild.height || bild.naturalHeight;
|
||||
const faktor = Math.min(1, FOTO_KANTE / Math.max(breiteRoh, hoeheRoh));
|
||||
const leinwand = document.createElement("canvas");
|
||||
leinwand.width = Math.max(1, Math.round(breiteRoh * faktor));
|
||||
leinwand.height = Math.max(1, Math.round(hoeheRoh * faktor));
|
||||
leinwand.getContext("2d").drawImage(bild, 0, 0, leinwand.width, leinwand.height);
|
||||
bild.close?.();
|
||||
const klecks = await new Promise((fertig) => leinwand.toBlob(fertig, "image/jpeg", 0.85));
|
||||
return {
|
||||
bytes: new Uint8Array(await klecks.arrayBuffer()),
|
||||
breite: leinwand.width,
|
||||
hoehe: leinwand.height,
|
||||
vorschau: leinwand.toDataURL("image/jpeg", 0.6),
|
||||
};
|
||||
}
|
||||
|
||||
let pdflibGeladen = null;
|
||||
|
||||
/** pdf-lib nachladen -- nur wenn wirklich ein Bild eingesetzt wird. */
|
||||
async function pdflibLaden(adresse) {
|
||||
if (!pdflibGeladen) {
|
||||
pdflibGeladen = new Promise((fertig, schiefgegangen) => {
|
||||
const skript = document.createElement("script");
|
||||
skript.src = adresse;
|
||||
skript.onload = () => fertig(window.PDFLib);
|
||||
skript.onerror = () => {
|
||||
pdflibGeladen = null;
|
||||
schiefgegangen(new Error("pdf-lib liess sich nicht laden."));
|
||||
};
|
||||
document.head.append(skript);
|
||||
});
|
||||
}
|
||||
return pdflibGeladen;
|
||||
}
|
||||
|
||||
/** Stempelt die gewaehlten Fotos in die Bildfelder.
|
||||
*
|
||||
* Eingabe sind die Bytes, die pdf.js nach dem Ausfuellen geschrieben hat --
|
||||
* die Formularwerte bleiben also erhalten.
|
||||
*/
|
||||
async function fotosEinsetzen(bytes, bilder, adresse) {
|
||||
const PDFLib = await pdflibLaden(adresse);
|
||||
const dokument = await PDFLib.PDFDocument.load(bytes);
|
||||
const formular = dokument.getForm();
|
||||
for (const eintrag of bilder) {
|
||||
const seite = dokument.getPage(eintrag.seite - 1);
|
||||
const jpeg = await dokument.embedJpg(eintrag.foto.bytes);
|
||||
const [x1, y1, x2, y2] = eintrag.rechteck;
|
||||
const kastenBreite = Math.abs(x2 - x1);
|
||||
const kastenHoehe = Math.abs(y2 - y1);
|
||||
// Einpassen statt verzerren: das Seitenverhaeltnis des Fotos bleibt.
|
||||
const faktor = Math.min(kastenBreite / jpeg.width, kastenHoehe / jpeg.height);
|
||||
const breite = jpeg.width * faktor;
|
||||
const hoehe = jpeg.height * faktor;
|
||||
seite.drawImage(jpeg, {
|
||||
x: Math.min(x1, x2) + (kastenBreite - breite) / 2,
|
||||
y: Math.min(y1, y2) + (kastenHoehe - hoehe) / 2,
|
||||
width: breite,
|
||||
height: hoehe,
|
||||
});
|
||||
// Den Knopf aus der fertigen Kopie nehmen: seine Flaeche liegt ueber dem
|
||||
// Seiteninhalt und wuerde das Foto verdecken. Zu tun haette er dort auch
|
||||
// nichts mehr -- seine Aktion fuehrt kein Browser aus, und das Bild steht
|
||||
// jetzt in der Seite. Die Vorlage bleibt unberuehrt.
|
||||
try {
|
||||
const feld = formular.getFieldMaybe(eintrag.feldname);
|
||||
if (feld) formular.removeField(feld);
|
||||
} catch (fehler) {
|
||||
// Bleibt der Knopf liegen, ist das Foto verdeckt -- aber die Datei ist
|
||||
// heil. Das ist der bessere von zwei schlechten Ausgaengen.
|
||||
console.warn("Bildknopf liess sich nicht entfernen", fehler);
|
||||
}
|
||||
}
|
||||
return dokument.save();
|
||||
}
|
||||
|
||||
/* -- PDF ------------------------------------------------------------------- */
|
||||
|
||||
let pdfjsGeladen = null;
|
||||
@@ -244,6 +358,72 @@ async function pdfBetrachter(behaelter, seiten, url, basis) {
|
||||
start = null;
|
||||
});
|
||||
|
||||
/* Bildknoepfe: eigene Schaltflaeche darueber, denn Acrobats Aktion
|
||||
("buttonImportIcon") fuehrt kein Browser aus. Gesammelt wird, was beim
|
||||
Speichern in die Datei gestempelt werden soll. */
|
||||
const bilder = new Map();
|
||||
|
||||
const bildknoepfeAufsetzen = async (nurSeite) => {
|
||||
for (let nummer = 1; nummer <= dokument.numPages; nummer++) {
|
||||
if (nurSeite && nummer !== nurSeite) continue;
|
||||
const seite = await dokument.getPage(nummer);
|
||||
const annots = await seite.getAnnotations({ intent: "display" });
|
||||
for (const annot of annots) {
|
||||
const quelltext = (annot.actions?.Action || []).join(" ");
|
||||
if (!quelltext.includes("buttonImportIcon")) continue;
|
||||
const kasten = behaelter.querySelector(
|
||||
`section[data-annotation-id="${annot.id}"]`
|
||||
);
|
||||
if (!kasten || kasten.querySelector("[data-viewer-bildwahl]")) continue;
|
||||
kasten.classList.add("viewer__bildfeld");
|
||||
const knopf = document.createElement("label");
|
||||
knopf.className = "viewer__bildwahl";
|
||||
knopf.setAttribute("data-viewer-bildwahl", "");
|
||||
knopf.innerHTML =
|
||||
'<input type="file" accept="image/*" hidden>' +
|
||||
"<span>Bild einsetzen</span>";
|
||||
const feld = knopf.querySelector("input");
|
||||
feld.addEventListener("change", async () => {
|
||||
const datei = feld.files?.[0];
|
||||
if (!datei) return;
|
||||
try {
|
||||
const foto = await fotoAlsJpeg(datei);
|
||||
bilder.set(annot.id, {
|
||||
seite: nummer,
|
||||
rechteck: annot.rect,
|
||||
feldname: annot.fieldName,
|
||||
foto,
|
||||
});
|
||||
// Als eigenes Bild und nicht als Hintergrund: der Kasten traegt
|
||||
// eine Leinwand von pdf.js (das Aussehen des Knopfes aus dem PDF),
|
||||
// und die liegt ueber jedem Hintergrund.
|
||||
let vorschau = kasten.querySelector("[data-viewer-bildvorschau]");
|
||||
if (!vorschau) {
|
||||
vorschau = document.createElement("img");
|
||||
vorschau.setAttribute("data-viewer-bildvorschau", "");
|
||||
vorschau.alt = "";
|
||||
kasten.append(vorschau);
|
||||
}
|
||||
vorschau.src = foto.vorschau;
|
||||
kasten.classList.add("viewer__bildfeld--belegt");
|
||||
knopf.querySelector("span").textContent = "Anderes Bild";
|
||||
} catch (fehler) {
|
||||
window.tesm.showToast(fehler.message || "Bild nicht lesbar.", "danger");
|
||||
}
|
||||
});
|
||||
kasten.append(knopf);
|
||||
}
|
||||
}
|
||||
};
|
||||
// Die Knoepfe koennen erst auf eine gerenderte Anmerkungsebene -- die
|
||||
// entsteht je Seite, wenn sie sichtbar wird.
|
||||
eventBus.on("annotationlayerrendered", (ereignis) => {
|
||||
bildknoepfeAufsetzen(ereignis.pageNumber).catch((fehler) =>
|
||||
console.error("Bildfelder", fehler)
|
||||
);
|
||||
});
|
||||
await bildknoepfeAufsetzen();
|
||||
|
||||
return {
|
||||
hinein: () => {
|
||||
viewer.currentScale = Math.min(MAX_ZOOM, viewer.currentScale * 1.2);
|
||||
@@ -254,8 +434,16 @@ async function pdfBetrachter(behaelter, seiten, url, basis) {
|
||||
anpassen: () => {
|
||||
viewer.currentScaleValue = "page-width";
|
||||
},
|
||||
/** Das ausgefuellte Formular als Bytes -- pdf.js schreibt die Werte hinein. */
|
||||
speichern: () => dokument.saveDocument(),
|
||||
/** Das ausgefuellte Formular als Bytes.
|
||||
*
|
||||
* pdf.js schreibt die Feldwerte; gewaehlte Fotos kommen danach mit
|
||||
* pdf-lib hinein -- pdf.js kann nichts in ein PDF zeichnen.
|
||||
*/
|
||||
speichern: async (pdflibAdresse) => {
|
||||
const bytes = await dokument.saveDocument();
|
||||
if (!bilder.size) return bytes;
|
||||
return fotosEinsetzen(bytes, [...bilder.values()], pdflibAdresse);
|
||||
},
|
||||
/** Wurde ueberhaupt etwas eingetragen? */
|
||||
veraendert: () => {
|
||||
const s = dokument.annotationStorage;
|
||||
@@ -430,7 +618,7 @@ export function initFilePreview(wurzel = document) {
|
||||
const vorher = jetzt.textContent;
|
||||
jetzt.textContent = "Speichern ...";
|
||||
try {
|
||||
const bytes = await pdf.speichern();
|
||||
const bytes = await pdf.speichern(rumpf.dataset.viewerPdflib || "");
|
||||
const daten = new FormData();
|
||||
daten.append("pfad", aktuell.pfad);
|
||||
daten.append("ordner", ordnerFeld.value.trim());
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
pdf-lib 1.17.1 -- https://github.com/Hopding/pdf-lib (MIT, siehe LICENSE)
|
||||
|
||||
Aus dem CDN-Bau "pdf-lib.min.js" (UMD, setzt window.PDFLib).
|
||||
|
||||
Wofuer: pdf.js kann Formulare ausfuellen, aber nichts in ein PDF zeichnen. Fuer
|
||||
den Bildknopf in Formularen (Acrobats "buttonImportIcon", das kein Browser
|
||||
ausfuehren kann) wird das gewaehlte Foto damit in das Feld gestempelt.
|
||||
|
||||
Geladen wird die Datei erst, wenn wirklich ein Bild eingesetzt wird.
|
||||
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2019 Andrew Dillon
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
@@ -0,0 +1 @@
|
||||
1.17.1
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?e(exports):"function"==typeof define&&define.amd?define(["exports"],e):e((t=t||self).PDFLib={})}(this,(function(t){"use strict";
|
||||
/*! *****************************************************************************
|
||||
Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
Licensed under the Apache License, Version 2.0 (the "License"); you may not use
|
||||
this file except in compliance with the License. You may obtain a copy of the
|
||||
License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
|
||||
WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
|
||||
MERCHANTABLITY OR NON-INFRINGEMENT.
|
||||
|
||||
See the Apache Version 2.0 License for specific language governing permissions
|
||||
and limitations under the License.
|
||||
***************************************************************************** */var e=function(t,n){return(e=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(t,e){t.__proto__=e}||function(t,e){for(var n in e)e.hasOwnProperty(n)&&(t[n]=e[n])})(t,n)};function n(t,n){function r(){this.constructor=t}e(t,n),t.prototype=null===n?Object.create(n):(r.prototype=n.prototype,new r)}var r=function(){return(r=Object.assign||function(t){for(var e,n=1,r=arguments.length;n<r;n++)for(var i in e=arguments[n])Object.prototype.hasOwnProperty.call(e,i)&&(t[i]=e[i]);return t}).apply(this,arguments)};function i(t,e,n,r){return new(n||(n=Promise))((function(i,o){function a(t){try{l(r.next(t))}catch(t){o(t)}}function s(t){try{l(r.throw(t))}catch(t){o(t)}}function l(t){var e;t.done?i(t.value):(e=t.value,e instanceof n?e:new n((function(t){t(e)}))).then(a,s)}l((r=r.apply(t,e||[])).next())}))}function o(t,e){var n,r,i,o,a={label:0,sent:function(){if(1&i[0])throw i[1];return i[1]},trys:[],ops:[]};return o={next:s(0),throw:s(1),return:s(2)},"function"==typeof Symbol&&(o[Symbol.iterator]=function(){return this}),o;function s(o){return function(s){return function(o){if(n)throw new TypeError("Generator is already executing.");for(;a;)try{if(n=1,r&&(i=2&o[0]?r.return:o[0]?r.throw||((i=r.return)&&i.call(r),0):r.next)&&!(i=i.call(r,o[1])).done)return i;switch(r=0,i&&(o=[2&o[0],i.value]),o[0]){case 0:case 1:i=o;break;case 4:return a.label++,{value:o[1],done:!1};case 5:a.label++,r=o[1],o=[0];continue;case 7:o=a.ops.pop(),a.trys.pop();continue;default:if(!(i=a.trys,(i=i.length>0&&i[i.length-1])||6!==o[0]&&2!==o[0])){a=0;continue}if(3===o[0]&&(!i||o[1]>i[0]&&o[1]<i[3])){a.label=o[1];break}if(6===o[0]&&a.label<i[1]){a.label=i[1],i=o;break}if(i&&a.label<i[2]){a.label=i[2],a.ops.push(o);break}i[2]&&a.ops.pop(),a.trys.pop();continue}o=e.call(t,a)}catch(t){o=[6,t],r=0}finally{n=i=0}if(5&o[0])throw o[1];return{value:o[0]?o[1]:void 0,done:!0}}([o,s])}}}function a(){for(var t=0,e=0,n=arguments.length;e<n;e++)t+=arguments[e].length;var r=Array(t),i=0;for(e=0;e<n;e++)for(var o=arguments[e],a=0,s=o.length;a<s;a++,i++)r[i]=o[a];return r}for(var s="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",l=new Uint8Array(256),h=0;h<s.length;h++)l[s.charCodeAt(h)]=h;var u,c=function(t){for(var e="",n=t.length,r=0;r<n;r+=3)e+=s[t[r]>>2],e+=s[(3&t[r])<<4|t[r+1]>>4],e+=s[(15&t[r+1])<<2|t[r+2]>>6],e+=s[63&t[r+2]];return n%3==2?e=e.substring(0,e.length-1)+"=":n%3==1&&(e=e.substring(0,e.length-2)+"=="),e},d=function(t){var e,n,r,i,o,a=.75*t.length,s=t.length,h=0;"="===t[t.length-1]&&(a--,"="===t[t.length-2]&&a--);var u=new Uint8Array(a);for(e=0;e<s;e+=4)n=l[t.charCodeAt(e)],r=l[t.charCodeAt(e+1)],i=l[t.charCodeAt(e+2)],o=l[t.charCodeAt(e+3)],u[h++]=n<<2|r>>4,u[h++]=(15&r)<<4|i>>2,u[h++]=(3&i)<<6|63&o;return u},f=/^(data)?:?([\w\/\+]+)?;?(charset=[\w-]+|base64)?.*,/i,p=function(t){var e=t.trim(),n=e.substring(0,100).match(f);if(!n)return d(e);var r=n[0],i=e.substring(r.length);return d(i)},g=function(t){return t.charCodeAt(0)},v=function(t){return t.codePointAt(0)},y=function(t,e){return x(t.toString(16),e,"0").toUpperCase()},m=function(t){return y(t,2)},b=function(t){return String.fromCharCode(t)},w=function(t){return b(parseInt(t,16))},x=function(t,e,n){for(var r="",i=0,o=e-t.length;i<o;i++)r+=n;return r+t},k=function(t,e,n){for(var r=t.length,i=0;i<r;i++)e[n++]=t.charCodeAt(i);return r},F=function(t){return t.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")},S=function(t){return t.replace(/\t|\u0085|\u2028|\u2029/g," ").replace(/[\b\v]/g,"")},C=["\\n","\\f","\\r","\\u000B"],A=function(t){return/^[\n\f\r\u000B]$/.test(t)},T=function(t){return t.split(/[\n\f\r\u000B]/)},P=function(t){return t.replace(/[\n\f\r\u000B]/g," ")},z=function(t,e){var n,r=t.charCodeAt(e),i=e+1,o=1;return r>=55296&&r<=56319&&t.length>i&&(n=t.charCodeAt(i))>=56320&&n<=57343&&(o=2),[t.slice(e,e+o),o]},R=function(t){for(var e=[],n=0,r=t.length;n<r;){var i=z(t,n),o=i[0],a=i[1];e.push(o),n+=a}return e},O=function(t,e,n,r){for(var i=function(t){for(var e=C.join("|"),n=["$"],r=0,i=t.length;r<i;r++){var o=t[r];if(A(o))throw new TypeError("`wordBreak` must not include "+e);n.push(""===o?".":F(o))}var a=n.join("|");return new RegExp("("+e+")|((.*?)("+a+"))","gm")}(e),o=S(t).match(i),a="",s=0,l=[],h=function(){""!==a&&l.push(a),a="",s=0},u=0,c=o.length;u<c;u++){var d=o[u];if(A(d))h();else{var f=r(d);s+f>n&&h(),a+=d,s+=f}}return h(),l},D=/^D:(\d\d\d\d)(\d\d)?(\d\d)?(\d\d)?(\d\d)?(\d\d)?([+\-Z])?(\d\d)?'?(\d\d)?'?$/,B=function(t){var e=t.match(D);if(e){var n=e[1],r=e[2],i=void 0===r?"01":r,o=e[3],a=void 0===o?"01":o,s=e[4],l=void 0===s?"00":s,h=e[5],u=void 0===h?"00":h,c=e[6],d=void 0===c?"00":c,f=e[7],p=void 0===f?"Z":f,g=e[8],v=void 0===g?"00":g,y=e[9];return new Date(n+"-"+i+"-"+a+"T"+l+":"+u+":"+d+("Z"===p?"Z":""+p+v+":"+(void 0===y?"00":y)))}},N=function(t,e){for(var n,r,i=0;i<t.length;){var o=t.substring(i).match(e);if(!o)return{match:r,pos:i};r=o,i+=(null!==(n=o.index)&&void 0Line truncated
|
||||
//# sourceMappingURL=pdf-lib.min.js.map
|
||||
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
||||
|
||||
[project]
|
||||
name = "tesm-licensing"
|
||||
version = "2.3.0"
|
||||
version = "2.3.1"
|
||||
description = "Ed25519-basiertes Lizenz- und Aktivierungsprotokoll fuer TESM und TESM-Lizenzserver"
|
||||
requires-python = ">=3.11"
|
||||
dependencies = ["cryptography>=42"]
|
||||
|
||||
Reference in new issue
Block a user