I want to add a markdown editor for users to post their answers into my page. I've found TinyMCE but there is a problem with it: I don't know how to implement markdown editor with TinyMCE.
Is there anybody who has experience with this? Please show me how to setup a markdown editor with it.
It looks like the Text Pattern Plugin can do this:
This plugin matches special patterns in the text and applies formats or executed commands on these patterns.
…
tinymce.init({
selector: "textarea", // change this value according to your HTML
plugins: 'textpattern',
textpattern_patterns: [
{start: '*', end: '*', format: 'italic'},
{start: '**', end: '**', format: 'bold'},
{start: '#', format: 'h1'},
{start: '##', format: 'h2'},
{start: '###', format: 'h3'},
{start: '####', format: 'h4'},
{start: '#####', format: 'h5'},
{start: '######', format: 'h6'},
{start: '1. ', cmd: 'InsertOrderedList'},
{start: '* ', cmd: 'InsertUnorderedList'},
{start: '- ', cmd: 'InsertUnorderedList'}
]
});
Note that the plugins key here fixes a typo in the upstream documentation, which uses plugin instead.
TinyMCE does not currently support a markdown mode with their editor, however I just recently was in the situation where I needed a markdown editor and wanted to use tinymce for it.
You will have to add a markdown package to your project. I recommend MarkdownIt, which I found from this list of recommendations. You can use any one of the recommendations from the link, just change the MarkdownIt usage with your markdown library in the code examples below.
I do not recommend Chris' approach because it's not very user friendly - the user needs the ability to save text with markdown in it and expect it to render the proper element when it is rendered. To have to press space or enter after each element to watch it change into a WYSIWYG style element is not user friendly. As such, if you take this approach you should actually remove the textpattern plugin and the textpattern_patterns configuration.
What you will want to do is to configure the setup function in your tiny config to listen to change events, and then pass the content through your markdown parser before returning the value to whatever needs it. You will also want to set menubar, toolbar, and statusbar to false.
var editorHandlerTimeout;
var MarkdownIt = require('markdown-it')
tinymce.init({
el: 'el',
menubar: false,
toolbar: false,
statusbar: false,
setup: function (editor) {
editor.on('paste change input undo redo', function() {
// the timeout is to throttle how often this runs while typing
clearTimeout(vm.editorHandlerTimeout);
vm.editorHandlerTimeout = setTimeout(function () {
var md = new MarkdownIt() // or any other markdown library
var contentFromEditor = editor.getContent()
//MarkdownIt adds its own paragraph tags, so strip the ones from tinymce
if (contentFromEditor.startsWith('<p>'))
contentFromEditor = contentFromEditor.substring(3)
if (contentFromEditor.endsWith('</p>'))
contentFromEditor = contentFromEditor.substring(0, contentFromEditor.length - 4)
var contentFromMdIt = md.render(contentFromEditor)
// markdown-it inserts the html encoded values for these (this might be a bug), so we will want to replace them since we will be rendering as html
contentFromMdIt = contentFromMdIt.replace(/>/g, '>')
.replace(/</g, '<')
.replace(/&/g, '&')
// time to do something with your rendered markdown text
// im in vuejs, so I emit the result as 'input' which allows my markdown editor to work as a v-model
vm.$emit('input', contentFromMdIt)
})
})
})
})
Also, it is highly recommended to add a preview to your markdown editor, as the majority of users are unfamiliar with markdown. Make the preview feature simple and accessible, and just render their output as html so they can see what is happening.
Seems TinyMCE has a Markdown plugin for their editor now
https://github.com/vaidhyanathan93/Markdownfortinymce/blob/master/markdown/plugin.js
https://www.tiny.cloud/labs/markdown/
Tiny Markdown is a markdown syntax plugin for TinyMCE, providing
flexible rich text and markdown content creation options for authors,
and also provides robust, reliable markdown output for developer
projects.
Related
I'd like Headings to have a pre-defined font. How can I do this?
Any help, much appreciated. 🙂
TinyMCE has a range of formatting options available, and the formatting includes elements like headings. The docs have some examples -> https://www.tiny.cloud/docs/configure/content-formatting/
tinymce.init({
selector: 'textarea',
formats: {
heading: { inline: 'h1', styles: { 'font-weight': 'bold', 'color': 'blue' } }
}
});
You can use CSS in the key: value format, I believe in a comma separated list. Check the section in the docs on block formats, and inline formats, since each one has different implications to the text in the editor.
!Important! UPDATE:
Using the above method will style the headings, but won't create an easy-to-use default font. Another and better way to manage this is to use the content_css option to setup a default style for those heading elements (docs).
The first solution above would mean if you had a style update, you would need to change every header individually. However, any style changes to the content_css option would change each heading tag instance.
Example
tinymce.init({
selector: 'textarea',
formats: {
content_css: "pathway/to/style.css",
}
});
I have SCRIPT and BR listed in extended_valid_elements but those HTML tags are still being removed. I have extended_valid_elements: "script[src|async],br[clear]" I also have allow_script_urls: true
TinyMCE Community Version: 5.0.0-1 (2019-02-04)
This seems to work just fine if you use:
extended_valid_elements: "script"
Here is a working example: https://fiddle.tiny.cloud/dyhaab
EDIT/UPDATE: If you want to allow attributes on a tag you need to explicitly list them. The documentation provides a variety of examples (https://www.tiny.cloud/docs/configure/content-filtering/#extended_valid_elements)
For your specific case you would want:
extended_valid_elements: "script[src]"
Here is an updated fiddle: https://fiddle.tiny.cloud/dyhaab/1
I installed the TinyMCE editor on top of a fresh Connections 6.5.1 installation. While syntax highlighting using the codesample plugin is enabled out of the box, it works only for certain languages. I found the codesample_languages, which were overriden like described in this article.
externalPlugins: [{
name: "codesample",
url: "/connections/resources/web/tiny.editors.connections/tinymce/plugins/codesample/plugin.min.js",
settings: {
codesample_global_prismjs: true,
codesample_languages: [
{ text: 'ASP.NET (Core)', value: 'aspnet' },
{ text: 'Apache', value: 'apacheconf' },
{ text: 'Bash', value: 'bash' },
{ text: 'C#', value: 'csharp' },
{ text: 'C++', value: 'cpp' },
{ text: 'CSS', value: 'css' }
]
}
}
]
Now its possible to select them in the editor. But they don't work because the embedded PrismJS from the editor only support extend, insertBefore, DFS, markup, xml, html, mathml, svg, css, clike, javascript, js, c, csharp, cs, dotnet, cpp, java, markup-templating, php, python, py, ruby, rb.
So I loaded the missing plugins from a cdn, e.g. the batch plugin. Including it in header.jsp doesn't work because the Prism namespace is not initialized. In the footer.jsp it seems to have no effect, assuming that PrismJS is already initialized.
Customizing the webresource archive
PrismJS seems to be fetched from https://cnx65.internal/connections/resources/web/tiny.editors.connections/render/prism.js so I extracted tiny.editors.connections_4.2.1.1.jar in /opt/IBM/shared/provision/webresources, modified resources/render/prism.js and re-packed those folter:
[centos#cnx65 webresources]$ zip -r tiny.editors.connections_4.2.1.1.jar resources/render/
After restarting Common and Wiki (the application where I'm testing TinyMCE), there is still no syntax highlighting for Bash. Altough when I'm navigating to https://cnx65.internal/connections/resources/web/tiny.editors.connections/render/prism.js, I see the Bash plugin code which I have inserted. To see which languages are avaliable, I append
console.log(Object.keys(Prism.languages))
at the end of the file. This gave me an array containing bash. So the plugin is avaliable, but why doesn't TinyMCE show syntax highlighting?
PrismJS was not the problem: Connections changed the way how they use PrismJS. In the past, they just append the class so that we need to include prisms css/js files in the rendered page (e.g. header/footer.jsp). But it seems that since 6.5.1 (CR1), the TinyMCE editor calls PrismJS when a code block is changed. After pressing save, the editor places the entire parsed highlighted HTML with inline css in its HTML.
As a consequence, it's not enough to reload the rendered page in read mode because it was rendered before the lighlight plugin was added. The highlighting works when we click on edit and make a double click in the code block. Then click save in the code modal and also in the wiki page. Now it works:
Highlight in the editor, too
I found out that resources/render/prism.js is responsible for the readonly view, but not the editor itself. If we only add the plugin there, we get no highlighting in the edit view
To fix this, we need to edit resources/tinymce/tinymce-bundle.min.js inside the TinyMCE archive. Add the plugin JS code in the plugins section. For example, before Prism.languages.csharp=.... Now add the modified file to the archive
[centos#cnx65 webresources]$ sudo zip -r tiny.editors.connections_4.2.1.1.jar resources/tinymce/tinymce-bundle.min.js
and restart common + the application you're using (e.g. Wikis). Now the highlighting works both in the readonly view as well inside the editor:
By default TinyMCE (4) has a "Paragraph ▼" dropdown, and if you click on it you get a list of formatting options ("Paragraph", "Heading 1", etc.).
I'd like to be able to do two things. First, I want to change the options and their names (eg. to "Normal" and "Heading"), and I found the block_formats option which does exactly that:
block_formats: 'Normal=p;Heading=h1'
However, I'm stuck on thing #2: adding classes to the generated elements. Instead of plain <h1> elements, when someone picks "Heading" I want to generate a <h1 class="heading">.
I thought maybe this would work:
block_formats: 'Normal=p;Heading=h1.heading'
... but it doesn't, and I haven't been able to find any other option that would let me do this. Then again, the TinyMCE documentation isn't always the easiest place to find answers, which is why I came here.
Does anyone know how I configure TinyMCE to have a "Paragraph ▼" dropdown with customized names AND custom classes on the generated elements?
I never did find a way to do this, so what I wound up doing instead was remove the block format drop-down entirely and replace it with the (custom) format dropdown. In other words I:
removed the formatselect from the toolbar1 config (removing the un-configurable normal formatting dropdown)
added the custom format dropdown (styleselect) to the toolbar1 config
defined a style_formats config entry with my custom styles
The style_formats config looked like this:
style_formats: [
{
title: 'Header',
inline: 'span',
classes: 'someClass',
styles: {someStyle: '5px'}
},
], // next style would go here
There were only two downsides of this approach. First, the dropdown now says "Formats", and I don't seem to be able to configure that anywhere. However I do have a single formatting dropdown, with only the options I want, and those options add the desired classes to the formatted text, so the dropdown's name isn't a big deal.
The second issue was that TinyMCE uses an <iframe>, which prevents it from using our stylesheet. I could have written a stylesheet for TinyMCE and then appended it to the <iframe> (or used some TinyMCE mechanism, if there is one) ... but I'm lazy so I just used style: entries for each custom format to define the style.
Using the wysihtml5 editor, is there a way to disable the parser rules for pasting, or simply paste plain text? Such that only plain text, with no tags or any other formatting is pasted? Commenting out my parser rule does not work for me because I still want pre-populated text (with anchor and line-break tags) to be parsed by my parser rules. Although not essential, I also would like the editor to detect URLs and create anchors as I type, but not necessarily when pasting.
The reason I want to do this is because a lot of garbage characters (like new lines %0A and span tags) are pasted when pasting using the parser rules (specially from MSWord, but also from web content). Pasting plain text would prevent random hidden content from being pasted.
Just for reference, my parser rules are extremely simple:
var wysihtml5ParserRules = {
tags: {
br: {},
a: {
set_attributes: {
target: "_blank",
rel: "nofollow"
},
check_attributes: {
href: "url" // important to avoid XSS
}
}
}
};
If you want plain text all the time, go to your project Scripts and you will find file wysihtml5-toolbar.min.js
Find text
wysihtml5.dom.getPastedHtml=function(a){var b;return
a.clipboardData&&(wysihtml5.lang.array(a.clipboardData.types).contains("text/html")?b=a.clipboardData.getData("text/html"):wysihtml5.lang...
Change b=a.clipboardData.getData("text/html") to "text/plain"