JavaScript Python PHP
import * as __biblioteca0 from "unified";
import * as __biblioteca1 from "remark-parse";
import * as __biblioteca2 from "remark-gfm";
import * as __biblioteca3 from "remark-rehype";
import * as __biblioteca4 from "rehype-stringify";
import * as __biblioteca5 from "entities";
function executar(input = '# Olá\n\n**Bennu** e [link](https://example.com)') {
const unified = __biblioteca0["unified"];
const remarkParse = __biblioteca1["default"];
const remarkGfm = __biblioteca2["default"];
const remarkRehype = __biblioteca3["default"];
const rehypeStringify = __biblioteca4["default"];
const decodeHTML = __biblioteca5["decodeHTML"];
function validateMarkupUrl(url) {
// HTML entities and ASCII controls can obscure a scheme interpreted by a browser.
const normalized = decodeHTML(url).replace(/[\u0000-\u0020\u007f]/g, '');
let protocol;
try {
protocol = new URL(normalized, 'https://converter.invalid/').protocol;
}
catch {
throw new Error('URL inválida: use uma URL relativa, âncora, HTTP, HTTPS ou mailto.');
}
if (!['http:', 'https:', 'mailto:'].includes(protocol))
throw new Error(`Protocolo de URL não permitido: ${protocol.slice(0, -1)}. Use HTTP, HTTPS, mailto, URL relativa ou âncora.`);
}
function checkInput(input) {
if (input.length > 1000000)
throw new Error('A entrada excede o limite de 1 milhão de caracteres.');
}
function prepareMarkdown(node, depth = 0, state = { count: 0 }) {
if (++state.count > 100000 || depth > 100)
throw new Error('Documento muito complexo: limite de 100 níveis ou 100 mil nós.');
if (node.url !== undefined)
validateMarkupUrl(node.url);
if (node.children)
node.children = node.children.map(child => {
if (child.type === 'html') {
const text = { type: 'text', value: child.value ?? '' };
return node.type === 'paragraph' ? text : { type: 'paragraph', children: [text] };
}
prepareMarkdown(child, depth + 1, state);
return child;
});
}
function markdownToHtml(input) {
checkInput(input);
if (!input.trim())
return '';
const processor = unified().use(remarkParse).use(remarkGfm).use(remarkRehype).use(rehypeStringify);
const tree = processor.parse(input);
prepareMarkdown(tree);
return processor.stringify(processor.runSync(tree));
}
return markdownToHtml(input);
}
import html
import re
from urllib.parse import urlsplit
from markdown_it import MarkdownIt
def executar(input="# Olá\n\n**Bennu** e [link](https://example.com)"):
if len(input.encode("utf-16-le",errors="surrogatepass"))//2>1000000: raise ValueError("Limite de 1 milhão de caracteres.")
if not input.strip(): return ""
def safe_url(value):
normalized=re.sub(r"[\x00-\x20\x7f]","",html.unescape(value))
try: protocol=urlsplit(normalized).scheme.lower()
except ValueError as error: raise ValueError("URL inválida.") from error
if protocol and protocol not in ("http","https","mailto"): raise ValueError("Protocolo de URL não permitido: "+protocol)
return True
parser=MarkdownIt("commonmark",{"html":False}).enable(["table","strikethrough"])
parser.validateLink=safe_url
tokens=parser.parse(input)
count=0
def walk(items,depth=0):
nonlocal count
if depth>100: raise ValueError("Limite de 100 níveis.")
for token in items:
count+=1
if count>100000 or token.level>100: raise ValueError("Documento muito complexo.")
for attribute in ("href","src"):
url=token.attrGet(attribute)
if url is not None: safe_url(url)
if token.children: walk(token.children,depth+1)
walk(tokens)
return parser.renderer.render(tokens,parser.options,{}).removesuffix("\n")
<?php
use League\CommonMark\Environment\Environment;
use League\CommonMark\Extension\CommonMark\CommonMarkCoreExtension;
use League\CommonMark\Extension\GithubFlavoredMarkdownExtension;
use League\CommonMark\Extension\CommonMark\Node\Inline\Link;
use League\CommonMark\Extension\CommonMark\Node\Inline\Image;
use League\CommonMark\Parser\MarkdownParser;
use League\CommonMark\Renderer\HtmlRenderer;
require_once 'vendor/autoload.php';
function executar($input = "# Olá\n\n**Bennu** e [link](https://example.com)") {
if (!mb_check_encoding($input,'UTF-8') || strlen(mb_convert_encoding($input,'UTF-16LE','UTF-8'))/2>1000000) throw new InvalidArgumentException('UTF-8 inválido ou limite de entrada.');
if (trim($input)==='') return '';
$safeUrl=function ($value) {
$normalized=preg_replace('/[\x00-\x20\x7f]/','',html_entity_decode($value,ENT_QUOTES | ENT_HTML5,'UTF-8'));
if (preg_match('/^([A-Za-z][A-Za-z0-9+.-]*):/',$normalized,$m) && !in_array(strtolower($m[1]),['http','https','mailto'],true)) throw new InvalidArgumentException('Protocolo de URL não permitido: '.$m[1]);
if (parse_url($normalized)===false) throw new InvalidArgumentException('URL inválida.');
};
$environment=new Environment(['html_input'=>'escape','allow_unsafe_links'=>false,'max_nesting_level'=>100]);
$environment->addExtension(new CommonMarkCoreExtension());
$environment->addExtension(new GithubFlavoredMarkdownExtension());
$tree=(new MarkdownParser($environment))->parse($input);
$walker=$tree->walker(); $count=0;
while ($event=$walker->next()) {
if (!$event->isEntering()) continue;
if (++$count>100000) throw new InvalidArgumentException('Limite de 100 mil nós.');
$node=$event->getNode();
if ($node instanceof Link || $node instanceof Image) $safeUrl($node->getUrl());
}
return rtrim((string)(new HtmlRenderer($environment))->renderDocument($tree),"\n");
}