Add initial simple oneboxing support

This commit is contained in:
Starbeamrainbowlabs 2022-03-12 02:52:53 +00:00
parent f4f08d8066
commit 434abdf29f
Signed by: sbrl
GPG Key ID: 1BE5172E637709C2
4 changed files with 58 additions and 2 deletions

View File

@ -8,6 +8,9 @@ This file holds the changelog for Pepperminty Wiki. This is the master list of t
- Added support for embedding external YouTube and Vimeo videos (e.g. `![alt text](https://youtube.com/watch?v=pID0xQ2qnrQ)`)
- If you know of a cool service that should be supported, please open an issue - YouTube and Vimeo were just the only 2 I could think of
- Known issue: specifying the size (i.e. with ` | 500x400` inside the brackets `()` there) doesn't currently work because iframes are weird
- Added [oneboxing](https://meta.discourse.org/t/rich-link-previews-with-onebox/98088): rich previews for internal links. If an internal link is on it's own with nothing before or after it on a line, then it'll be turned into a onebox
- 2 new settings have also been added to control it: `parser_onebox_enabled` and `parser_onebox_preview_length`
- TODO: Update the dynamic help page for this.
### Changed
- Display returnto URL above the login form if present to further mitigate CSRF issues

View File

@ -5,7 +5,7 @@
register_module([
"name" => "Parsedown",
"version" => "0.11.5",
"version" => "0.12",
"author" => "Emanuil Rusev & Starbeamrainbowlabs",
"description" => "An upgraded (now default!) parser based on Emanuil Rusev's Parsedown Extra PHP library (https://github.com/erusev/parsedown-extra), which is licensed MIT. Please be careful, as this module adds some weight to your installation.",
"extra_data" => [
@ -515,6 +515,7 @@ class PeppermintParsedown extends ParsedownExtra
parent::__construct();
array_unshift($this->BlockTypes["["], "TableOfContents");
array_unshift($this->BlockTypes["["], "OneBox");
// Prioritise our internal link parsing over the regular link parsing
$this->addInlineType("[", "InternalLink", true);
@ -1484,7 +1485,7 @@ class PeppermintParsedown extends ParsedownExtra
protected function generateTableOfContents() : string {
global $settings;
error_log(var_export($this->tableOfContents, true));
$elements = [ $this->generateTableOfContentsElement($this->tableOfContents) ];
if($settings->parser_toc_heading_level > 1)
array_unshift(
@ -1572,6 +1573,52 @@ class PeppermintParsedown extends ParsedownExtra
return $result;
}
protected function blockOneBox($fragment) {
global $env, $settings, $pageindex;
if($fragment["indent"] > 0 || !$settings->parser_onebox_enabled) return;
if(preg_match('/^\[\[([^\]]*?)\]\]$/u', $fragment["text"], $matches) !== 1)
return;
// 1: Parse parameters out
// -------------------------------
$link_page = trim(str_replace(["\r", "\n"], [" ", " "], $matches[1]));
if(empty($pageindex->$link_page)) return;
$link_page_content = file_get_contents($env->storage_prefix.$pageindex->$link_page->filename);
$preview = $link_page_content;
if(mb_strlen($preview) > $settings->parser_onebox_preview_length)
$preview = mb_substr($preview, 0, $settings->parser_onebox_preview_length) . "";
// 2: Generate onebox
// -------------------------------
$result = [
"element" => [
"name" => "a",
"attributes" => [
"class" => "onebox",
"href" => "?page=".rawurlencode($link_page)
],
"elements" => [
[
"name" => "div",
"attributes" => [ "class" => "onebox-header" ],
"text" => $link_page
],
[
"name" => "div",
"attributes" => [ "class" => "onebox-preview" ],
"text" => $preview
]
]
]
];
return $result;
}
# ~
# Static Methods
# ~

View File

@ -74,6 +74,8 @@
"parser_ext_allow_anon": { "type": "checkbox", "description": "<p>Whether to allow anonymous users to render new diagrams with the external renderer. When disabled, anonymous users will still be allowed to recall pre-rendered items from the cache, but will be unable to generate brand-new diagrams.</p><p>Note that if you allow anonymous edits this setting won't fully protect you: anonymous users could edit a page and insert a malicious diagram, and then laer a logged in user could unwittingly invoke the external renderer on the anonymous user's behalf.", "default": false },
"parser_toc_heading_level": { "type": "number", "description": "The level of heading to create when generating a table of contents. Corresponds directly with the HTML h1-h6 tags. A value of 0 disables the heading.", "default": 2 },
"parser_mangle_external_links": { "type": "checkbox", "description": "Whether <code>[display text](./Page Name.md)</code> style links are transparently handled as internal links. Useful to increase compatibility to other systems that use this style of link such as <a href='https://js.wiki/'>Wiki.js</a>.", "default": false },
"parser_onebox_enabled": { "type": "checkbox", "description": "Whether oneboxing is enabled or not. Oneboxes are fancy renderings of an internal link with a preview of the text on the linked page. To generate a onebox, an internal link must be on it's own on a line with nothing before or after it.", "default": true },
"parser_onebox_preview_length": { "type": "number", "description": "The number of characters preview to display in oneboxes. ", "default": 250 },
"interwiki_index_location": { "type": "text", "description": "The location to find the interwiki wiki definition file, which contains a list of wikis along with their names, prefixes, and root urls. May be a URL, or simply a file path - as it's passed to file_get_contents(). If left blank, interwiki link parsing is disabled.", "default": null },
"clean_raw_html": { "type": "checkbox", "description": "Whether page sources should be cleaned of HTML before rendering. It is STRONGLY recommended that you keep this option turned on.", "default": true },
"all_untrusted": { "type": "checkbox", "description": "Whether to treat both page sources and comment text as untrusted input. Untrusted input has additional restrictions to protect against XSS attacks etc. Turn on if your wiki allows anonymous edits.", "default": false},

View File

@ -261,6 +261,10 @@ input[type=submit].large { width: 100%; box-sizing: border-box; padding: 0.5em;
.tag-list li { display: inline-block; margin: 1rem; }
.mini-tag { background: var(--tag); margin: 0 0.4em; padding: 0.2rem 0.4rem; color: var(--accent-b2); text-decoration: none; }
.onebox { display: flex; flex-direction: column;
border: 0.2em solid var(--tag); padding: 0.5em; text-decoration: none; }
.onebox-header { font-weight: bolder; font-size: 125%; border-bottom: 0.1em solid var(--tag); }
.grid-large { display: grid; grid-template-columns: repeat(auto-fit, minmax(25em, 1fr)); grid-auto-rows: min-content; grid-gap: 1em; justify-content: center;}
.theme-item { justify-self: center; text-align: center; }