Skip to content
This repository has been archived by the owner on Jul 1, 2023. It is now read-only.

Use xhp for html rendering #27

Open
wants to merge 37 commits into
base: main
Choose a base branch
from
Open
Changes from 1 commit
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
9415eeb
Remove HH_FIXME for ENT_HTML5
lexidor May 27, 2023
572bf9d
Require xhp-lib
lexidor May 27, 2023
e625dd9
Format the affect files
lexidor May 27, 2023
94aac71
Shift hhast into top gear
lexidor May 27, 2023
8d8282b
Lint PreferSingleQuotedStringLiteral
lexidor May 27, 2023
8134e9d
Lint NoFinalMethodInFinalClass
lexidor May 27, 2023
dccc276
Lint DontHaveTwoEmptyLinesInARow
lexidor May 27, 2023
799edc0
Disable FinalOrAbstractClassLinter
lexidor May 27, 2023
32a5de5
Disable UseStatementWithAsLinter
lexidor May 27, 2023
228532a
Lint NoEmptyStatementsLinter
lexidor May 27, 2023
9ff4e8c
Lint clean with "all"
lexidor May 27, 2023
0bf465f
Remove needless null check with help from HHClientLinter
lexidor May 27, 2023
cbc51f9
Introduce a couple hacks to aid in the migration
lexidor May 27, 2023
b02c8d9
Prepare for boolean attributes in tests
lexidor May 27, 2023
c8fdbdd
Introduce an escape hatch for XHP rendering
lexidor May 27, 2023
b5e961a
Create covariant interface IRenderer<T>
lexidor May 27, 2023
82ba6dd
Prepare the tests for a new renderer
lexidor May 27, 2023
728a277
Fix doubly normalized html in tests
lexidor May 27, 2023
c5f3fd4
FAILING_TEST_ON_PURPOSE_TO_ENSURE_THIS_IS_COVERED
lexidor May 27, 2023
30979eb
Change the type of HTMLXhpRenderer to Render<node>
lexidor May 27, 2023
19916da
Move simple cases to native XHP
lexidor May 27, 2023
1e5646d
Emit images with xhp
lexidor May 27, 2023
8a5c5b4
Move more simple cases to native XHP
lexidor May 27, 2023
666c388
Render lists with XHP
lexidor May 27, 2023
b60ab93
Remove the last FORCE_RENDER() call in HTMLXHPRenderer
lexidor May 27, 2023
c6a0f40
Make DO_NOT_ESCAPE_ATTRIBUTE slightly less dangerous
lexidor May 27, 2023
63148c2
Remove FORCE_RENDER
lexidor May 27, 2023
9482d13
Increase the scare factor of DO_NOT_ESCAPE()
lexidor May 27, 2023
6b25e2c
Factor out escape_uri_attribute
lexidor May 27, 2023
fb18394
Wrap the HTMLXHPRenderer in a Renderer<string>
lexidor May 27, 2023
69b6b88
Put HTMLRenderer::URI_SAFE back for BC
lexidor May 27, 2023
86ec5dc
Lint almost clean (including HHClientLinter)
lexidor May 27, 2023
999f859
Optimization found by HHClientLinter
lexidor May 27, 2023
c096490
Remove needless xhp_join() calls
lexidor May 27, 2023
c53319a
Update README to mention RenderableAsXHP
lexidor May 27, 2023
4a55838
Remove hhvm(-autoload) requirement
lexidor May 27, 2023
08e5859
Fix CI
lexidor May 27, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Wrap the HTMLXHPRenderer in a Renderer<string>
We can't simply switch the HTMLRender to use HTMLXHPRenderer under the hood.
The xhp renderer has slightly different output:
 - Boolean attributes are rendered as `attr` instead of `attr=""`.
 - Void elements don't include a trailing solidus (backslash) in their open tag.
I'd not want to break test suites , bust caches, or break naive parsers.
This change should be opt-in, but low friction.
  • Loading branch information
lexidor committed May 27, 2023
commit fb18394d2b9e078860365a417b65253435076bc0
10 changes: 10 additions & 0 deletions src/render/HTMLRenderer.php
Original file line number Diff line number Diff line change
@@ -13,6 +13,16 @@
use namespace HH\Lib\{C, Str, Vec};
use namespace HH\Asio;

/**
* You probably want to use `HTMLXHPRenderer` or failing that
* `HTMLWithXHPInternallyRenderer`. These two renderers are built with xhp,
* which automates the escaping of attributes and text nodes.
*
* `HTMLRenderer` uses string concatenation and manual escaping under the hood.
* Great care is taken to escape user data, but when this is done manually,
* bugs can slip through. Strongly consider the other renderers in security
* critical contexts.
*/
class HTMLRenderer extends Renderer<string> {
const keyset<classname<RenderFilter>> EXTENSIONS = keyset[
TagFilterExtension::class,
155 changes: 155 additions & 0 deletions src/render/HTMLWithXHPInternallyRenderer.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
<?hh // strict
/*
* Copyright (c) 2004-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
*/

namespace Facebook\Markdown;

// HHAST_IGNORE_ALL[DontUseAsioJoin]
// We want to offer this renderer to those who can't upgrade to HTMLXHPRenderer.
// HTMLRenderer is a Renderer<string>, so HTMLWithXHPInternallyRenderer is too.
// This forces us to run the Awaitables in a blocking fashion.

use namespace HH\Lib\{C, Str, Vec};
use namespace HH\Asio;
use namespace Facebook\XHP;

final class HTMLWithXHPInternallyRenderer extends Renderer<string> {
private IRenderer<XHP\Core\node> $impl;

public function __construct(RenderContext $context) {
parent::__construct($context);
$this->impl = new HTMLXHPRenderer($context);
}

<<__Override>>
protected function renderNodes(vec<ASTNode> $nodes): string {
return $this->impl->renderNodes($nodes) |> Asio\join($$->toStringAsync());
}

<<__Override>>
protected function renderResolvedNode(ASTNode $node): string {
return
$this->impl->renderResolvedNode($node) |> Asio\join($$->toStringAsync());
}

<<__Override>>
protected function renderBlankLine(): string {
return $this->impl->renderBlankLine() |> Asio\join($$->toStringAsync());
}

<<__Override>>
protected function renderBlockQuote(Blocks\BlockQuote $node): string {
return
$this->impl->renderBlockQuote($node) |> Asio\join($$->toStringAsync());
}

<<__Override>>
protected function renderCodeBlock(Blocks\CodeBlock $node): string {
return
$this->impl->renderCodeBlock($node) |> Asio\join($$->toStringAsync());
}

<<__Override>>
protected function renderHeading(Blocks\Heading $node): string {
return $this->impl->renderHeading($node) |> Asio\join($$->toStringAsync());
}

<<__Override>>
protected function renderHTMLBlock(Blocks\HTMLBlock $node): string {
return
$this->impl->renderHTMLBlock($node) |> Asio\join($$->toStringAsync());
}

<<__Override>>
protected function renderLinkReferenceDefinition(
Blocks\LinkReferenceDefinition $def,
): string {
return $this->impl->renderLinkReferenceDefinition($def)
|> Asio\join($$->toStringAsync());
}

<<__Override>>
protected function renderListOfItems(Blocks\ListOfItems $node): string {
return
$this->impl->renderListOfItems($node) |> Asio\join($$->toStringAsync());
}

<<__Override>>
protected function renderParagraph(Blocks\Paragraph $node): string {
return
$this->impl->renderParagraph($node) |> Asio\join($$->toStringAsync());
}

<<__Override>>
protected function renderTableExtension(Blocks\TableExtension $node): string {
return $this->impl->renderTableExtension($node)
|> Asio\join($$->toStringAsync());
}

<<__Override>>
protected function renderThematicBreak(): string {
return $this->impl->renderThematicBreak() |> Asio\join($$->toStringAsync());
}

<<__Override>>
protected function renderAutoLink(Inlines\AutoLink $node): string {
return $this->impl->renderAutoLink($node) |> Asio\join($$->toStringAsync());
}

<<__Override>>
protected function renderInlineWithPlainTextContent(
Inlines\InlineWithPlainTextContent $node,
): string {
return $this->impl->renderInlineWithPlainTextContent($node)
|> Asio\join($$->toStringAsync());
}

<<__Override>>
protected function renderCodeSpan(Inlines\CodeSpan $node): string {
return $this->impl->renderCodeSpan($node) |> Asio\join($$->toStringAsync());
}

<<__Override>>
protected function renderEmphasis(Inlines\Emphasis $node): string {
return $this->impl->renderEmphasis($node) |> Asio\join($$->toStringAsync());
}

<<__Override>>
protected function renderHardLineBreak(): string {
return $this->impl->renderHardLineBreak() |> Asio\join($$->toStringAsync());
}

<<__Override>>
protected function renderImage(Inlines\Image $node): string {
return $this->impl->renderImage($node) |> Asio\join($$->toStringAsync());
}

<<__Override>>
protected function renderLink(Inlines\Link $node): string {
return $this->impl->renderLink($node) |> Asio\join($$->toStringAsync());
}

<<__Override>>
protected function renderRawHTML(Inlines\RawHTML $node): string {
return $this->impl->renderRawHTML($node) |> Asio\join($$->toStringAsync());
}

<<__Override>>
protected function renderSoftLineBreak(): string {
return $this->impl->renderSoftLineBreak() |> Asio\join($$->toStringAsync());
}

<<__Override>>
protected function renderStrikethroughExtension(
Inlines\StrikethroughExtension $node,
): string {
return $this->impl->renderStrikethroughExtension($node)
|> Asio\join($$->toStringAsync());
}
}
1 change: 1 addition & 0 deletions tests/TestCase.php
Original file line number Diff line number Diff line change
@@ -37,6 +37,7 @@ public function provideHTMLRendererConstructors(
return vec[
tuple(($ctx)[defaults] ==> new HTMLRenderer($ctx)),
tuple(($ctx)[defaults] ==> new HTMLXHPRenderer($ctx)),
tuple(($ctx)[defaults] ==> new HTMLWithXHPInternallyRenderer($ctx)),
];
}