← Cloudflare Workers / workers / runtime-apis
HTMLRewriter
Kontext
HTMLRewriter třída umožňuje vývojářům vytvářet komplexní a expresivní parsery HTML přímo v aplikaci Cloudflare Workers. Lze si ji představit jako obdobu jQuery přímo uvnitř vaší aplikace Workers. Díky výkonnému JavaScript API pro parsování a transformaci HTML HTMLRewriter umožňuje vývojářům vytvářet aplikace s bohatou funkčností.
HTMLRewriter třída by měla být ve vašem Workers skriptu instanciována jednou, s několika handlery připojenými pomocí on a onDocument funkce.
Konstruktor
new HTMLRewriter()
.on("*", new ElementHandler())
.onDocument(new DocumentHandler());Globální typy
V celém HTMLRewriter API existuje několik jednotných typů, které používá řada vlastností a metod:
-
Contentstring | Response | ReadableStream- Obsah vložený do výstupního proudu by měl být řetězec,
Response, neboReadableStream.
- Obsah vložený do výstupního proudu by měl být řetězec,
-
ContentOptionsObject{ html: Boolean }Určuje způsob, jakým HTMLRewriter zpracovává vložený obsah. Pokudhtmlboolean je nastaven na true, obsah je zpracován jako čisté HTML. Pokud jehtmlboolean je nastaven na false nebo není zadán, obsah bude zpracován jako text a bude na něj uplatněno správné HTML escapování.
Obslužné rutiny
Existují dva typy handlerů, které lze použít s HTMLRewriter: obslužné rutiny prvků a obslužné rutiny dokumentů.
Element Handlers
Obslužná rutina elementu reaguje na jakýkoli příchozí element, pokud je připojena pomocí .on funkce objektu HTMLRewriter instance. Handler elementu by měl reagovat na element, comments, a text. Příklad zpracovává div elementů s ElementHandler třídu.
class ElementHandler {
element(element) {
// An incoming element, such as `div`
console.log(`Incoming element: ${element.tagName}`);
}
comments(comment) {
// An incoming comment
}
text(text) {
// An incoming piece of text
}
}
async function handleRequest(req) {
const res = await fetch(req);
return new HTMLRewriter().on("div", new ElementHandler()).transform(res);
}Document Handlers
Document handler představuje příchozí HTML dokument. Na document handleru lze definovat řadu funkcí pro dotazování a úpravu doctype, comments, text, a end. Na rozdíl od element handleru má document handler doctype, comments, text, a end funkce nejsou omezeny konkrétním selektorem. Funkce handleru dokumentu se volají pro veškerý obsah na stránce, včetně obsahu mimo nejvyšší HTML značku:
class DocumentHandler {
doctype(doctype) {
// An incoming doctype, such as <!DOCTYPE html>
}
comments(comment) {
// An incoming comment
}
text(text) {
// An incoming piece of text
}
end(end) {
// The end of the document
}
}Asynchronní handlery
Všechny funkce definované jak u element handlerů, tak u document handlerů mohou vracet buď void nebo Promise<void>. Když svou handler funkci učiníte async umožňuje přístup k externím zdrojům, jako je API přes fetch, Workers KV, Durable Objects nebo cache.
class UserElementHandler {
async element(element) {
let response = await fetch(new Request("/user"));
// fill in user info using response
}
}
async function handleRequest(req) {
const res = await fetch(req);
// run the user element handler via HTMLRewriter on a div with ID `user_info`
return new HTMLRewriter()
.on("div#user_info", new UserElementHandler())
.transform(res);
}Element
element argument, používaný pouze v handlerech elementů, je reprezentací DOM elementu. Element má k dispozici řadu metod pro jeho dotazování a úpravu:
Vlastnosti
-
tagNamestring- Název tagu, například
"h1"nebo"div". Této vlastnosti lze přiřadit různé hodnoty a upravit tak tag elementu.
- Název tagu, například
-
attributesIterator pouze pro čtení- A
[name, value]pár atributů daného tagu.
- A
-
removedboolean- Určuje, zda byl element odstraněn nebo nahrazen jedním z předchozích handlerů.
-
namespaceURIstring- Představuje URI jmenného prostoru ↗ prvku.
Metody
-
getAttribute(name:string)string | null- Vrátí hodnotu daného názvu atributu na elementu, nebo
nullpokud se nenajde.
- Vrátí hodnotu daného názvu atributu na elementu, nebo
-
hasAttribute(name:string)boolean- Vrátí hodnotu typu boolean udávající, zda na elementu existuje daný atribut.
-
setAttribute(name:string, valuestring)Element- Nastaví atribut na zadanou hodnotu; pokud atribut neexistuje, vytvoří ho.
-
removeAttribute(name:string)Element- Odebere atribut.
-
before(content:Content, contentOptionsContentOptionsoptional)Element- Vkládá obsah před element.
-
after(content:Content, contentOptionsContentOptionsoptional)Element- Vkládá obsah hned za element.
-
prepend(content:Content, contentOptionsContentOptionsoptional)Element- Vkládá obsah hned za počáteční značku elementu.
-
append(content:Content, contentOptionsContentOptionsoptional)Element- Vkládá obsah hned před koncovou značku elementu.
-
replace(content:Content, contentOptionsContentOptionsoptional)Element- Odebere element a na jeho místo vloží obsah.
-
setInnerContent(content:Content, contentOptionsContentOptionsoptional)Element- Nahradí obsah elementu.
-
remove():Element- Odebere element včetně veškerého obsahu.
-
removeAndKeepContent():Element- Odebere počáteční a koncovou značku elementu, ale zachová jeho vnitřní obsah beze změny.
-
onEndTag(handler:Function<void>)void- Registruje handler, který se vyvolá při dosažení koncové značky elementu.
EndTag
endTag argument, používaný pouze v handlerech registrovaných pomocí element.onEndTag, je omezenou reprezentací prvku DOM.
Vlastnosti
namestring- Název tagu, například
"h1"nebo"div". Této vlastnosti lze přiřadit různé hodnoty a upravit tak tag elementu.
- Název tagu, například
Metody
-
before(content:Content, contentOptionsContentOptionsoptional)EndTag- Vkládá obsah hned před koncovou značku.
-
after(content:Content, contentOptionsContentOptionsoptional)EndTag- Vkládá obsah hned za koncovou značku.
-
remove():EndTag- Odebere element včetně veškerého obsahu.
Textové části
Cloudflare provádí streamované parsování bez kopírování dat (zero-copy), takže textové bloky (chunks) nejsou totéž co textové uzly v lexikálním stromu. Jeden textový uzel lexikálního stromu může být tvořen více bloky, jak postupně přicházejí po síti z origin serveru.
Uvažujme následující značkování: <div>Hey. How are you?</div>. Je možné, že skript Workers nezíská celý textový uzel z originu najednou; místo toho text obslužná rutina elementu se vyvolá pro každou přijatou část textového uzlu. Obslužná rutina může být například vyvolána s "Hey. How ", poté "are you?". Jakmile dorazí poslední chunk, textu se lastInTextNode vlastnost bude nastavena na true. Vývojáři by měli zajistit, aby tyto části (chunky) spojili dohromady.
Vlastnosti
-
removedboolean- Určuje, zda byl element odstraněn nebo nahrazen jedním z předchozích handlerů.
-
textstring, jen pro čtení- Textový obsah bloku. Může být prázdný, pokud jde o poslední blok textového uzlu.
-
lastInTextNodeboolean, jen pro čtení- Určuje, zda je tento chunk posledním chunkem textového uzlu.
Metody
-
before(content:Content, contentOptionsContentOptionsoptional)Element- Vkládá obsah před element.
-
after(content:Content, contentOptionsContentOptionsoptional)Element- Vkládá obsah hned za element.
-
replace(content:Content, contentOptionsContentOptionsoptional)Element- Odebere element a na jeho místo vloží obsah.
-
remove():Element- Odebere element včetně veškerého obsahu.
Komentáře
comments funkce na handleru elementu umožňuje vývojářům dotazovat a upravovat značky HTML komentářů.
class ElementHandler {
comments(comment) {
// An incoming comment element, such as <!-- My comment -->
}
}Vlastnosti
-
comment.removedboolean- Určuje, zda byl element odstraněn nebo nahrazen jedním z předchozích handlerů.
-
comment.textstring- Text komentáře. Této vlastnosti lze přiřadit různé hodnoty a tím text komentáře změnit.
Metody
-
before(content:Content, contentOptionsContentOptionsoptional)Element- Vkládá obsah před element.
-
after(content:Content, contentOptionsContentOptionsoptional)Element- Vkládá obsah hned za element.
-
replace(content:Content, contentOptionsContentOptionsoptional)Element- Odebere element a na jeho místo vloží obsah.
-
remove():Element- Odebere element včetně veškerého obsahu.
Doctype
doctype funkce na handleru dokumentu umožňuje vývojářům dotazovat se na doctype ↗.
class DocumentHandler {
doctype(doctype) {
// An incoming doctype element, such as
// <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
}
}Vlastnosti
-
doctype.namestring | null, jen pro čtení- Název doctype.
-
doctype.publicIdstring | null, jen pro čtení- Řetězec v uvozovkách v doctype za atomem PUBLIC.
-
doctype.systemIdstring | null, jen pro čtení- Řetězec v uvozovkách v doctype za atomem SYSTEM nebo bezprostředně za
publicId.
- Řetězec v uvozovkách v doctype za atomem SYSTEM nebo bezprostředně za
Konec
end funkce na handleru dokumentu umožňuje vývojářům připojit obsah na konec dokumentu.
class DocumentHandler {
end(end) {
// The end of the document
}
}Metody
-
append(content:Content, contentOptionsContentOptionsoptional)DocumentEnd- Vkládá obsah za konec dokumentu.
Selektory
Toto jsou selektory a k tomuto účelu se používají.
-
*- Jakýkoli prvek.
-
E- Jakýkoli prvek typu E.
-
E:nth-child(n)- Element E, n-tý potomek svého rodiče.
-
E:first-child- Element E, první potomek svého rodiče.
-
E:nth-of-type(n)- Element E, n-tý sourozenec svého typu.
-
E:first-of-type- Element E, první sourozenec svého typu.
-
E:not(s)- Element E, který neodpovídá žádnému ze složených selektorů.
-
E.warning- Element E patřící do třídy warning.
-
E#myid- Element E s ID rovným myid.
-
E[foo]- Element E s atributem foo.
-
E[foo="bar"]- Element E, jehož hodnota atributu foo se přesně rovná bar.
-
E[foo="bar" i]- Element E, jehož hodnota atributu foo se přesně rovná libovolné (v rozsahu ASCII) permutaci velikosti písmen řetězce bar.
-
E[foo="bar" s]- Element E, jehož hodnota atributu foo se přesně a s rozlišením velikosti písmen rovná bar.
-
E[foo~="bar"]- Element E, jehož hodnota atributu foo je seznam hodnot oddělených mezerami, přičemž jedna z nich se přesně rovná bar.
-
E[foo^="bar"]- Element E, jehož hodnota atributu foo začíná přesně řetězcem bar.
-
E[foo$="bar"]- Element E, jehož hodnota atributu foo končí přesně řetězcem bar.
-
E[foo*="bar"]- Element E, jehož hodnota atributu foo obsahuje podřetězec bar.
-
E[foo|="en"]- Element E, jehož hodnota atributu foo je seznam hodnot oddělených spojovníkem, začínající en.
-
E F- Element F, potomek elementu E na libovolné úrovni.
-
E > F- Element F, přímý potomek elementu E.
Chyby
Pokud handler vyvolá výjimku, parsování se okamžitě zastaví, tělo transformované odpovědi skončí chybou s vyvolanou výjimkou a tělo netransformované odpovědi se zruší (uzavře). Pokud už bylo tělo transformované odpovědi částečně odesláno klientovi jako stream, klient uvidí zkrácenou odpověď.
async function handle(request) {
let oldResponse = await fetch(request);
let newResponse = new HTMLRewriter()
.on("*", {
element(element) {
throw new Error("A really bad error.");
},
})
.transform(oldResponse);
// At this point, an expression like `await newResponse.text()`
// will throw `new Error("A really bad error.")`.
// Thereafter, any use of `newResponse.body` will throw the same error,
// and `oldResponse.body` will be closed.
// Alternatively, this will produce a truncated response to the client:
return newResponse;
}