sbrl / Pepperminty-Wiki

A wiki in a box
https://peppermint.mooncarrot.space/
Mozilla Public License 2.0
178 stars 20 forks source link

Implement [display](./pagename/subpage.md) style links #190

Closed RyanGreenup closed 3 years ago

RyanGreenup commented 4 years ago

Markdown Links are broken

Issue

Markdown links are not correctly followed by Pepperminty

Link Output Status
[Myfile](./MyFile.md) **mywiki.org/pepperminty/Myfile.md Broken
[[New-page]] mywiki.org/?page=New-Page Working
[MyFile](?page=MyFile) mywiki.org/pepperminty/?page=MyFile Working
Old Table, Mistaken My-bad sorry: Link Output Status
[Myfile](./MyFile.md) mywiki.org/pepperminty/?page=MyFile Broken
[[New-page]] mywiki.org/New-page.md Working
[MyFile](?page=MyFile) mywiki.org/pepperminty/?page=MyFile Broken

This means that if you import markdown content from elsewhere, the links won’t work and will instead point your browser to the source, obviously not what we want.

How to reproduce

On a fresh linux install:

  1. Install Apache + php modules
  2. Enable modules in php.ini
  3. use `<Files “peppermint.json”> ‘ to restrict access
  4. Login
  5. create a page with the following links:
* [mynewfile (broken)](./mynewfile.md)
* [mynewfile (working)](?page=mynewfile)
* [[my-new-file-wikilink]]

More Details

sbrl commented 4 years ago

Hey there! Thanks for reporting this. Right, so there are a number of different factors at work here. First, Pepperminty Wiki supports 2 different forms of link.

Case 1: An internal link

An [[Internal Link]]

Case 2: A 'regular link'

A [regular link](URL_HERE)

Explanation

In case 1, Pepperminty Wiki takes the text between the double square brackets and interprets it as a page name. A number of different processing steps happen here (such as support for display text and interwiki links amongst others), but ultimately a regular internal link is translated into ?page=%s, where %s is replaced with the following code:

$link_url = str_replace(
    "%s", rawurlencode($link_page),
    $this->internalLinkBase // equal to "?page=%s"
);

In case 2, the text is taken as-is and dropped directly into an <a href="URL_HERE">regular link</a> (where regular link is the display text). To this end, the following 2 cases should be equivalent:

[[New page]]
[Display text](?page=New page)

In your issue report, you give 3 examples in a table. I looked at each of those:

  1. This might work, but it depends on your circumstances. If your data directory is . (i.e. the same directory as index.php) - the default - it should either display the raw text of that page or offer it for download, depending on your web server configuration.
  2. This one does correctly work as expected on Pepperminty Wiki, but the output there is not identical to what Pepperminty Wiki produces. For that example, Pepperminty Wiki should produce something like <a href="?page=New-page">New-page</a>.
  3. I can't reproduce this one. I tested [MyFile](?page=MyFile), and Pepperminty Wiki correctly gave <a href="?page=MyFile">MyFile</a> as output, which directed me to create that page. You do need to ensure that index.php is treated as a default file (e.g. like index.html likely is) by your web server though, because otherwise it will generate a 404.

Are you saying that in other wikis, the [display](URL) syntax is used for internal links? If that's so, then I may be able to write a converter script to aid with importing content from other wikis. Such a script would be separate from Pepperminty Wiki though.

To this end, this seems like an import issue rather than an issue with the way that Pepperminty Wiki works itself though.

Even though, I'm interested to hear your thoughts on the above. As it stands, I'm still rather fuzzy on precisely what's wrong.

RyanGreenup commented 4 years ago

Sorry I must have wrote that table when I was tired, I've edited it to be more accurate.

RyanGreenup commented 4 years ago

Oh ok I think I better understand now, there are only two types of supported links:

  1. [link-text](www.google.com) will produce an external link
  2. [[link-name]] will produce an internal link
    • BTW this is almost totally compatible with vimwiki actually, playing around with it it's worked really well, you should mention that in the docs or if you'd like I can forward my config and you can make a footnote somewhere?

What I expected

Proposal

I think this behaviour should be changed so that this markdown:

Produces this link:

Because that way the md files could be edited in other editors and the links will be preserved, if a person wanted to link to the actual source.md the following could be used perhaps:

Other Programs

The only program, I know of, that supports [[link-name]] style links is Vimwiki when it is configured to markdown mode, I actually quite like that link style quite a lot so they should definitely be left as is.

In saying that however [this type of link](./path-to-file.md) can be followed in any other program and so for compatibility sake should be preserved, for example, these links can be followed in:

This behaviour would also be consistent with the venerable org-mode (as documented here), I must be the only person who uses org-roam and then occasionally does a pandoc --> md, but, it's super convenient to leverage the power of org-mode but cross platform support of Markdown.

Implementing

Implement Link Style

I think it would be quite nice to have that style of link work inside the wiki so that the source files could be edited externally from /srv/http/html, this would definitely be convenient.

A use case could possibly be syncing the content of Pepperminty with GitHub in which case being able to navigate through the links on GitHub would be very convenient.

Import Procedure

In saying that I don't know any PHP really, I use mostly R and Mathematica, so this could, for all I know, be super difficult and in which case perhaps this should simply be handled by an importing procedure to faciltate somebody wanted to move content from one system into pepperminty

This would be mostly fine because the links can still be followed with vimwiki.


Anyway I'd love to hear what you think about that, I think Pepperminty is awesome and I think better cross-compatability would only make it better.

sbrl commented 4 years ago

Ah, thanks for your reply. That's some detailed consideration there! I include my thoughts below.

Oh ok I think I better understand now, there are only two types of supported links:

That's correct. Note though that your external link example there would need a protocol prefix to point to another domain - i.e. [link-text](https://duckduckgo.com). This is just because of the way the HTML <a href=""></a> element works.

Proposal

Rewrite [New-Page](./New-page.md) to <a href="?page=New-page">New-page</a>

That's certainly possible. Currently Pepperminty Wiki does not override the default markdown link syntax provided by Parsedown though, so I'd have to override that to support that syntax natively.

I'm somewhat hesitent to support the syntax natively because of the complications involved with overriding the native Parsedown link syntax, because I'm pretty sure that Parsedown does some sort of sanitization there.

However, I'd be fine with writing a new importer script. Said script could contain a number of find-and-replace rules for rewriting the content of pages. It could have an input and output directory, and as it copies the content over it could rewrite the markdown to the format that Pepperminty Wiki supports.

That way we could start to 'support' other arcane syntaxes that Pepperminty Wiki already supports, but in a different form.

Regarding accessing the raw source of a page, the recommended way to do that is with the raw action. Such a URL would look like this:

https://wiki.example.com/path/to/wiki/?action=raw&page=URL_ENCODED_PAGE_NAME

This should serve the raw content of the specified page with the content type text/markdown. You could, for example, include a link to this in one of the navigation menus. The properties you're probably after for this are nav_links, nav_links_extra, and nav_links_bottom, which are documented here: https://starbeamrainbowlabs.com/labs/peppermint/peppermint-config-info.php#config_nav_links.

You'll need to edit peppermint.json for this (there's no GUI for it yet). It should be fairly intuitive. You could, for example, add the following array to your nav_links_extra:

[
    "See raw source",
    "?action=raw&page={page}"
],

{page} is automatically substituted in as the url-encoded page name.

From time to time, I update the navigation menus (most notable changes recently are the new mega menu and the watch button) - this is always noted in the changelog because you have to delete or update your peppermint.json because it keeps with the old value (it's not currently smart enough to auto-update it).

For the curious, the full HTTP API for Pepperminty Wiki is documented here.

In saying that however [this type of link](./path-to-file.md) can be followed in any other program and so for compatibility sake should be preserved, for example, these links can be followed in:

Wow, that's quite the list then. Adding import support for that kind of link sounds like a valuable exercise then.

I'm somewhat baffled though because that syntax interferes with the regular link syntax..... :P

Implement Link Style

Ah, that is an interesting use-case. You'd need to somehow handle peppermint.json though, because it contains your hashed password.

Implementing the link style though would be complicated though, due to reasons outlined above regarding overriding Parsedown's default external link handler which I would rather avoid.

Import Procedure

Yes, I think an import procedure would be the easiest solution here. I have a few proposals:

  1. A separate importer script. You'd download and run this separately.
  2. A command-line interface command. You could execute this any time you like to convert pages in-place. We'd also have to implement a CLI command for exporting (which we should perhaps do anyway).
  3. A button in the master settings to run the conversion import, with a link to the exporter to allow for taking backups.

Thinking about it, I think that options 2 and 3 would be the best options. While we could implement option 1 here, it would increase complexity for users having to download a second file. On the other hand, the clear separation between the importer and Pepperminty Wiki itself might be worth keeping.

What do you think?

sbrl commented 4 years ago

Oh yeah, and in one of the links you include there I see a very cool interactive directed graph of the wiki. That looks so cool - I'd love to implement something like that, but I think it's a little too far out of reach at the moment (especially for large wikis).

RyanGreenup commented 4 years ago

Hmm, I think importing importing/exporting would probably address the cross-compatability reasonably well, but it honestly sounds like more work than just redirecting the link right?

A use case I could imagine is storing the files on a git repo, editing through the git repo and then having pepperminty push/pull the repo every 5 minutes to merge the changes, (WikiJS does this and it's really convenient) this would mean that the push/pull would also have to include a import/export.

A CLI command would be better so the push/pull/import/export could be tied to a cron job, but in saying that it sounds like a lot more work than changing the link to redirect, but I know like 0 PHP, I'm more of a DataSci guy so you would have a much better understanding of this than me.

RyanGreenup commented 4 years ago

Oh yeah, and in one of the links you include there I see a very cool interactive directed graph of the wiki. That looks so cool - I'd love to implement something like that, but I think it's a little too far out of reach at the moment (especially for large wikis).

I actually use Org Roam Server quite a bit and I love it, I actually do use the graph overlay to browse through my iPad, that would be a really cool thing to implement eventually.

Honestly you sort of already can if you just did pandoc -f md -t org(but for the [](./link.md) support of course )

sbrl commented 4 years ago

A use case I could imagine is storing the files on a git repo, editing through the git repo and then having pepperminty push/pull the repo every 5 minutes to merge the changes, (WikiJS does this and it's really convenient) this would mean that the push/pull would also have to include a import/export.

Ah, ok - that makes sense. Thinking about it, I might be able to override the existing implementation and still keep the functionality - a bit like what I did for the table of contents & header customisations.

I'd be ok to implement this feature, but behind a setting that is disabled by default. If it turns out to be a really popular feature that lots of people use, I will consider turning it on by default.

sbrl commented 3 years ago

A bit out of the blue, but I've implemented this, @RyanGreenup! Experimental support for transparently handling [display text](./Page Name) support has now landed in the latest master.

It's disabled by default: enable the parser_mangle_external_links setting and delete the ._cache directory to enable it.