{$footer}";
return;
}
if ( !$id ) {
// as of writing this, there is no JSON API to get a memo by its uid
// so, we first get the numeric id by sloppily parsing the GRPC API
$id = explode( '%', urlencode(explode( 'memos/', file_get_contents( "{$instance}/memos.api.v1.MemoService/SearchMemos", false, stream_context_create([ 'http' => [
'method' => 'POST',
'header' => 'Content-Type: application/grpc-web+proto',
'content' => urldecode('%00%00%00%00!%0A%1Fuid%20%3D%3D%20%22' . $uid . '%22'),
]]) ) )[1]))[0];
}
// we always use the numeric id to get memo data via the JSON API
$memo = json_decode(file_get_contents("{$instance}/api/v1/memos/{$id}"));
$user = json_decode(file_get_contents("{$instance}/api/v1/{$memo->creator}"));
// patch the Markdown before parsing it, so that output is quasi-consistent with Memos
$content = '';
$inblock = false;
$lines = explode( "\n", $memo->content );
foreach ( $lines as $line ) {
if ( str_starts_with( $line, '```' ) ) {
$inblock = !$inblock;
} else if ( str_starts_with( $line, '#' ) ) {
// prevent hashtags from being interpreted as headings
$firstword = explode( ' ', str_replace( "\t", ' ', $line ) )[0];
if ( $firstword !== '#' ) {
$content .= " {$firstword}";
$line = substr( $line, strlen($firstword) );
}
}
$content .= $line . "\n";
if ( !$inblock ) {
$content .= "\n";
}
}
$markdown->setContent($content);
$content = $markdown->toHtml();
$htmlparts = explode( '