CodeMirror custom mode - how to apply styles on keywords? - codemirror

I'm trying to write my own CodeMirror mode as documented here.
My objective is to change the color of specific keywords. For example, any "aaa" word needs to be red and any "bbb" word needs to be blue. Any other words need to have the default color.
This is my unsuccessful attempt (see jsfiddle). How to make this work?
HTML:
<textarea rows="4" cols="30" id="cm" name="cm">aaa bbb ccc</textarea>
CSS:
.style1 { color: red; }
.style2 { color: blue; }
Javascript:
CodeMirror.defineMode("mymode", function() {
return {
token: function(stream,state) {
if (stream.match("aaa") ) {
console.log("aaa found");
while ((ch = stream.next()) != null)
if (ch == " " && stream.next() == " ") break;
return "style1";
}
else if (stream.match("bbb") ) {
console.log("bbb found");
while ((ch = stream.next()) != null)
if (ch == " " && stream.next() == " ") break;
return "style2";
}
else
return null;
}
};
});
var editor = CodeMirror.fromTextArea(document.getElementById('cm'), {
mode: "mymode",
lineNumbers: true
});

You had two problems.
CodeMirror prefixed cm- to classes used to style tokens. The styles in your CSS have to account for that.
You were skipping the rest of the line after finding "aaa" or "bbb", althrough your description of your goal sounds like you didn't want to do that.
I've fixed both in the jsfiddle. You may also want to only match full words (currently fooaaabar also has aaa highlighted). To do that, first have your tokenizer read a whole word (stream.eatWhile(/\w/)), and then see if the resulting word is one of the words you are looking for (stream.current() == "aaa").

Related

How to create customized Add Comment in Word-Addins Taskpane?

I am creating an MS-Word Add-ins for Word for mac and I have to create a custom comment section with a task pane so I have created one textbox and create a button on click on button comment is added to that selected text.
I find many articles but don't work for me so that I attach a sample code below.
HTML File
<div class="padding">
<textarea id="areaDiv"></textarea>
<button id="addComment">Add Comment</button>
<div id="errorDiv"></div>
</div>
**JS File**
Office.onReady(function () {
// Office is ready
$(document).ready(function () {
// The document is ready
// Use this to check whether the API is supported in the Word client.
if (Office.context.requirements.isSetSupported('WordApi', '1.1')) {
// Do something that is only available via the new APIs
$('#addComment').click(addComment);
$('#supportedVersion').html('This code is using Word 2016 or later.');
}
else {
// Just letting you know that this code will not work with your version of Word.
$('#supportedVersion').html('This code requires Word 2016 or later.');
}
});
});
// Function that writes to a div with id='message' on the page.
function addComment() {
Office.context.document.getSelectedDataAsync(Office.CoercionType.Text,
{ valueFormat: "unformatted", filterType: "all" },
function (asyncResult) {
var error = asyncResult.error;
if (asyncResult.status === Office.AsyncResultStatus.Failed) {
write('');
}
else {
var range = asyncResult.value;
write(range);
}
});
}
function onError(error) {
$('#errorDiv').text(error.name + ' ' + error.code + ': ' + error.message);
}
function write(range) {
$('#errorDiv').text(range);
var text = $("#areaDiv").val();
if (range != null && range != "" && text != null && text != "") {
$('#errorDiv').text(range + " " + text);
var document = Office.context.document.properties.comments;
document.add(range, text);
$("#areaDiv").val("");
}
}
Here there is no error but there is an issue of no comment is set the selected text and not goes in the catch block.
If anyone has an idea about this then it helps me a lot.

bootstrap date-picker paste control

Even I set forceParse option to false, when I paste a text into the input box, it auto set to today.
For typing, I can type in any letters, but for the pasting (ctrl + v) is not working, if the pasting text is not in the correct format then.
How can I disable(ignore) the paste auto-collect action so that I can paste any letter into the input box? I do formatting manually when blurring from the input box.
$('#yourcalenderid').datepicker({
forceParse: false
});
http://bootstrap-datepicker.readthedocs.io/en/latest/options.html#forceparse
As commented, in bootstrap-datepicker.js line 508 change it to the following
paste: function(e){
/* var dateString;
if (e.originalEvent.clipboardData && e.originalEvent.clipboardData.types
&& $.inArray('text/plain', e.originalEvent.clipboardData.types) !== -1) {
dateString = e.originalEvent.clipboardData.getData('text/plain');
} else
if (window.clipboardData) {
dateString = window.clipboardData.getData('Text');
} else {
return;
}
this.setDate(dateString);
this.update();
e.preventDefault(); */
},

How to force cursive display in ckeditor while typing

<!DOCTYPE html>
<html>
<head>
<script src="http://cdn.ckeditor.com/4.6.2/standard/ckeditor.js"></script>
</head>
<body>
<textarea name="editorUrdu"></textarea>
<script>
CKEDITOR.plugins.addExternal( 'easykeymap', '/ckeditor/plugins/easykeymap', 'plugin.js' );
CKEDITOR.replace( 'editorUrdu',{
extraPlugins: 'easykeymap',
contentsLangDirection: 'rtl'
});
</script>
</body>
</html>
/**
* This work is mine, and yours. You can modify it as you wish.
* #Author: Roni Saha<roni.cse#gmail.com>
*
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
*/
CKEDITOR.plugins.add('easykeymap',
{
requires : ['wysiwygarea'],
init: function (editor) {
//var keyMaps = CKEDITOR.tools.extend({}, editor.config.easykeymaps || {}, true);
//Not using keymap specification from config variables, but using internally defined ones from param below
function isRegisteredKeystroke(code) {
if(typeof editor.keystrokeHandler.keystrokes[code] != 'undefined') {
console.warn("the keystroke : " + code + " is being attached to another event")
return true;
}
return false;
}
var sm1 = []; var en1 = [];
sm1[192]="؏"; en1[192]="~";
sm1[49]="۱"; en1[49]="1";
sm1[50]="۲"; en1[50]="2";
sm1[51]="۳"; en1[51]="3";
sm1[52]="۴"; en1[52]="4";
sm1[53]="۵"; en1[53]="5";
sm1[54]="۶"; en1[54]="6";
sm1[55]="۷"; en1[55]="7";
sm1[56]="۸"; en1[56]="8";
sm1[57]="۹"; en1[57]="9";
sm1[48]="۰"; en1[48]="0";
sm1[189]="-"; en1[189]="-";
sm1[187]="="; en1[187]="=";
//sm1[8]=""; en1[8]="";//BACKSPACE
var sm2 = []; var en2 = [];
sm2[9]=""; en2[9]="";//TAB
sm2[81]="ق"; en2[81]="Q";
sm2[87]="و"; en2[87]="W";
sm2[69]="ع"; en2[69]="E";
sm2[82]="ر"; en2[82]="R";
sm2[84]="ت"; en2[84]="T";
sm2[89]="ے"; en2[89]="Y";
sm2[85]="ء"; en2[85]="U";
sm2[73]="ی"; en2[73]="I";
sm2[79]="ہ"; en2[79]="O";
sm2[80]="پ"; en2[80]="P";
sm2[219]="'"; en2[219]="{";
sm2[221]="ﷲ"; en2[221]="}";
sm2[220]="÷"; en2[220]="\\";
var sm3 = []; var en3 = [];
//sm3[20]=""; en3[20]="";//CAPSLOCK
sm3[65]="ا"; en3[65]="A";
sm3[83]="س"; en3[83]="S";
sm3[68]="د"; en3[68]="D";
sm3[70]="ف"; en3[70]="F";
sm3[71]="گ"; en3[71]="G";
sm3[72]="ح"; en3[72]="H";
sm3[74]="ج"; en3[74]="J";
sm3[74]="ک"; en3[75]="K";
sm3[76]="ل"; en3[76]="L";
sm3[186]="؛"; en3[186]=":";
sm3[222]=","; en3[222]="\"";
sm3[13]=""; en3[13]="";//ENTER
var sm4 = []; var en4 = [];
//sm4[16]=""; en4[16]="";//SHIFT
sm4[90]="ز"; en4[90]="Z";
sm4[88]="ش"; en4[88]="X";
sm4[67]="چ"; en4[67]="C";
sm4[86]="ط"; en4[86]="V";
sm4[66]="ب"; en4[66]="B";
sm4[78]="ن"; en4[78]="N";
sm4[77]="م"; en4[77]="M";
sm4[188]="،"; en4[188]="<";
sm4[190]="۔"; en4[190]=">";
sm4[191]="/"; en4[191]="?";
sm4[16]=""; en4[16]="";//SHIFT
var keyBoard = {};
keyBoard.Row1 = { "sm" : sm1, "en" : en1 };
keyBoard.Row2 = { "sm" : sm2, "en" : en2 };
keyBoard.Row3 = { "sm" : sm3, "en" : en3 };
keyBoard.Row4 = { "sm" : sm4, "en" : en4 };
function getMappedCharacter(code) {
console.info(code);
if (typeof keyBoard.Row1.sm[code] != 'undefined')
return keyBoard.Row1.sm[code]
else if (typeof keyBoard.Row2.sm[code] != 'undefined')
return keyBoard.Row2.sm[code]
else if (typeof keyBoard.Row3.sm[code] != 'undefined')
return keyBoard.Row3.sm[code]
else if (typeof keyBoard.Row4.sm[code] != 'undefined')
return keyBoard.Row4.sm[code]
else
return false;
}
editor.on( 'key', function( event ) {
var t = event.target;
var mappedCode = getMappedCharacter(event.data.keyCode);
if (mappedCode !== false && !isRegisteredKeystroke(event.data.keyCode)) {
event.cancel();
if(typeof mappedCode == 'function') {
return mappedCode.call(editor, editor);
}
editor.insertText(mappedCode);
}
} );
}
});
I'm using ckeditor for allowing my users to input Urdu text. Like Arabic, Urdu is cursive, and uses distinct ligatures when joined.
I'm using the
editor.on( 'key', function( event ))
event to intercept the
event.data.keyCode
and replace it using
editor.insertText()
function.
So, e.g. if the user types L and A, I replace it with the Urdu
ا (U+0627)
and
ل (U+0644).
Now, after being typed, they both appear as distinct characters, separate from each other. I can press space, or enter, and they both remain as they are. But I would like them to be replaced with their proper equivalent ligature ﻻ which is FEFB in this unicode chart
I see that ckeditor automatically correct this if I switch to Source view. There, inside the <p> block, it shows the separate, disjointed letter's already replace with proper cursive ligature. And it keeps it that way when I switch back from Source view. But whatever is causing this to happen, how can I trigger that to happen while typing?
Attaching images also.
After typing
After going to source view
After returning from source view
When ever you type L and A , editor.insertText() is just append it as two separate stings, instead of combining into one.
<p>"ل"
"ا"
<br>
</p>
that why its not producing desired output.
Added these two line
var $pTag = editor.getSelection().getRanges()[0].startContainer.$; // accessing the p tag
$pTag.innerText = $pTag.innerText+mappedCode; // modifing the inner text
replacing
editor.insertText(mappedCode); // in editor.on( 'key', function( event )
will output as "لا"
above fix has some issues to deal with like linebeak(new line)
Updated
replace the below snippet
var $pTag = editor.getSelection().getRanges()[0].startContainer.$;
var innerText =$pTag.innerText; // accessing the p tag data
$pTag.innerText = ""; // removing the existing data
editor.insertHtml(innerText+mappedCode); // concat with new string
with
editor.insertText(mappedCode); // in editor.on( 'key', function( event )
Example: codepen

How do I make multiline hilighter on draft-js?

Now I make markdown highlighter.
Highlight inline is not so difficult. I use CompositeDecorator to rewrite text. https://facebook.github.io/draft-js/docs/advanced-topics-decorators.html
But I can't use multiline syntax (for example, codeblock). By default, newline becomes next block and decorator is handled by block to block.
Below image is example of my implementation. I can't decorate codeblock syntax.
How do I make multiline highlighter on draft-js?
Depends on what 'Highlight' style you want. Mostly the inline style should be enough if you just want some color or font size. check the color example.
While for block style, you need a custom CSS class and map the block to your class, refer this.
I found work around. Detecting markdown codeblock by dand on blockRendererFn.
// use blockRedererFn
<Editor
blockRendererFn={(block) => blockRenderer(block, this.state.editorState)}
editorState={this.state.editorState}
/>;
// detect code block and add fontFamily: monospace
// Example
//
// ```
// here
// ```
function blockRenderer(contentBlock, editorState) {
const type = contentBlock.getType();
if (type === "unstyled") {
const allText = editorState.getCurrentContent().getPlainText();
const allCount = countCodeBlockHeader(allText);
if (allCount > 0 && allCount % 2 === 0) {
const contentText = contentBlock.getText();
const [before, after] = allText.split(contentText);
const beforeCount = countCodeBlockHeader(before);
const afterCount = countCodeBlockHeader(after);
if (beforeCount % 2 === 1) {
if (afterCount % 2 === 1) {
return {
component: (_props) => {
return <code style={{
fontFamily: "monospace",
direction: "ltr",
unicodeBidi: "bidi-override",
}}>{contentText}</code>;
},
editable: true
};
}
}
}
}
}
function countCodeBlockHeader(text) {
return text
.split("\n")
.filter(l => l.match(new RegExp("^(```)")))
.length;
}
but it's dirty.

WYSIHTML5 editor does not focus the editable area while inserting unordered list in Chrome

In WYSIHTML5 editor, when we add unordered list, it does not focus on the editable area in the Google Chrome browser. However, it works fine for other options such as bold, italic, etc. I have searched, but have been unable to find a solution for this bug.
In WYSIHTML5 js, search line wysihtml5.commands.insertUnorderedList and further look for
composer.commands.exec("formatBlock", "div", tempClassName);
tempElement = doc.querySelector("." + tempClassName);
isEmpty = tempElement.innerHTML === "" || tempElement.innerHTML === wysihtml5.INVISIBLE_SPACE;
composer.selection.executeAndRestoreSimple(function() {
list = wysihtml5.dom.convertToList(tempElement, "ul");
});
if (isEmpty) {
composer.selection.selectNode(list.querySelector("li"));
}
and comment or remove the condition part like :
composer.commands.exec("formatBlock", "div", tempClassName);
tempElement = doc.querySelector("." + tempClassName);
isEmpty = tempElement.innerHTML === "" || tempElement.innerHTML === wysihtml5.INVISIBLE_SPACE;
composer.selection.executeAndRestoreSimple(function() {
list = wysihtml5.dom.convertToList(tempElement, "ul");
});
//if (isEmpty) {
composer.selection.selectNode(list.querySelector("li"));
//}
It worked for me coz the condition isEmpty = tempElement.innerHTML === "" || tempElement.innerHTML === wysihtml5.INVISIBLE_SPACE; can never become true as we have inserted unordered list and editable area is not blank after that. Good luck..!!