RemexHtml/nl

Introductie
RemexHtml is een parser voor HTML5, geschreven in PHP.

Uitgangspunten RemexHtml:


 * Modulair en flexibel.
 * Snel, liever dan elegant. Voorbeeld: we gebruiken soms directe toegang in plaats van accessors, en programmeren zelf handmatig de code als die performance gevoelig is.
 * Robuust, het streven is de slechts denkbare performance helemaal te voorkomen.

RemexHtml bevat deze modules:


 * Een soepele preprocessor en tokenizer. Dit zorgt voor een 'token event stream'.
 * Soepele boomstructuuropbouw, inclusief foutherstel. Dit zorgt voor een goed doorlopende aanpassing van de boomstructuur.
 * Een snelle geïntegreerde HTML-serializer, passend bij het HTML fragment serialisatie algoritme.
 * DOMDocument opbouw.

RemexHtml huidige gebreken:


 * Encoding ondersteuning. Er wordt vanuit gegaan dat de invoer geldige UTF-8 is.
 * Scripting.
 * XHTML serialisatie.
 * Precieze volgen van de bij bepaalde fouten gegenereerde uitvoer van de parser.

RemexHtml wil de W3C aanbevelingen van HTML 5.1 volgen, er zijn wat uitzonderingen voor wat kleine bugfixes voor het ondersteunen van oudere versies van HTML. Er is gekozen om de W3C standaard te implementeren en niet de laatste WHATWG draft omdat we streven naar stabiliteit en niet naar volledigheid van functionaliteit.

RemexHtml voldoet aan alle html5lib testen, met uitzondering van het tellen van de parse fouten en testen waarin gekeken wordt of aan de toekomstige versie van de standaard wordt voldaan.

In MediaWiki
RemexHtml is als een core composer afhankelijkheid vanaf MediaWiki 1.29 beschikbaar. Het oorspronkelijke doel was het om een vervanging te zijn van HTML Tidy. Uitvoer van de wikitext parser wordt gestuurd naar de RemexHtml's HTML parser en de HTML5 tag gebruik wordt opgeschoond. De Tokenizer component wordt nu ook gebruikt voor tag verwijdering in Sanitizer.

Het wordt ook gebruikt voor het vooraf verwerken van HTML in de extensies, en.



Buiten de Mediawiki
Installeer het wikimedia/remex-html package vanaf Packagist:

composer require wikimedia/remex-html

De gebruikte versienaamgeving is semantisch. De hoofdversie wordt verhoogd als de wijziging er een is die niet meer compatibel is de voorafgaande versie.



Overzicht architectuur
Voor een volledige documentatie, bekijk de uit de broncode samengestelde documentatie, of de broncode zelf.


 * Gegenereerde API documentatie

RemexHtml gebruikt een 'pipeline model'. Als er een gebeurtenis gemaakt moet worden, dan wordt er een toegevoegd callback object aangeroepen die de gebeurtenis afhandelt. De stappen zijn:


 * Tokenizer
 * Geeft een stroom van tekens uit de HTML. Voert de tokenization uit, zoals beschreven in het tokenisatie hoofdstuk in de HTML specificatie.


 * Dispatcher
 * Volgt de insertie mode, en geeft token gebeurtenissen door aan een specifieke handler voor de huidige insertie mode. Elke mode heeft een eigen class, met methoden voor elk token type.


 * TreeBuilder
 * Een helper class voor de insertie modes. Het volgt de status van de boomconstructie, ontvangt verzoeken voor aanpassingen in de boom van de insertie mode classes en verstuurd de boomaanpassingen.

In de HTML-specificatie wordt de boomstructuur voorgesteld als sterk geïntegreerd met de aanmaak van de DOM gegevensstructuur. Een grote innovatie van RemexHtml is het scheiden van de boomopbouw in een fase waar de wijzigingen van boom worden doorgegeven en een fase waarin de datastructuur echt wordt gemaakt. RemexHtml kan het wijzigen van de boom direct op volgorde brengen in de uitvoer zonder de hele DOM in het geheugen te hebben.


 * Serializer : Geeft HTML uit een stroom gebeurtenissen met aanpassingen aan de boom.
 * DOMBuilder : Geeft een intern native PHP DOMDocument uit een stroom gebeurtenissen met aanpassingen aan de boom.

Bij het gebruiken van Serializer ie er nog een afsluitende fase:


 * Formatter
 * De interface Formatter converteert de SerializerNode objecten naar strings. Het is een helper voor Serializer waardoor de geproduceerde HTML eenvoudig kan worden aangepast. Serializer is complex en kent statussen, waar de Formatter subclasses in het algemeen geen status hebben, anders dan voor configuratie.

RemexHtml heeft ook:


 * DOMSerializer
 * een utility class voor het serialiseren van een DOM binnen een DOMBuilder, met een interface dat vergelijkbaar is met Serializer.


 * PropGuard
 * Veel RemexHtml classes gebruiken de PropGuard behandeling, wat voorkomt dat er per ongeluk een niet bestaande property wordt gebruikt. Dit voorkomt dat de ontwikkelaar verrast wordt door de class types. Als u toch zelf een property in uw applicatie wilt toevoegen, PropGuard kan globaal met PropGuard::$armed = false worden uitgeschakeld.


 * TokenGenerator
 * een class die zorgt voor een gegevensstroom via een generator interface, in plaats van via een gebeurtenissenstroom. It constructs its own Tokenizer. Consuming token events in this way is less efficient, but may be more convenient for some use cases.

There are optional pipeline stages providing debugging facilities:


 * DispatchTracer
 * This class sits between Tokenizer and Dispatcher. It reports all token events, and reports insertion mode transitions within Dispatcher. Log messages are sent to a callback function.


 * TreeMutationTracer
 * This forwards tree mutation events coming from TreeBuilder, and reports such events to a callback.


 * DestructTracer
 * This class forwards tree mutation events, and reports when the Element object emitted by TreeBuilder is destroyed. This helps to identify memory leaks.

RemexHtml's model of a configurable pipeline provides a great deal of flexibility. Applications may subclass pipeline classes provided by RemexHtml, or write their own from scratch, implementing the relevant event receiver interface. Or they may interpose custom pipeline stages in between RemexHtml's standard stages.

However, for simple use cases, there is a fair amount of boilerplate. T217850 proposes to add a simplified method for constructing a standard pipeline, but this has not yet been implemented.

Voorbeelden


De DOM opbouwen uit invoertekst
In the above code sample, the pipeline is constructed backwards, from end to start. The constructor of each pipeline stage receives the following pipeline stage. Then with the pipeline fully constructed, $tokenizer->execute causes the whole input text to be parsed and emitted through the pipeline, eventually reaching the DOMBuilder. After execution, the constructed document is available via $domBuilder->getFragment.



Doelen link wijzigen
This example modifies an HTML document on the fly, altering href attributes inside tags and returning an HTML string. It does this by subclassing HtmlFormatter, which is a relatively easy hook point into reserialization. It clones the SerializerNode and Attributes objects to avoid altering the document as seen by Serializer, since it is possible this function may be called more than once on each node, and we don't want to prefix the domain name more than once.

Alternatively we could have used SerializerNode::$snData as a flag, to avoid double-prefixing:

Performance
Various options can be enabled which improve performance, potentially at the expense of correctness:


 * Tokenizer
 * ignoreErrors - This does not simply discard parse errors as they are generated. In some cases it chooses a more efficient algorithm which implicitly ignores errors. If parse errors are not required, this should always be set.
 * skipPreprocess - The HTML specification requires that the input be preprocessed to normalize line endings and strip control characters. If line endings are already normalized in your application, and if you don't mind control characters being propagated through to the output, this option can be enabled, for a small improvement to performance.
 * ignoreNulls - Enabling this option causes any null characters to be passed through to the output. The HTML specification requires complex, context-dependent handling of null characters whenever they appear in the input. So if the application simply strips null characters from the input and enables this option, the result will not be standards-compliant, but performance will be slightly improved.
 * ignoreCharRefs - This is an aggressive and rarely-useful optimisation option which ignores character references, passing them through unmodified. It needs to be paired with a special serializer that will emit bare ampersands from text nodes instead of escaping them.
 * TreeBuilder
 * ignoreNulls, ignoreErrors - Same as the corresponding Tokenizer options



Over TokenizerError exceptions
If RemexHtml throws a TokenizerError exception, for example "pcre.backtrack_limit exhausted", this is usually not a bug in RemexHtml. Either the relevant configuration setting should be increased, or the input size should be limited. The pcre.backtrack_limit INI setting should be at least double the input size.



Zie ook

 * T89331 – Tidy in MediaWiki parser vervangen door HTML5 parse/reserialize
 * Html5Depurate (eerdere optie)
 * Parsing/Vervanging Tidy

