-
Notifications
You must be signed in to change notification settings - Fork 8
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Enh #67 Add collapsible blocks with summary and settings #95
base: develop
Are you sure you want to change the base?
Enh #67 Add collapsible blocks with summary and settings #95
Conversation
@schlagmichdoch Thanks for the updated PR and sorry for the delay. i am a bit careful with syntax extensions, because they have to be supported by all internal & external parsers (see internal RichText Parser here: https://community.humhub.com/s/contribution-core-development/wiki/Richtext#converter-classes) and can hardly changed or removed later on. |
How do you do this with the special syntax for internal links or mentions? |
Special features such as Mentioning or OEmbed must be supported by the MarkdownConverters in addition to Prosemirror support. See Extensions here: I am not sure atm which syntax ( Probably tags and some HTML support would be best. However, such a change would have many other effects. (user possibilities, parser support, security). |
I will take a look into that. The goal would be that the converter successfully transforms the markdown snippet into the correct
We would then be full circle where we started: #69 (comment) with an error regarding html_blocks not being supported. As you mentioned this would be a recipe for XSS attacks. Something like this could work if not properly filtered:
This is why I prefer the |
@schlagmichdoch Not sure how to procced here. Currently I would probably prefer the way via I'm worried that workarounds like |
I understand that.
My implementation is based on common marks implemention of fenced code blocks: https://spec.commonmark.org/0.30/#code-fence ```ruby startline=3 def foo(x) return 3 end ``` If you prefer GitHub Flavored Markdown we would need to make sure that html input that is parsed is stripped of all javascript tags like Interestingly, the newline tag already seems to be allowed eventhough html is off. Maybe there is a possibility to save html to the db without the need to switch html=true in render.js markdownItOptions:
I could look further into this. |
This seems to be a result of allowing breaks with markdownItOptions: let markdownItOptions = context && context.options.markdownIt || {html: false, breaks: true, linkify: true}; When switching breaks to false the linebreaks outside of tables are stripped away but they are still somehow preserved inside tables. |
One more data point for your decision: If switching html on, we would need an external sanitizer. Following their plugin link we get two plugins using a slightly different syntax:
The latter uses two different chars:
Default CLOSED:
I like to give the user two different styles to choose from but if you think the box style is enough we could also go that route. |
Hey @luke-, Have you had the time, to take a look at the markdown-it documentation? How would you like to proceed? Can I do something to help with the implementation? |
@schlagmichdoch Haven't had time for this topic yet. I hope I get to it soon. It's not something I want to decide on the fly, unfortunately. |
Hi @luke- ,
If there is anything I can do to help please don't hesitate to tell me here or send me an e-mail. |
@schlagmichdoch Sorry, for your (syntax) extension I can't say concrete anything yet. Hopefully we will then have a bit more capacity to address the issue of Markdown extensions (either HTML or MarkdownSyntax). |
Thanks for the update! I would appreciate it, if you could keep me in the loop and tell me if I can do anything to speed things up or clarify anything. |
Hi @luke- , |
@schlagmichdoch Unfortunately not yet. I also don't know when and if/how we will tackle the issue. Maybe it could be a solution for you - in the meantime - to fork the prosemirror project first and manually overwrite the editor in your installation? |
I think this isn't a bad idea, but I think it would be a nifty idea to do something similar to the Katex module for this. |
@ArchBlood Thanks for joining the discussion! Why do you think collapsible sections would be better as a Katex-like plugin rather than as part of the richtext editor (prosemirror) itself? |
The Katex module is a part of @humhub-contrib which is under the @humhub management, the module is installed just like any other module, the only difference with this module is that you must build the js bundle, see the README.md. As to why I think it would be better as a module, I think it would be better to keep the current ProseMirror editor as it is without complexing it anymore than it should be and extend as part of a module so that it's an optional method that can be installed and uninstalled based on HumHub instance preference. |
Sounds promising! If I understand it correctly, the Katex module only renders latex syntax written with the editor. Would I be able to add buttons/pop-ups to the ProseMirror GUI as well or would I only be able to render some special syntax? |
I think it would be possible with extending an existing editor class; |
Sounds promising! Not sure when I will have time to get into that though. As food for thought: It would also be possible to implement this alongside admonitions: https://squidfunk.github.io/mkdocs-material/reference/admonitions/#admonition-icons-fontawesome This would allow users to add info or warning boxes on wiki pages and alike. All of them can be rendered collapsible, either collapsed or not collapsed. There are also two markdown-it plugins, although they are both missing the collapsible admonations: |
@luke- Do you think this is doable via a Humhub module? I wonder if this would only include extending the rendering of a certain syntax (as with the LaTeX module) or whether I could implement a functioning editor node as is the case with this pull request. Any ideas? I'd prefer to implement this via a module as it would be easy to install / deinstall for admins, but I'm unsure whether it's worth it and whether everything would work in the end. |
Adding such features as a Markdown extension would be a good and preferred solution. Unfortunately, there is currently no such ready to use module API here. However, I think the foundation for this has already been created on the PHP side with Markdown Extensions. https://github.com/humhub/humhub/tree/master/protected/humhub/modules/content/widgets/richtext/extensions |
What would you do in my place? Is this already doable as a HumHub module or is there some work needed to add this API to the humhub code? |
Good question. Unfortunately, I can't estimate how complex it is to make the Markdown features pluggable. If we had such an Plugin API, we could, for example, put a We could probably provide some help for the basic structure of the module. But we need a prototype on the prosemirror side first. (Plugin) |
I believe we'd probably also need a convertible process if we were going the pluggable route, but as you stated without a strong solid Plugin API this would be rather difficult, but would be intriguing to say the least. 🤔 |
I'd suggest something similar to my current module that is under review by HumHub even though it's in its infancy, the PluginManager is rather powerful and will continue to mature in the future. |
@ArchBlood can you provide a link with more information or explain what that PluginManager of yours is about? |
Currently not due to it being part of a paid module that's in active development. |
But currently the idea behind the PluginManager is to allow for another layer of addons to be possible within my forums module, it currently works as expected as long as the plugin follows a simple file structure which is similar to that of a HumHub module. Plugin Diagramgraph TD
A[example] --> B[assets]
A --> C[controllers]
A --> D[models]
A --> E[views]
A --> F[Plugin.php]
A --> G[config.php]
A --> H[plugin.json]
A --> I[README.md]
B -->|"CSS, JS, images"| B1[Static files]
C -->|"Action handlers"| C1[Controller classes]
D -->|"Data structures"| D1[Model classes]
E -->|"Templates"| E1[View files]
F -->|"Main plugin class"| F1[Plugin logic]
G -->|"Configuration"| G1[Plugin settings]
H -->|"Metadata"| H1[Plugin information]
I -->|"Documentation"| I1[Usage instructions]
Current example for such a plugin is found here, but again the PluginManager itself is built inside of my paid module so I can't really just throw it out into the world. But the idea of creating a Plugin Management module could be in theory possible to create. I could however provide a possible example for a PluginManager for ProseMirror Example
|
@luke- @schlagmichdoch I've been working on a similar method within a helper class which provides similar functionalities to this within my forums module, where I can confirm that it is very possible to implement this within a module, but requires some more testing of <?php
namespace humhub\modules\content\widgets\richtext;
use humhub\components\Widget;
use humhub\modules\content\widgets\richtext\RichText;
/**
* RichTextWidget processes rich text content using HumHub's RichText class.
*
* This widget can be used to output or convert rich text content. It uses
* RichText::output() when no format is specified, and RichText::convert()
* when a specific format is provided.
*/
class RichTextWidget extends Widget
{
/** @var string The rich text content to process */
public string $text;
/** @var string|null The format to convert the text to (null for default output) */
public ?string $format = null;
/** @var array<string, mixed> Additional options for text processing */
public array $options = [];
/**
* Runs the widget and returns the processed text.
*
* @return string The processed rich text content
*/
public function run(): string
{
return self::processText($this->text, $this->format, $this->options);
}
/**
* Processes the given rich text content.
*
* If no format is specified, it uses RichText::output().
* If a format is specified, it uses RichText::convert().
*
* @param string $text The rich text content to process
* @param string|null $format The format to convert the text to (null for default output)
* @param array<string, mixed> $options Additional options for text processing
* @return string The processed rich text content
*/
public static function processText(string $text, ?string $format = null, array $options = []): string
{
if ($format === null) {
return RichText::output($text, $options);
}
return RichText::convert($text, $format, $options);
}
} |
Why this PR
See #67 for introduction and goal.
Supersedes #69 and #71 as most of it is rewritten everything is rebased into two commits and this PR is based on the develop instead of the master branch.
My contractor uses the humhub wiki as a place for documentation that can get quite long, messy and repetitive. He really craves a feature to have collapsible sections and asked me to give it another try eventhough I have not heard much from you guys. I would really like this feature to get implemented!
I have seen that you have actively worked on this repository a lot for some time now so I hope this is a good time to add this PR.
I really like the new possibility to be able to edit the markdown itself and switch between these two editor modes! Kudos for implementing this!
What does this PR include
This is now a fully working addition to humhub-prosemirror! It works similar to editing of images and links and includes some options for even more flexibility for the user. I can see this beeing used to tidy up very long pages or create FAQs
A collapsible block is added that behaves similar to blockquotes:
It is possible to nest multiple multiple blocks into each other, to drag and drop blocks (might need to select the block with the Escape key or via ctrl/cmd-click), to break out of the block using backspace while inside a block or delete a block
A menu is opened to edit the summary (which supports markdown), choose whether the collabsible block should be parsed open or closed after saving the page and what style is preferred for the block. For the style the user can choose between "default" and "box" although there could be more possibilities in the future to choose from. The look of these styles can be changed by themes with css
Markdown
The markdown-it-container is used to save the
<details><summary>
tags as markdown without using html tags.This is always shown
This content is shown by default
This is always shown
This content is hidden by default
With Markdown
support
This content is
hidden
by defaultOuter summary
Before nested collapsible block
Nested summary
Inside nested collapsible block
After second collapsible block
Styling
Both styles need further css styling added to humhubs main repository:
humhub/static/less/markdown.less
and add the following lines below the blockquote styling (line 94):grunt build-theme
Screenshots
Default Style
Box Style
Edit Menu