add glossary, remove extension
Browse files- src/.gitignore +2 -1
- src/01_setup/glossar.qmd +15 -6
- src/_extensions/shafayetShafee/downloadthis/_extension.yml +0 -8
- src/_extensions/shafayetShafee/downloadthis/downloadthis.lua +0 -121
- src/_extensions/shafayetShafee/downloadthis/puremagic.lua +0 -735
- src/_extensions/shafayetShafee/downloadthis/resources/css/downloadthis.css +0 -13
- src/_quarto.yml +2 -2
- src/index.qmd +1 -1
src/.gitignore
CHANGED
@@ -1,2 +1,3 @@
|
|
1 |
/.quarto/
|
2 |
-
pdf
|
|
|
|
1 |
/.quarto/
|
2 |
+
pdf
|
3 |
+
_extensions
|
src/01_setup/glossar.qmd
CHANGED
@@ -1,6 +1,5 @@
|
|
1 |
In der Welt des Internets und der Computerwissenschaften gibt es eine Vielzahl von Begriffen und Konzepten, die für das Verständnis und die Durchführung von Webscraping-Projekten relevant sind.
|
2 |
|
3 |
-
|
4 |
## A wie Asynchrones Scraping
|
5 |
* AJAX (Asynchronous JavaScript and XML): Eine Gruppe von Webentwicklungstechniken, die für die Erstellung asynchroner Webanwendungen verwendet wird, was bedeutet, dass Webseiten dynamisch ohne Neuladen aktualisiert werden können.
|
6 |
* API (Application Programming Interface): Eine Sammlung von Definitionen und Protokollen, die es ermöglichen, dass Softwareanwendungen miteinander kommunizieren können. Wird oft verwendet, um Daten legal und effizient zu extrahieren.
|
@@ -19,17 +18,17 @@ In der Welt des Internets und der Computerwissenschaften gibt es eine Vielzahl v
|
|
19 |
|
20 |
## D wie DOM
|
21 |
* Data Pipeline: Ein Prozess oder System zum Sammeln, Transformieren und Laden von Daten von einer Quelle zu einem Ziel, oft im Webscraping-Kontext.
|
22 |
-
* Dieses Glossar deckt einige der grundlegenden Begriffe ab, die beim Webscraping verwendet werden. Es gibt natürlich viele mehr spezialisierte Begriffe und Werkzeuge, aber dies sollte einen guten Überblick bieten.
|
23 |
* DOM (Document Object Model): Eine Programmierschnittstelle für HTML- und XML-Dokumente, die eine strukturierte Darstellung der Dokumente ermöglicht, um sie zu manipulieren und zu durchsuchen.
|
24 |
* DOM Manipulation: Der Vorgang, das Document Object Model einer Webseite zu ändern oder zu untersuchen, um Daten zu extrahieren oder Interaktionen zu simulieren.
|
25 |
* Dynamic Content: Inhalte auf einer Webseite, die erst nach dem Laden der Seite durch JavaScript generiert oder verändert werden, erfordern oft spezielle Scraping-Techniken.
|
26 |
|
27 |
## E wie Element
|
28 |
* Elastic IP: Eine statische IP-Adresse, die in der Cloud-Computing-Umgebung verwendet wird und bei Bedarf an Instanzen zugewiesen werden kann, nützlich für langfristige Scraping-Projekte.
|
29 |
-
* Element: Ein einzelner Teil eines HTML- oder XML-Dokuments, wie z.B. ein
|
30 |
* Encoding: Bezieht sich auf die Methode, mit der Daten in einem Webscraping-Kontext dargestellt und interpretiert werden, z.B. UTF-8.
|
31 |
|
32 |
## F wie Fingerprinting
|
|
|
33 |
* Fiddler: Ein Web-Debugger, der verwendet werden kann, um HTTP-Verkehr zu überwachen, was beim Debuggen von Webscraping-Skripten hilfreich sein kann.
|
34 |
* Fingerprinting: Der Prozess der Erkennung und Identifizierung von Anfragen durch Analyse von Browser- und Benutzereigenschaften, um anti-scraping-Maßnahmen zu setzen.
|
35 |
* Frame Handling: Umgang mit Frames oder IFrames auf Webseiten, die separate HTML-Dokumente enthalten, die gesondert gescraped werden müssen.
|
@@ -41,7 +40,6 @@ In der Welt des Internets und der Computerwissenschaften gibt es eine Vielzahl v
|
|
41 |
|
42 |
## H wie Headless
|
43 |
* Headless Browser: Ein Webbrowser ohne grafische Benutzeroberfläche, der von Skripten gesteuert wird, um Webseiten wie ein normaler Browser zu rendern, aber ohne Sichtbarkeit.
|
44 |
-
* Hier sind einige zusätzliche Begriffe, die in das Webscraping-Glossar aufgenommen werden können:
|
45 |
* Honeypot: Eine Falle, die von Websites platziert wird, um automatische Scraping- oder Hacking-Versuche zu erkennen und zu blockieren.
|
46 |
* HTML5: Die neueste Version von HTML, die viele neue Elemente und Attribute einführt, die beim Scraping berücksichtigt werden müssen.
|
47 |
* HTTP (Hypertext Transfer Protocol): Das Protokoll, das für die Übertragung von Webseiten und Daten über das Internet verwendet wird.
|
@@ -88,6 +86,7 @@ In der Welt des Internets und der Computerwissenschaften gibt es eine Vielzahl v
|
|
88 |
* Page Object Model: Ein Designmuster bei der Automatisierung, das die Repräsentation von Webseiten als Objekte mit bestimmten Methoden und Eigenschaften erlaubt.
|
89 |
* Pagination: Eine Technik, Inhalte auf mehreren Seiten zu verteilen, anstatt alles auf einer einzigen Seite anzuzeigen. Um die Darstellung großer Datenmengen zu verwalten, indem die Ergebnisse in kleinere, überschaubare Teile aufgeteilt werden. Viele Websites verwenden ein konsistentes Muster in ihren URLs, um auf verschiedene Seiten zu verlinken (z.B. ?page=2). Manche Seiten laden Inhalte dynamisch, was bedeutet, dass ein Scraper möglicherweise JavaScript ausführen muss, um die nächsten Seiteninhalte zu laden.
|
90 |
* Parser: Ein Programm, das eine Struktur (wie HTML) in eine andere Form, die für die Verarbeitung geeignet ist, umwandelt.
|
|
|
91 |
* PhantomJS: War ein skriptbares Headless Webkit, das für Webscraping genutzt wurde; jedoch ist es seit 2018 nicht mehr weiterentwickelt.
|
92 |
* Proxy: Ein Server, der als Mittelsmann zwischen einem Client und dem Internet fungiert. Kann verwendet werden, um Anfragen zu maskieren oder den Standort des Scrapers zu verschleiern.
|
93 |
* Puppeteer: Eine Node.js-Bibliothek, die eine High-Level API zum Steuern von Headless Chrome oder Chromium über das DevTools-Protokoll bietet, oft für Webscraping verwendet.
|
@@ -100,7 +99,10 @@ In der Welt des Internets und der Computerwissenschaften gibt es eine Vielzahl v
|
|
100 |
* Regex (Regular Expressions): Mächtige Suchmuster, die verwendet werden können, um spezifische Textmuster in Webseiten zu finden und zu extrahieren.
|
101 |
* Request Headers: Metadaten, die mit jeder HTTP-Anfrage gesendet werden, können manipuliert werden, um wie ein legitimer Benutzer zu erscheinen.
|
102 |
* Request: Ein Modul in Python, das es ermöglicht, HTTP-Anfragen zu senden. Wird oft im Zusammenhang mit Webscraping verwendet.
|
|
|
|
|
103 |
* Robots.txt: Eine Datei, die von Webseitenbetreibern verwendet wird, um zu definieren, welche Teile ihrer Website von Bots (wie Webscrapern) durchsucht werden dürfen.
|
|
|
104 |
|
105 |
## S wie Selenium
|
106 |
* Scraper: Ein Skript oder Programm, das Daten von Websites extrahiert.
|
@@ -108,6 +110,13 @@ In der Welt des Internets und der Computerwissenschaften gibt es eine Vielzahl v
|
|
108 |
* Selenium: Ein Tool, das hauptsächlich für das Testen von Web-Anwendungen verwendet wird, aber auch für Webscraping, da es eine Browser-Automatisierung bietet, um mit JavaScript-reichen Seiten umzugehen.
|
109 |
* Spider: Ein spezifischer Begriff für ein Programm oder Modul, das durch Webseiten navigiert und Daten sammelt, oft in Verbindung mit Frameworks wie Scrapy verwendet.
|
110 |
* Splash: Eine JavaScript-Rendering-Service, der oft mit Scrapy verwendet wird, um dynamische Webseiten zu rendern.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
111 |
|
112 |
## T wie Throttling
|
113 |
* Text Mining: Der Prozess der Extraktion von nützlichem Wissen aus Text, oft nach dem Scraping von Textinhalten.
|
@@ -138,6 +147,6 @@ In der Welt des Internets und der Computerwissenschaften gibt es eine Vielzahl v
|
|
138 |
## Y wie Yield
|
139 |
* Yield: In Python eine Schlüsselwörter, das in Generator-Funktionen verwendet wird, um ein Ergebnis zurückzugeben und die Ausführung zu pausieren, bis der nächste Wert angefordert wird, nützlich in Webscraping für effizientes Arbeiten mit großen Datenmengen.
|
140 |
|
141 |
-
## Z wie
|
142 |
* Zope: Ein Python-Web-Framework, das manchmal im Zusammenhang mit Webscraping erwähnt wird, da es Tools und Bibliotheken bietet, die auch in Scraping-Projekten nützlich sein können.
|
143 |
-
* Zyte (ehemals Scrapinghub) ist ein führendes Unternehmen im Bereich der Web-Datenextraktion und bietet eine Vielzahl von Tools und Diensten, die Webscraping vereinfachen und skalieren.
|
|
|
1 |
In der Welt des Internets und der Computerwissenschaften gibt es eine Vielzahl von Begriffen und Konzepten, die für das Verständnis und die Durchführung von Webscraping-Projekten relevant sind.
|
2 |
|
|
|
3 |
## A wie Asynchrones Scraping
|
4 |
* AJAX (Asynchronous JavaScript and XML): Eine Gruppe von Webentwicklungstechniken, die für die Erstellung asynchroner Webanwendungen verwendet wird, was bedeutet, dass Webseiten dynamisch ohne Neuladen aktualisiert werden können.
|
5 |
* API (Application Programming Interface): Eine Sammlung von Definitionen und Protokollen, die es ermöglichen, dass Softwareanwendungen miteinander kommunizieren können. Wird oft verwendet, um Daten legal und effizient zu extrahieren.
|
|
|
18 |
|
19 |
## D wie DOM
|
20 |
* Data Pipeline: Ein Prozess oder System zum Sammeln, Transformieren und Laden von Daten von einer Quelle zu einem Ziel, oft im Webscraping-Kontext.
|
|
|
21 |
* DOM (Document Object Model): Eine Programmierschnittstelle für HTML- und XML-Dokumente, die eine strukturierte Darstellung der Dokumente ermöglicht, um sie zu manipulieren und zu durchsuchen.
|
22 |
* DOM Manipulation: Der Vorgang, das Document Object Model einer Webseite zu ändern oder zu untersuchen, um Daten zu extrahieren oder Interaktionen zu simulieren.
|
23 |
* Dynamic Content: Inhalte auf einer Webseite, die erst nach dem Laden der Seite durch JavaScript generiert oder verändert werden, erfordern oft spezielle Scraping-Techniken.
|
24 |
|
25 |
## E wie Element
|
26 |
* Elastic IP: Eine statische IP-Adresse, die in der Cloud-Computing-Umgebung verwendet wird und bei Bedarf an Instanzen zugewiesen werden kann, nützlich für langfristige Scraping-Projekte.
|
27 |
+
* Element: Ein einzelner Teil eines HTML- oder XML-Dokuments, wie z.B. ein `<div>` oder `<p>`-Tag, aus dem Daten extrahiert werden können.
|
28 |
* Encoding: Bezieht sich auf die Methode, mit der Daten in einem Webscraping-Kontext dargestellt und interpretiert werden, z.B. UTF-8.
|
29 |
|
30 |
## F wie Fingerprinting
|
31 |
+
* Feed bezieht sich in der Webtechnologie auf eine Quelle von Inhalten, die regelmäßig aktualisiert werden und in einem standardisierten Format wie RSS, Atom oder JSON Feed präsentiert werden.
|
32 |
* Fiddler: Ein Web-Debugger, der verwendet werden kann, um HTTP-Verkehr zu überwachen, was beim Debuggen von Webscraping-Skripten hilfreich sein kann.
|
33 |
* Fingerprinting: Der Prozess der Erkennung und Identifizierung von Anfragen durch Analyse von Browser- und Benutzereigenschaften, um anti-scraping-Maßnahmen zu setzen.
|
34 |
* Frame Handling: Umgang mit Frames oder IFrames auf Webseiten, die separate HTML-Dokumente enthalten, die gesondert gescraped werden müssen.
|
|
|
40 |
|
41 |
## H wie Headless
|
42 |
* Headless Browser: Ein Webbrowser ohne grafische Benutzeroberfläche, der von Skripten gesteuert wird, um Webseiten wie ein normaler Browser zu rendern, aber ohne Sichtbarkeit.
|
|
|
43 |
* Honeypot: Eine Falle, die von Websites platziert wird, um automatische Scraping- oder Hacking-Versuche zu erkennen und zu blockieren.
|
44 |
* HTML5: Die neueste Version von HTML, die viele neue Elemente und Attribute einführt, die beim Scraping berücksichtigt werden müssen.
|
45 |
* HTTP (Hypertext Transfer Protocol): Das Protokoll, das für die Übertragung von Webseiten und Daten über das Internet verwendet wird.
|
|
|
86 |
* Page Object Model: Ein Designmuster bei der Automatisierung, das die Repräsentation von Webseiten als Objekte mit bestimmten Methoden und Eigenschaften erlaubt.
|
87 |
* Pagination: Eine Technik, Inhalte auf mehreren Seiten zu verteilen, anstatt alles auf einer einzigen Seite anzuzeigen. Um die Darstellung großer Datenmengen zu verwalten, indem die Ergebnisse in kleinere, überschaubare Teile aufgeteilt werden. Viele Websites verwenden ein konsistentes Muster in ihren URLs, um auf verschiedene Seiten zu verlinken (z.B. ?page=2). Manche Seiten laden Inhalte dynamisch, was bedeutet, dass ein Scraper möglicherweise JavaScript ausführen muss, um die nächsten Seiteninhalte zu laden.
|
88 |
* Parser: Ein Programm, das eine Struktur (wie HTML) in eine andere Form, die für die Verarbeitung geeignet ist, umwandelt.
|
89 |
+
* Parsing ist der Prozess der Analyse und Interpretation von Datenstrukturen oder Text, um sie in eine andere, oft einfacher zu verarbeitende Form zu bringen.
|
90 |
* PhantomJS: War ein skriptbares Headless Webkit, das für Webscraping genutzt wurde; jedoch ist es seit 2018 nicht mehr weiterentwickelt.
|
91 |
* Proxy: Ein Server, der als Mittelsmann zwischen einem Client und dem Internet fungiert. Kann verwendet werden, um Anfragen zu maskieren oder den Standort des Scrapers zu verschleiern.
|
92 |
* Puppeteer: Eine Node.js-Bibliothek, die eine High-Level API zum Steuern von Headless Chrome oder Chromium über das DevTools-Protokoll bietet, oft für Webscraping verwendet.
|
|
|
99 |
* Regex (Regular Expressions): Mächtige Suchmuster, die verwendet werden können, um spezifische Textmuster in Webseiten zu finden und zu extrahieren.
|
100 |
* Request Headers: Metadaten, die mit jeder HTTP-Anfrage gesendet werden, können manipuliert werden, um wie ein legitimer Benutzer zu erscheinen.
|
101 |
* Request: Ein Modul in Python, das es ermöglicht, HTTP-Anfragen zu senden. Wird oft im Zusammenhang mit Webscraping verwendet.
|
102 |
+
* Request Parameter sind Daten, die in einer HTTP-Anfrage an den Server übergeben werden, um zusätzliche Informationen zu liefern oder die Anfrage zu spezifizieren. Teil der URL nach einem `?`, z.B. `?id=123&name=test`.
|
103 |
+
* REST API (Representational State Transfer Application Programming Interface) ist ein Architekturstil für das Design von vernetzten Anwendungen. Es nutzt HTTP-Methoden für CRUD-Operationen (Create, Read, Update, Delete) und ist darauf ausgelegt, stateless zu sein, was bedeutet, dass jede Anfrage alle Informationen enthält, die der Server benötigt, um sie zu verarbeiten.
|
104 |
* Robots.txt: Eine Datei, die von Webseitenbetreibern verwendet wird, um zu definieren, welche Teile ihrer Website von Bots (wie Webscrapern) durchsucht werden dürfen.
|
105 |
+
* RSS (Really Simple Syndication) ist ein XML-basierter Formatstandard, der verwendet wird, um häufig aktualisierte Inhalte wie Blogeinträge, Nachrichten oder Podcasts zu veröffentlichen. RSS ist trotz der Zunahme anderer Technologien wie APIs für die Content-Syndikation immer noch weit verbreitet, besonders in Nischen für fortlaufende, zeitnahe Informationen.
|
106 |
|
107 |
## S wie Selenium
|
108 |
* Scraper: Ein Skript oder Programm, das Daten von Websites extrahiert.
|
|
|
110 |
* Selenium: Ein Tool, das hauptsächlich für das Testen von Web-Anwendungen verwendet wird, aber auch für Webscraping, da es eine Browser-Automatisierung bietet, um mit JavaScript-reichen Seiten umzugehen.
|
111 |
* Spider: Ein spezifischer Begriff für ein Programm oder Modul, das durch Webseiten navigiert und Daten sammelt, oft in Verbindung mit Frameworks wie Scrapy verwendet.
|
112 |
* Splash: Eine JavaScript-Rendering-Service, der oft mit Scrapy verwendet wird, um dynamische Webseiten zu rendern.
|
113 |
+
* Status Codes sind numerische Codes, die in HTTP-Antworten zurückgegeben werden, um den Status der Anfrage zu kommunizieren.
|
114 |
+
* 1xx (Informational): Anfrage wird verarbeitet, z.B. 100 Continue.
|
115 |
+
* 2xx (Success): Anfrage erfolgreich, z.B. 200 OK, 201 Created.
|
116 |
+
* 3xx (Redirection): Weitere Aktionen sind erforderlich, z.B. 301 Moved Permanently, 302 Found.
|
117 |
+
* 4xx (Client Error): Anfrage kann nicht verarbeitet werden, da die Anfrage fehlerhaft ist, z.B. 400 Bad Request, 404 Not Found.
|
118 |
+
* 5xx (Server Error): Der Server hat die Anfrage nicht erfüllen können, z.B. 500 Internal Server Error, 503 Service Unavailable.
|
119 |
+
* Stream bezeichnet den kontinuierlichen Fluss von Daten, oft in Echtzeit, wie bei Live-Video oder Datenanalyse, und ermöglicht die sofortige Verarbeitung und Übertragung von Informationen. Streaming-Technologien nutzen Protokolle und Plattformen, um Daten effizient von Quellen zu Konsumenten zu leiten, sei es für Multimedia oder Datenverarbeitung.
|
120 |
|
121 |
## T wie Throttling
|
122 |
* Text Mining: Der Prozess der Extraktion von nützlichem Wissen aus Text, oft nach dem Scraping von Textinhalten.
|
|
|
147 |
## Y wie Yield
|
148 |
* Yield: In Python eine Schlüsselwörter, das in Generator-Funktionen verwendet wird, um ein Ergebnis zurückzugeben und die Ausführung zu pausieren, bis der nächste Wert angefordert wird, nützlich in Webscraping für effizientes Arbeiten mit großen Datenmengen.
|
149 |
|
150 |
+
## Z wie Zyte
|
151 |
* Zope: Ein Python-Web-Framework, das manchmal im Zusammenhang mit Webscraping erwähnt wird, da es Tools und Bibliotheken bietet, die auch in Scraping-Projekten nützlich sein können.
|
152 |
+
* Zyte (ehemals Scrapinghub) ist ein führendes Unternehmen im Bereich der Web-Datenextraktion und bietet eine Vielzahl von Tools und Diensten, die Webscraping vereinfachen und skalieren.
|
src/_extensions/shafayetShafee/downloadthis/_extension.yml
DELETED
@@ -1,8 +0,0 @@
|
|
1 |
-
title: Downloadthis
|
2 |
-
author: Shafayet Khan Shafee
|
3 |
-
version: 1.1.0
|
4 |
-
quarto-required: ">=1.2.0"
|
5 |
-
contributes:
|
6 |
-
shortcodes:
|
7 |
-
- downloadthis.lua
|
8 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/_extensions/shafayetShafee/downloadthis/downloadthis.lua
DELETED
@@ -1,121 +0,0 @@
|
|
1 |
-
--[[
|
2 |
-
MIT License
|
3 |
-
|
4 |
-
Copyright (c) 2023 Shafayet Khan Shafee
|
5 |
-
|
6 |
-
Permission is hereby granted, free of charge, to any person obtaining a copy
|
7 |
-
of this software and associated documentation files (the "Software"), to deal
|
8 |
-
in the Software without restriction, including without limitation the rights
|
9 |
-
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
10 |
-
copies of the Software, and to permit persons to whom the Software is
|
11 |
-
furnished to do so, subject to the following conditions:
|
12 |
-
|
13 |
-
The above copyright notice and this permission notice shall be included in all
|
14 |
-
copies or substantial portions of the Software.
|
15 |
-
|
16 |
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
17 |
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
18 |
-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
19 |
-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
20 |
-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
21 |
-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
22 |
-
SOFTWARE.
|
23 |
-
]]--
|
24 |
-
|
25 |
-
|
26 |
-
|
27 |
-
local str = pandoc.utils.stringify
|
28 |
-
--local p = quarto.log.output
|
29 |
-
|
30 |
-
local function ensureHtmlDeps()
|
31 |
-
quarto.doc.add_html_dependency({
|
32 |
-
name = "downloadthis",
|
33 |
-
version = "1.9.1",
|
34 |
-
stylesheets = {"resources/css/downloadthis.css"}
|
35 |
-
})
|
36 |
-
end
|
37 |
-
|
38 |
-
local function optional(arg, default)
|
39 |
-
if arg == nil or arg == ""
|
40 |
-
then
|
41 |
-
return default
|
42 |
-
else
|
43 |
-
return arg
|
44 |
-
end
|
45 |
-
end
|
46 |
-
|
47 |
-
function import(script)
|
48 |
-
local path = PANDOC_SCRIPT_FILE:match("(.*[/\\])")
|
49 |
-
package.path = path .. script .. ";" .. package.path
|
50 |
-
return require(script)
|
51 |
-
end
|
52 |
-
|
53 |
-
local puremagic = import("puremagic.lua")
|
54 |
-
|
55 |
-
return {
|
56 |
-
['downloadthis'] = function(args, kwargs, meta)
|
57 |
-
|
58 |
-
-- args and kwargs
|
59 |
-
local file_path = str(args[1])
|
60 |
-
local extension = "." .. file_path:match("[^.]+$")
|
61 |
-
local dname = optional(str(kwargs["dname"]), "file")
|
62 |
-
local dfilename = dname .. extension
|
63 |
-
local btn_label = " " .. optional(str(kwargs["label"]), "Download") .. " "
|
64 |
-
local btn_type = optional(str(kwargs["type"]), "default")
|
65 |
-
local icon = optional(str(kwargs["icon"]), "download")
|
66 |
-
local class = " " .. optional(str(kwargs["class"]), "")
|
67 |
-
local rand = "dnldts" .. str(math.random(1, 65000))
|
68 |
-
local id = optional(str(kwargs["id"]), rand)
|
69 |
-
-- reading files
|
70 |
-
local fh = io.open(file_path, "rb")
|
71 |
-
if not fh then
|
72 |
-
io.stderr:write("Cannot open file " ..
|
73 |
-
file_path ..
|
74 |
-
" | Skipping adding buttons\n")
|
75 |
-
return pandoc.Null()
|
76 |
-
else
|
77 |
-
local contents = fh:read("*all")
|
78 |
-
fh:close()
|
79 |
-
|
80 |
-
-- creating dataURI object
|
81 |
-
local b64_encoded = quarto.base64.encode(contents)
|
82 |
-
local mimetype = puremagic.via_path(file_path)
|
83 |
-
local data_uri = 'data:' .. mimetype .. ";base64," .. b64_encoded
|
84 |
-
|
85 |
-
-- js code taken from
|
86 |
-
-- https://github.com/fmmattioni/downloadthis/blob/master/R/utils.R#L59
|
87 |
-
local js = [[fetch('%s').then(res => res.blob()).then(blob => {
|
88 |
-
const downloadURL = window.URL.createObjectURL(blob);
|
89 |
-
const a = document.createElement('a');
|
90 |
-
document.body.appendChild(a);
|
91 |
-
a.href = downloadURL;
|
92 |
-
a.download = '%s'; a.click();
|
93 |
-
window.URL.revokeObjectURL(downloadURL);
|
94 |
-
document.body.removeChild(a);
|
95 |
-
});]]
|
96 |
-
|
97 |
-
local clicked = js:format(data_uri, dfilename)
|
98 |
-
|
99 |
-
-- creating button
|
100 |
-
local button =
|
101 |
-
"<button class=\"btn btn-" .. btn_type .. " downloadthis " ..
|
102 |
-
class .. "\"" ..
|
103 |
-
" id=\"" .. id .. "\"" ..
|
104 |
-
"><i class=\"bi bi-" .. icon .. "\"" .. "></i>" ..
|
105 |
-
btn_label ..
|
106 |
-
"</button>"
|
107 |
-
if quarto.doc.is_format("html:js") and quarto.doc.has_bootstrap()
|
108 |
-
then
|
109 |
-
ensureHtmlDeps()
|
110 |
-
return pandoc.RawInline('html',
|
111 |
-
"<a href=\"#" .. id .. "\"" ..
|
112 |
-
" onclick=\"" .. clicked .. "\">" .. button .. "</a>"
|
113 |
-
)
|
114 |
-
else
|
115 |
-
return pandoc.Null()
|
116 |
-
end
|
117 |
-
end
|
118 |
-
end
|
119 |
-
}
|
120 |
-
|
121 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/_extensions/shafayetShafee/downloadthis/puremagic.lua
DELETED
@@ -1,735 +0,0 @@
|
|
1 |
-
-- puremagic 1.0.1
|
2 |
-
-- Copyright (c) 2014 Will Bond <[email protected]>
|
3 |
-
-- Licensed under the MIT license.
|
4 |
-
|
5 |
-
|
6 |
-
function basename(path)
|
7 |
-
local basename_match = path:match('[/\\]([^/\\]+)$')
|
8 |
-
if basename_match then
|
9 |
-
return basename_match, nil
|
10 |
-
end
|
11 |
-
|
12 |
-
return path, nil
|
13 |
-
end
|
14 |
-
|
15 |
-
|
16 |
-
function extension(path)
|
17 |
-
path = path:lower()
|
18 |
-
local tar_match = path:match('%.(tar%.[^.]+)$')
|
19 |
-
if tar_match then
|
20 |
-
return tar_match
|
21 |
-
end
|
22 |
-
if path:sub(#path - 11, #path) == '.numbers.zip' then
|
23 |
-
return 'numbers.zip'
|
24 |
-
end
|
25 |
-
if path:sub(#path - 9, #path) == '.pages.zip' then
|
26 |
-
return 'pages.zip'
|
27 |
-
end
|
28 |
-
if path:sub(#path - 7, #path) == '.key.zip' then
|
29 |
-
return 'key.zip'
|
30 |
-
end
|
31 |
-
return path:match('%.([^.]+)$')
|
32 |
-
end
|
33 |
-
|
34 |
-
|
35 |
-
function in_table(value, list)
|
36 |
-
for i=1, #list do
|
37 |
-
if list[i] == value then
|
38 |
-
return true
|
39 |
-
end
|
40 |
-
end
|
41 |
-
return false
|
42 |
-
end
|
43 |
-
|
44 |
-
|
45 |
-
function string_to_bit_table(chars)
|
46 |
-
local output = {}
|
47 |
-
for char in chars:gmatch('.') do
|
48 |
-
local num = string.byte(char)
|
49 |
-
local bits = {0, 0, 0, 0, 0, 0, 0, 0}
|
50 |
-
for bit=8, 1, -1 do
|
51 |
-
if num > 0 then
|
52 |
-
bits[bit] = math.fmod(num, 2)
|
53 |
-
num = (num - bits[bit]) / 2
|
54 |
-
end
|
55 |
-
end
|
56 |
-
table.insert(output, bits)
|
57 |
-
end
|
58 |
-
return output
|
59 |
-
end
|
60 |
-
|
61 |
-
|
62 |
-
function bit_table_to_string(bits)
|
63 |
-
local output = {}
|
64 |
-
for i = 1, #bits do
|
65 |
-
local num = tonumber(table.concat(bits[i]), 2)
|
66 |
-
table.insert(output, string.format('%c', num))
|
67 |
-
end
|
68 |
-
return table.concat(output)
|
69 |
-
end
|
70 |
-
|
71 |
-
|
72 |
-
function bitwise_and(a, b)
|
73 |
-
local a_bytes = string_to_bit_table(a)
|
74 |
-
local b_bytes = string_to_bit_table(b)
|
75 |
-
|
76 |
-
local output = {}
|
77 |
-
for i = 1, #a_bytes do
|
78 |
-
local bits = {0, 0, 0, 0, 0, 0, 0, 0}
|
79 |
-
for j = 1, 8 do
|
80 |
-
if a_bytes[i][j] == 1 and b_bytes[i][j] == 1 then
|
81 |
-
bits[j] = 1
|
82 |
-
else
|
83 |
-
bits[j] = 0
|
84 |
-
end
|
85 |
-
end
|
86 |
-
table.insert(output, bits)
|
87 |
-
end
|
88 |
-
|
89 |
-
return bit_table_to_string(output)
|
90 |
-
end
|
91 |
-
|
92 |
-
|
93 |
-
-- Unpack a little endian byte string into an integer
|
94 |
-
function unpack_le(chars)
|
95 |
-
local bit_table = string_to_bit_table(chars)
|
96 |
-
-- Merge the bits into a string of 1s and 0s
|
97 |
-
local result = {}
|
98 |
-
for i=1, #bit_table do
|
99 |
-
result[#chars + 1 - i] = table.concat(bit_table[i])
|
100 |
-
end
|
101 |
-
return tonumber(table.concat(result), 2)
|
102 |
-
end
|
103 |
-
|
104 |
-
|
105 |
-
-- Unpack a big endian byte string into an integer
|
106 |
-
function unpack_be(chars)
|
107 |
-
local bit_table = string_to_bit_table(chars)
|
108 |
-
-- Merge the bits into a string of 1s and 0s
|
109 |
-
for i=1, #bit_table do
|
110 |
-
bit_table[i] = table.concat(bit_table[i])
|
111 |
-
end
|
112 |
-
return tonumber(table.concat(bit_table), 2)
|
113 |
-
end
|
114 |
-
|
115 |
-
|
116 |
-
-- Takes the first 4-8k of an EBML file and identifies if it is matroska or webm
|
117 |
-
-- and it it contains just video or just audio.
|
118 |
-
function ebml_parse(content)
|
119 |
-
local position = 1
|
120 |
-
local length = #content
|
121 |
-
|
122 |
-
local header_token, header_value, used_bytes = ebml_parse_section(content)
|
123 |
-
position = position + used_bytes
|
124 |
-
|
125 |
-
|
126 |
-
if header_token ~= '\x1AE\xDF\xA3' then
|
127 |
-
return nil, 'Unable to find EBML ID'
|
128 |
-
end
|
129 |
-
|
130 |
-
-- The matroska spec sets the default doctype to be 'matroska', however
|
131 |
-
-- many file specify this anyway. The other option is 'webm'.
|
132 |
-
local doctype = 'matroska'
|
133 |
-
if header_value['B\x82'] then
|
134 |
-
doctype = header_value['B\x82']
|
135 |
-
end
|
136 |
-
|
137 |
-
if doctype ~= 'matroska' and doctype ~= 'webm' then
|
138 |
-
return nil, 'Unknown EBML doctype'
|
139 |
-
end
|
140 |
-
|
141 |
-
local segment_position = nil
|
142 |
-
local track_position = nil
|
143 |
-
local has_video = false
|
144 |
-
local found_tracks = false
|
145 |
-
|
146 |
-
while position <= length do
|
147 |
-
local ebml_id, ebml_value, used_bytes = ebml_parse_section(content:sub(position, length))
|
148 |
-
position = position + used_bytes
|
149 |
-
|
150 |
-
-- Segment
|
151 |
-
if ebml_id == '\x18S\x80g' then
|
152 |
-
segment_position = position
|
153 |
-
end
|
154 |
-
|
155 |
-
-- Meta seek information
|
156 |
-
if ebml_id == '\x11M\x9Bt' then
|
157 |
-
-- Look for the seek info about the tracks token
|
158 |
-
for i, child in ipairs(ebml_value['M\xBB']) do
|
159 |
-
if child['S\xAB'] == '\x16T\xAEk' then
|
160 |
-
track_position = segment_position + unpack_be(child['S\xAC'])
|
161 |
-
position = track_position
|
162 |
-
break
|
163 |
-
end
|
164 |
-
end
|
165 |
-
end
|
166 |
-
|
167 |
-
-- Track
|
168 |
-
if ebml_id == '\x16T\xAEk' then
|
169 |
-
found_tracks = true
|
170 |
-
-- Scan through each track looking for video
|
171 |
-
for i, child in ipairs(ebml_value['\xAE']) do
|
172 |
-
-- Look to see if the track type is video
|
173 |
-
if unpack_be(child['\x83']) == 1 then
|
174 |
-
has_video = true
|
175 |
-
break
|
176 |
-
end
|
177 |
-
end
|
178 |
-
break
|
179 |
-
end
|
180 |
-
end
|
181 |
-
|
182 |
-
if found_tracks and not has_video then
|
183 |
-
if doctype == 'matroska' then
|
184 |
-
return 'audio/x-matroska'
|
185 |
-
else
|
186 |
-
return 'audio/webm'
|
187 |
-
end
|
188 |
-
end
|
189 |
-
|
190 |
-
if doctype == 'matroska' then
|
191 |
-
return 'video/x-matroska'
|
192 |
-
else
|
193 |
-
return 'video/webm'
|
194 |
-
end
|
195 |
-
end
|
196 |
-
|
197 |
-
|
198 |
-
-- Parses a section of an EBML document, returning the EBML ID at the beginning,
|
199 |
-
-- plus the value as a table with child EBML IDs as keys and the number of
|
200 |
-
-- bytes from the content that contained the ID and value
|
201 |
-
function ebml_parse_section(content)
|
202 |
-
local ebml_id, element_length, used_bytes = ebml_id_and_length(content)
|
203 |
-
|
204 |
-
-- Don't parse the segment since it is the whole file!
|
205 |
-
if ebml_id == '\x18\x53\x80\x67' then
|
206 |
-
return ebml_id, nil, used_bytes
|
207 |
-
end
|
208 |
-
|
209 |
-
local ebml_value = content:sub(used_bytes + 1, used_bytes + element_length)
|
210 |
-
used_bytes = used_bytes + element_length
|
211 |
-
|
212 |
-
-- We always parse the return value of level 0/1 elements
|
213 |
-
local recursive_parse = false
|
214 |
-
if #ebml_id == 4 then
|
215 |
-
recursive_parse = true
|
216 |
-
|
217 |
-
-- We need Seek information
|
218 |
-
elseif ebml_id == '\x4D\xBB' then
|
219 |
-
recursive_parse = true
|
220 |
-
|
221 |
-
-- We want the top-level of TrackEntry to grab the TrackType
|
222 |
-
elseif ebml_id == '\xAE' then
|
223 |
-
recursive_parse = true
|
224 |
-
end
|
225 |
-
|
226 |
-
if recursive_parse then
|
227 |
-
local buffer = ebml_value
|
228 |
-
ebml_value = {}
|
229 |
-
|
230 |
-
-- Track which child entries have been converted to an array
|
231 |
-
local array_children = {}
|
232 |
-
|
233 |
-
while #buffer > 0 do
|
234 |
-
local child_ebml_id, child_ebml_value, child_used_bytes = ebml_parse_section(buffer)
|
235 |
-
|
236 |
-
if array_children[child_ebml_id] then
|
237 |
-
table.insert(ebml_value[child_ebml_id], child_ebml_value)
|
238 |
-
|
239 |
-
-- Single values are just stores by themselves
|
240 |
-
elseif ebml_value[child_ebml_id] == nil then
|
241 |
-
-- Force seek info and tracks to be arrays even if there is only one
|
242 |
-
if child_ebml_id == 'M\xBB' or child_ebml_id == '\xAE' then
|
243 |
-
child_ebml_value = {child_ebml_value}
|
244 |
-
array_children[child_ebml_id] = true
|
245 |
-
end
|
246 |
-
ebml_value[child_ebml_id] = child_ebml_value
|
247 |
-
|
248 |
-
-- If there is already a value for the ID, turn it into a table
|
249 |
-
else
|
250 |
-
ebml_value[child_ebml_id] = {ebml_value[child_ebml_id], child_ebml_value}
|
251 |
-
array_children[child_ebml_id] = true
|
252 |
-
end
|
253 |
-
|
254 |
-
-- Move past the part we've parsed
|
255 |
-
buffer = buffer:sub(child_used_bytes + 1, #buffer)
|
256 |
-
end
|
257 |
-
end
|
258 |
-
|
259 |
-
return ebml_id, ebml_value, used_bytes
|
260 |
-
end
|
261 |
-
|
262 |
-
|
263 |
-
-- Should accept 12+ bytes, will return the ebml id, the data length and the
|
264 |
-
-- number of bytes that were used to hold those values.
|
265 |
-
function ebml_id_and_length(chars)
|
266 |
-
-- The ID is encoded the same way as the length, however, we don't want
|
267 |
-
-- to remove the length bits from the ID value or intepret it as an
|
268 |
-
-- unsigned int since all of the documentation online references the IDs in
|
269 |
-
-- encoded form.
|
270 |
-
local _, id_length = ebml_length(chars:sub(1, 4))
|
271 |
-
local ebml_id = chars:sub(1, id_length)
|
272 |
-
|
273 |
-
local remaining = chars:sub(id_length + 1, id_length + 8)
|
274 |
-
local element_length, used_bytes = ebml_length(remaining)
|
275 |
-
|
276 |
-
return ebml_id, element_length, id_length + used_bytes
|
277 |
-
end
|
278 |
-
|
279 |
-
|
280 |
-
-- Should accept 8+ bytes, will return the data length plus the number of bytes
|
281 |
-
-- that were used to hold the data length.
|
282 |
-
function ebml_length(chars)
|
283 |
-
-- We substring chars to ensure we don't build a huge table we don't need
|
284 |
-
local bit_tables = string_to_bit_table(chars:sub(1, 8))
|
285 |
-
|
286 |
-
local value_length = 1
|
287 |
-
for i=1, #bit_tables[1] do
|
288 |
-
if bit_tables[1][i] == 0 then
|
289 |
-
value_length = value_length + 1
|
290 |
-
else
|
291 |
-
-- Clear the indicator bit so the rest of the byte
|
292 |
-
bit_tables[1][i] = 0
|
293 |
-
break
|
294 |
-
end
|
295 |
-
end
|
296 |
-
|
297 |
-
local bits = {}
|
298 |
-
for i=1, value_length do
|
299 |
-
table.insert(bits, table.concat(bit_tables[i]))
|
300 |
-
end
|
301 |
-
|
302 |
-
return tonumber(table.concat(bits), 2), value_length
|
303 |
-
end
|
304 |
-
|
305 |
-
|
306 |
-
function binary_tests(content, ext)
|
307 |
-
local length = #content
|
308 |
-
local _1_8 = content:sub(1, 8)
|
309 |
-
local _1_7 = content:sub(1, 7)
|
310 |
-
local _1_6 = content:sub(1, 6)
|
311 |
-
local _1_5 = content:sub(1, 5)
|
312 |
-
local _1_4 = content:sub(1, 4)
|
313 |
-
local _1_3 = content:sub(1, 3)
|
314 |
-
local _1_2 = content:sub(1, 2)
|
315 |
-
local _9_12 = content:sub(9, 12)
|
316 |
-
|
317 |
-
|
318 |
-
-- Images
|
319 |
-
if _1_4 == '\xC5\xD0\xD3\xC6' then
|
320 |
-
-- With a Windows-format EPS, the file starts right after a 30-byte
|
321 |
-
-- header, or a 30-byte header followed by two bytes of padding
|
322 |
-
if content:sub(33, 42) == '%!PS-Adobe' or content:sub(31, 40) == '%!PS-Adobe' then
|
323 |
-
return 'application/postscript'
|
324 |
-
end
|
325 |
-
end
|
326 |
-
|
327 |
-
if _1_8 == '%!PS-Ado' and content:sub(9, 10) == 'be' then
|
328 |
-
return 'application/postscript'
|
329 |
-
end
|
330 |
-
|
331 |
-
if _1_4 == 'MM\x00*' or _1_4 == 'II*\x00' then
|
332 |
-
return 'image/tiff'
|
333 |
-
end
|
334 |
-
|
335 |
-
if _1_8 == '\x89PNG\r\n\x1A\n' then
|
336 |
-
return 'image/png'
|
337 |
-
end
|
338 |
-
|
339 |
-
if _1_6 == 'GIF87a' or _1_6 == 'GIF89a' then
|
340 |
-
return 'image/gif'
|
341 |
-
end
|
342 |
-
|
343 |
-
if _1_4 == 'RIFF' and _9_12 == 'WEBP' then
|
344 |
-
return 'image/webp'
|
345 |
-
end
|
346 |
-
|
347 |
-
if _1_2 == 'BM' and length > 14 and in_table(content:sub(15, 15), {'\x0C', '(', '@', '\x80'}) then
|
348 |
-
return 'image/x-ms-bmp'
|
349 |
-
end
|
350 |
-
|
351 |
-
local normal_jpeg = length > 10 and in_table(content:sub(7, 10), {'JFIF', 'Exif'})
|
352 |
-
local photoshop_jpeg = length > 24 and _1_4 == '\xFF\xD8\xFF\xED' and content:sub(21, 24) == '8BIM'
|
353 |
-
if normal_jpeg or photoshop_jpeg then
|
354 |
-
return 'image/jpeg'
|
355 |
-
end
|
356 |
-
|
357 |
-
if _1_4 == '8BPS' then
|
358 |
-
return 'image/vnd.adobe.photoshop'
|
359 |
-
end
|
360 |
-
|
361 |
-
if _1_8 == '\x00\x00\x00\x0CjP ' and _9_12 == '\r\n\x87\n' then
|
362 |
-
return 'image/jp2'
|
363 |
-
end
|
364 |
-
|
365 |
-
if _1_4 == '\x00\x00\x01\x00' then
|
366 |
-
return 'application/vnd.microsoft.icon'
|
367 |
-
end
|
368 |
-
|
369 |
-
|
370 |
-
-- Audio/Video
|
371 |
-
if _1_4 == '\x1AE\xDF\xA3' and length > 1000 then
|
372 |
-
local mimetype, err = ebml_parse(content)
|
373 |
-
|
374 |
-
if mimetype then
|
375 |
-
return mimetype
|
376 |
-
end
|
377 |
-
end
|
378 |
-
|
379 |
-
if _1_4 == 'MOVI' then
|
380 |
-
if in_table(content:sub(5, 8), {'moov', 'mdat'}) then
|
381 |
-
return 'video/quicktime'
|
382 |
-
end
|
383 |
-
end
|
384 |
-
|
385 |
-
if length > 8 and content:sub(5, 8) == 'ftyp' then
|
386 |
-
local lower_9_12 = _9_12:lower()
|
387 |
-
|
388 |
-
if in_table(lower_9_12, {'avc1', 'isom', 'iso2', 'mp41', 'mp42', 'mmp4', 'ndsc', 'ndsh', 'ndsm', 'ndsp', 'ndss', 'ndxc', 'ndxh', 'ndxm', 'ndxp', 'ndxs', 'f4v ', 'f4p ', 'm4v '}) then
|
389 |
-
return 'video/mp4'
|
390 |
-
end
|
391 |
-
|
392 |
-
if in_table(lower_9_12, {'msnv', 'ndas', 'f4a ', 'f4b ', 'm4a ', 'm4b ', 'm4p '}) then
|
393 |
-
return 'audio/mp4'
|
394 |
-
end
|
395 |
-
|
396 |
-
if in_table(lower_9_12, {'3g2a', '3g2b', '3g2c', 'kddi'}) then
|
397 |
-
return 'video/3gpp2'
|
398 |
-
end
|
399 |
-
|
400 |
-
if in_table(lower_9_12, {'3ge6', '3ge7', '3gg6', '3gp1', '3gp2', '3gp3', '3gp4', '3gp5', '3gp6', '3gs7'}) then
|
401 |
-
return 'video/3gpp'
|
402 |
-
end
|
403 |
-
|
404 |
-
if lower_9_12 == 'mqt ' or lower_9_12 == 'qt ' then
|
405 |
-
return 'video/quicktime'
|
406 |
-
end
|
407 |
-
|
408 |
-
if lower_9_12 == 'jp2 ' then
|
409 |
-
return 'image/jp2'
|
410 |
-
end
|
411 |
-
end
|
412 |
-
|
413 |
-
-- MP3
|
414 |
-
if bitwise_and(_1_2, '\xFF\xF6') == '\xFF\xF2' then
|
415 |
-
local byte_3 = content:sub(3, 3)
|
416 |
-
if bitwise_and(byte_3, '\xF0') ~= '\xF0' and bitwise_and(byte_3, "\x0C") ~= "\x0C" then
|
417 |
-
return 'audio/mpeg'
|
418 |
-
end
|
419 |
-
end
|
420 |
-
if _1_3 == 'ID3' then
|
421 |
-
return 'audio/mpeg'
|
422 |
-
end
|
423 |
-
|
424 |
-
if _1_4 == 'fLaC' then
|
425 |
-
return 'audio/x-flac'
|
426 |
-
end
|
427 |
-
|
428 |
-
if _1_8 == '0&\xB2u\x8Ef\xCF\x11' then
|
429 |
-
-- Without writing a full-on ASF parser, we can just scan for the
|
430 |
-
-- UTF-16 string "AspectRatio"
|
431 |
-
if content:find('\x00A\x00s\x00p\x00e\x00c\x00t\x00R\x00a\x00t\x00i\x00o', 1, true) then
|
432 |
-
return 'video/x-ms-wmv'
|
433 |
-
end
|
434 |
-
return 'audio/x-ms-wma'
|
435 |
-
end
|
436 |
-
|
437 |
-
if _1_4 == 'RIFF' and _9_12 == 'AVI ' then
|
438 |
-
return 'video/x-msvideo'
|
439 |
-
end
|
440 |
-
|
441 |
-
if _1_4 == 'RIFF' and _9_12 == 'WAVE' then
|
442 |
-
return 'audio/x-wav'
|
443 |
-
end
|
444 |
-
|
445 |
-
if _1_4 == 'FORM' and _9_12 == 'AIFF' then
|
446 |
-
return 'audio/x-aiff'
|
447 |
-
end
|
448 |
-
|
449 |
-
if _1_4 == 'OggS' then
|
450 |
-
local _29_33 = content:sub(29, 33)
|
451 |
-
if _29_33 == '\x01vorb' then
|
452 |
-
return 'audio/vorbis'
|
453 |
-
end
|
454 |
-
if _29_33 == '\x07FLAC' then
|
455 |
-
return 'audio/x-flac'
|
456 |
-
end
|
457 |
-
if _29_33 == 'OpusH' then
|
458 |
-
return 'audio/ogg'
|
459 |
-
end
|
460 |
-
-- Theora and OGM
|
461 |
-
if _29_33 == '\x80theo' or _29_33 == 'vide' then
|
462 |
-
return 'video/ogg'
|
463 |
-
end
|
464 |
-
end
|
465 |
-
|
466 |
-
if _1_3 == 'FWS' or _1_3 == 'CWS' then
|
467 |
-
return 'application/x-shockwave-flash'
|
468 |
-
end
|
469 |
-
|
470 |
-
if _1_3 == 'FLV' then
|
471 |
-
return 'video/x-flv'
|
472 |
-
end
|
473 |
-
|
474 |
-
|
475 |
-
if _1_5 == '%PDF-' then
|
476 |
-
return 'application/pdf'
|
477 |
-
end
|
478 |
-
|
479 |
-
if _1_5 == '{\\rtf' then
|
480 |
-
return 'text/rtf'
|
481 |
-
end
|
482 |
-
|
483 |
-
|
484 |
-
-- Office '97-2003 formats
|
485 |
-
if _1_8 == '\xD0\xCF\x11\xE0\xA1\xB1\x1A\xE1' then
|
486 |
-
if in_table(ext, {'xls', 'csv', 'tab'}) then
|
487 |
-
return 'application/vnd.ms-excel'
|
488 |
-
end
|
489 |
-
if ext == 'ppt' then
|
490 |
-
return 'application/vnd.ms-powerpoint'
|
491 |
-
end
|
492 |
-
-- We default to word since we need something if the extension isn't recognized
|
493 |
-
return 'application/msword'
|
494 |
-
end
|
495 |
-
|
496 |
-
if _1_8 == '\x09\x04\x06\x00\x00\x00\x10\x00' then
|
497 |
-
return 'application/vnd.ms-excel'
|
498 |
-
end
|
499 |
-
|
500 |
-
if _1_6 == '\xDB\xA5\x2D\x00\x00\x00' or _1_5 == '\x50\x4F\x5E\x51\x60' or _1_4 == '\xFE\x37\x00\x23' or _1_3 == '\x94\xA6\x2E' then
|
501 |
-
return 'application/msword'
|
502 |
-
end
|
503 |
-
|
504 |
-
if _1_4 == 'PK\x03\x04' then
|
505 |
-
-- Office XML formats
|
506 |
-
if ext == 'xlsx' then
|
507 |
-
return 'application/vnd.ms-excel'
|
508 |
-
end
|
509 |
-
|
510 |
-
if ext == 'pptx' then
|
511 |
-
return 'application/vnd.ms-powerpoint'
|
512 |
-
end
|
513 |
-
|
514 |
-
if ext == 'docx' then
|
515 |
-
return 'application/msword'
|
516 |
-
end
|
517 |
-
|
518 |
-
-- Open Office formats
|
519 |
-
if ext == 'ods' then
|
520 |
-
return 'application/vnd.oasis.opendocument.spreadsheet'
|
521 |
-
end
|
522 |
-
|
523 |
-
if ext == 'odp' then
|
524 |
-
return 'application/vnd.oasis.opendocument.presentation'
|
525 |
-
end
|
526 |
-
|
527 |
-
if ext == 'odt' then
|
528 |
-
return 'application/vnd.oasis.opendocument.text'
|
529 |
-
end
|
530 |
-
|
531 |
-
-- iWork - some programs like Mac Mail change the filename to
|
532 |
-
-- .numbers.zip, etc
|
533 |
-
if ext == 'pages' or ext == 'pages.zip' then
|
534 |
-
return 'application/vnd.apple.pages'
|
535 |
-
end
|
536 |
-
if ext == 'key' or ext == 'key.zip' then
|
537 |
-
return 'application/vnd.apple.keynote'
|
538 |
-
end
|
539 |
-
if ext == 'numbers' or ext == 'numbers.zip' then
|
540 |
-
return 'application/vnd.apple.numbers'
|
541 |
-
end
|
542 |
-
|
543 |
-
-- Otherwise just a zip
|
544 |
-
return 'application/zip'
|
545 |
-
end
|
546 |
-
|
547 |
-
|
548 |
-
-- Archives
|
549 |
-
if length > 257 then
|
550 |
-
if content:sub(258, 263) == 'ustar\x00' then
|
551 |
-
return 'application/x-tar'
|
552 |
-
end
|
553 |
-
if content:sub(258, 265) == 'ustar\x40\x40\x00' then
|
554 |
-
return 'application/x-tar'
|
555 |
-
end
|
556 |
-
end
|
557 |
-
|
558 |
-
if _1_7 == 'Rar!\x1A\x07\x00' or _1_8 == 'Rar!\x1A\x07\x01\x00' then
|
559 |
-
return 'application/x-rar-compressed'
|
560 |
-
end
|
561 |
-
|
562 |
-
if _1_2 == '\x1F\x9D' then
|
563 |
-
return 'application/x-compress'
|
564 |
-
end
|
565 |
-
|
566 |
-
if _1_2 == '\x1F\x8B' then
|
567 |
-
return 'application/x-gzip'
|
568 |
-
end
|
569 |
-
|
570 |
-
if _1_3 == 'BZh' then
|
571 |
-
return 'application/x-bzip2'
|
572 |
-
end
|
573 |
-
|
574 |
-
if _1_6 == '\xFD7zXZ\x00' then
|
575 |
-
return 'application/x-xz'
|
576 |
-
end
|
577 |
-
|
578 |
-
if _1_6 == '7z\xBC\xAF\x27\x1C' then
|
579 |
-
return 'application/x-7z-compressed'
|
580 |
-
end
|
581 |
-
|
582 |
-
if _1_2 == 'MZ' then
|
583 |
-
local pe_header_start = unpack_le(content:sub(61, 64))
|
584 |
-
local signature = content:sub(pe_header_start + 1, pe_header_start + 4)
|
585 |
-
|
586 |
-
if signature == 'PE\x00\x00' then
|
587 |
-
local image_file_header_start = pe_header_start + 5
|
588 |
-
local characteristics = content:sub(image_file_header_start + 18, image_file_header_start + 19)
|
589 |
-
local is_dll = bitwise_and(characteristics, '\x20\x00') == '\x20\x00'
|
590 |
-
|
591 |
-
if is_dll then
|
592 |
-
return 'application/x-msdownload'
|
593 |
-
end
|
594 |
-
|
595 |
-
return 'application/octet-stream'
|
596 |
-
end
|
597 |
-
end
|
598 |
-
|
599 |
-
return nil
|
600 |
-
end
|
601 |
-
|
602 |
-
|
603 |
-
function text_tests(content)
|
604 |
-
local lower_content = content:lower()
|
605 |
-
|
606 |
-
if content:find('^%%!PS-Adobe') then
|
607 |
-
return 'application/postscript'
|
608 |
-
end
|
609 |
-
|
610 |
-
if lower_content:find('<?php', 1, true) or content:find('<?=', 1, true) then
|
611 |
-
return 'application/x-httpd-php'
|
612 |
-
end
|
613 |
-
|
614 |
-
if lower_content:find('^%s*<%?xml') then
|
615 |
-
if content:find('<svg') then
|
616 |
-
return 'image/svg+xml'
|
617 |
-
end
|
618 |
-
if lower_content:find('<!doctype html') then
|
619 |
-
return 'application/xhtml+xml'
|
620 |
-
end
|
621 |
-
if content:find('<rss') then
|
622 |
-
return 'application/rss+xml'
|
623 |
-
end
|
624 |
-
return 'application/xml'
|
625 |
-
end
|
626 |
-
|
627 |
-
if lower_content:find('^%s*<html') or lower_content:find('^%s*<!doctype') then
|
628 |
-
return 'text/html'
|
629 |
-
end
|
630 |
-
|
631 |
-
if lower_content:find('^#![/a-z0-9]+ ?python') then
|
632 |
-
return 'application/x-python'
|
633 |
-
end
|
634 |
-
|
635 |
-
if lower_content:find('^#![/a-z0-9]+ ?perl') then
|
636 |
-
return 'application/x-perl'
|
637 |
-
end
|
638 |
-
|
639 |
-
if lower_content:find('^#![/a-z0-9]+ ?ruby') then
|
640 |
-
return 'application/x-ruby'
|
641 |
-
end
|
642 |
-
|
643 |
-
if lower_content:find('^#![/a-z0-9]+ ?php') then
|
644 |
-
return 'application/x-httpd-php'
|
645 |
-
end
|
646 |
-
|
647 |
-
if lower_content:find('^#![/a-z0-9]+ ?bash') then
|
648 |
-
return 'text/x-shellscript'
|
649 |
-
end
|
650 |
-
|
651 |
-
return nil
|
652 |
-
end
|
653 |
-
|
654 |
-
|
655 |
-
local ext_map = {
|
656 |
-
css = 'text/css',
|
657 |
-
csv = 'text/csv',
|
658 |
-
htm = 'text/html',
|
659 |
-
html = 'text/html',
|
660 |
-
xhtml = 'text/html',
|
661 |
-
ics = 'text/calendar',
|
662 |
-
js = 'application/javascript',
|
663 |
-
php = 'application/x-httpd-php',
|
664 |
-
php3 = 'application/x-httpd-php',
|
665 |
-
php4 = 'application/x-httpd-php',
|
666 |
-
php5 = 'application/x-httpd-php',
|
667 |
-
inc = 'application/x-httpd-php',
|
668 |
-
pl = 'application/x-perl',
|
669 |
-
cgi = 'application/x-perl',
|
670 |
-
py = 'application/x-python',
|
671 |
-
rb = 'application/x-ruby',
|
672 |
-
rhtml = 'application/x-ruby',
|
673 |
-
rss = 'application/rss+xml',
|
674 |
-
sh = 'text/x-shellscript',
|
675 |
-
tab = 'text/tab-separated-values',
|
676 |
-
vcf = 'text/x-vcard',
|
677 |
-
xml = 'application/xml'
|
678 |
-
}
|
679 |
-
|
680 |
-
function ext_tests(ext)
|
681 |
-
local mimetype = ext_map[ext]
|
682 |
-
if mimetype then
|
683 |
-
return mimetype
|
684 |
-
end
|
685 |
-
return 'text/plain'
|
686 |
-
end
|
687 |
-
|
688 |
-
|
689 |
-
local _M = {}
|
690 |
-
|
691 |
-
|
692 |
-
function _M.via_path(path, filename)
|
693 |
-
local f, err = io.open(path, 'r')
|
694 |
-
if not f then
|
695 |
-
return nil, err
|
696 |
-
end
|
697 |
-
|
698 |
-
local content = f:read(4096)
|
699 |
-
f:close()
|
700 |
-
|
701 |
-
if not filename then
|
702 |
-
filename = basename(path)
|
703 |
-
end
|
704 |
-
|
705 |
-
return _M.via_content(content, filename)
|
706 |
-
end
|
707 |
-
|
708 |
-
|
709 |
-
function _M.via_content(content, filename)
|
710 |
-
local ext = extension(filename)
|
711 |
-
|
712 |
-
-- If there are no low ASCII chars and no easily distinguishable tokens,
|
713 |
-
-- we need to detect by file extension
|
714 |
-
|
715 |
-
local mimetype = nil
|
716 |
-
|
717 |
-
mimetype = binary_tests(content, ext)
|
718 |
-
if mimetype then
|
719 |
-
return mimetype
|
720 |
-
end
|
721 |
-
|
722 |
-
-- Binary-looking files should have been detected so far
|
723 |
-
if content:find('[%z\x01-\x08\x0B\x0C\x0E-\x1F]') then
|
724 |
-
return 'application/octet-stream'
|
725 |
-
end
|
726 |
-
|
727 |
-
mimetype = text_tests(content)
|
728 |
-
if mimetype then
|
729 |
-
return mimetype
|
730 |
-
end
|
731 |
-
|
732 |
-
return ext_tests(ext)
|
733 |
-
end
|
734 |
-
|
735 |
-
return _M
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/_extensions/shafayetShafee/downloadthis/resources/css/downloadthis.css
DELETED
@@ -1,13 +0,0 @@
|
|
1 |
-
.downloadthis:focus,
|
2 |
-
.downloadthis:active {
|
3 |
-
box-shadow: none !important;
|
4 |
-
}
|
5 |
-
|
6 |
-
.downloadthis:hover {
|
7 |
-
transition: 0.2s;
|
8 |
-
filter: brightness(0.90);
|
9 |
-
}
|
10 |
-
|
11 |
-
.downloadthis:active {
|
12 |
-
filter: brightness(0.80);
|
13 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src/_quarto.yml
CHANGED
@@ -47,7 +47,7 @@ website:
|
|
47 |
- href: 01_setup/glossar.qmd
|
48 |
text: "Glossar"
|
49 |
- href: 01_setup/ressourcen.qmd
|
50 |
-
text: "Ressourcen"
|
51 |
- title: "No Code"
|
52 |
contents:
|
53 |
- href: basics.qmd
|
@@ -112,4 +112,4 @@ format:
|
|
112 |
html:
|
113 |
theme: cosmo
|
114 |
css: styles.css
|
115 |
-
toc: true
|
|
|
47 |
- href: 01_setup/glossar.qmd
|
48 |
text: "Glossar"
|
49 |
- href: 01_setup/ressourcen.qmd
|
50 |
+
text: "Weitere Ressourcen"
|
51 |
- title: "No Code"
|
52 |
contents:
|
53 |
- href: basics.qmd
|
|
|
112 |
html:
|
113 |
theme: cosmo
|
114 |
css: styles.css
|
115 |
+
toc: true
|
src/index.qmd
CHANGED
@@ -6,7 +6,7 @@ Herzlich willkommen zum Webscraping Workshop! Egal, ob Erste-Schritte oder Fortg
|
|
6 |
* Hast du ein Google Nutzerkonto?
|
7 |
* Hast du ein Huggingface Nutzerkonto?
|
8 |
* Hast du schon einmal Daten aus dem Internet extrahiert?
|
9 |
-
* Hast du schonmal Daten über eine API bezogen?
|
10 |
* Nutzt du Große Sprachmodelle?
|
11 |
|
12 |
## Navigation auf der Workshop Webseite 🧭
|
|
|
6 |
* Hast du ein Google Nutzerkonto?
|
7 |
* Hast du ein Huggingface Nutzerkonto?
|
8 |
* Hast du schon einmal Daten aus dem Internet extrahiert?
|
9 |
+
* Hast du schonmal Daten über eine [API](01_setup/glossar.html#a-wie-asynchrones-scraping) bezogen?
|
10 |
* Nutzt du Große Sprachmodelle?
|
11 |
|
12 |
## Navigation auf der Workshop Webseite 🧭
|