Paste should result in a clean Markdown code

* jquery.htmlClean.min.js: * in order to paste from any(?) document

* rangy-selectionsaverestore.js: required by hallo html cleanup

* App.master: * A link to awesome fonts
* a hint, to engage to invoice :-)

* rangy-core.js: using the bower installed one

* to-markdown.js: using the new code, came from the `npm start`
  process

* Edit.aspx: fixes copy/paste from LibreOffice writter colored text.

* Web.csproj: using new javascript references to:
rangy-core, rangy-selectionsaverestore jquery.htmlClean

* mdd_help.htm:
* mdd_styles.css:
* rangyinputs-jquery-1.1.2.js: obsolete
vnext
Paul Schneider 9 years ago
parent 6bf32bf3c5
commit f4329d6176
11 changed files with 4179 additions and 684 deletions

@ -1,3 +1,29 @@
2015-09-27 Paul Schneider <paul@pschneider.fr>
* jquery.htmlClean.min.js: * in order to paste from any(?)
document
* rangy-selectionsaverestore.js: required by hallo html
cleanup
* App.master: * A link to awesome fonts
* a hint, to engage to invoice :-)
* rangy-core.js: using the bower installed one
* to-markdown.js: using the new code, came from the `npm
start` process
* Edit.aspx: fixes copy/paste from LibreOffice writter colored
text.
* Web.csproj: using new javascript references to:
rangy-core, rangy-selectionsaverestore jquery.htmlClean
* mdd_help.htm:
* mdd_styles.css:
* rangyinputs-jquery-1.1.2.js: obsolete
2015-09-25 Paul Schneider <paul@pschneider.fr>
* BlogsController.cs: Fixes the Markdown usage of the uploaded

@ -2,8 +2,8 @@
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<asp:ContentPlaceHolder id="init" runat="server">
</asp:ContentPlaceHolder><%
ViewState["orgtitle"] = Html.Translate(Page.Title);
</asp:ContentPlaceHolder>
<% ViewState["orgtitle"] = Html.Translate(Page.Title);
Page.Title = ViewState["orgtitle"] + " - " + YavscHelpers.SiteName;
%><head runat="server">
<meta charset="utf-8">
@ -11,6 +11,7 @@ ViewState["orgtitle"] = Html.Translate(Page.Title);
<meta name="viewport" content="width=device-width, initial-scale=1" />
<link rel="stylesheet" href="~/App_Themes/style.css" />
<link rel="icon" type="image/png" href="/favicon.png?v=3" />
<link rel="stylesheet" href="<%=Url.Content("~/App_Themes/font-awesome.css")%>" />
<script type="text/javascript">
var apiBaseUrl = '<%=Url.Content(Yavsc.WebApiConfig.UrlPrefixRelative)%>';
</script>
@ -38,7 +39,7 @@ var apiBaseUrl = '<%=Url.Content(Yavsc.WebApiConfig.UrlPrefixRelative)%>';
<% if (Membership.GetUser()==null) { %>
<div class="menuitem">
<%= Html.ActionLink("Authentification", "Login", "Account", new { returnUrl=Request.Url.PathAndQuery },null) %>
<div class="hint">Pour pouvoir publier</div>
<div class="hint">Pour pouvoir publier, facturer</div>
</div>
<% } else { %><div class="menuitem">
<a href="/Blog/<%= HttpContext.Current.User.Identity.Name%>">

File diff suppressed because one or more lines are too long

@ -1,168 +0,0 @@
<div class="panel">
<h2>Markdown Formatting</h2>
<p><a href="http://daringfireball.net/projects/markdown/" target="_blank">Markdown</a> turns plain text formatting into fancy HTML formatting.</p>
<h3>Phrase Emphasis</h3>
<pre><code>*italic* **bold**
_italic_ __bold__
</code></pre>
<h3>Links</h3>
<p>Inline:</p>
<pre><code>An [example](http://url.com/ &quot;Title&quot;)
</code></pre>
<p>Reference-style labels (titles are optional):</p>
<pre><code>An [example][id]. Then, anywhere
else in the doc, define the link:
[id]: http://example.com/ &quot;Title&quot;
</code></pre>
<h3>Images</h3>
<p>Inline (titles are optional):</p>
<pre><code>![alt text](/path/img.jpg &quot;Title&quot;)
</code></pre>
<p>Reference-style:</p>
<pre><code>![alt text][id]
[id]: /url/to/img.jpg &quot;Title&quot;
</code></pre>
<h3>Headers</h3>
<p>Setext-style:</p>
<pre><code>Header 1
========
Header 2
--------
</code></pre>
<p>atx-style (closing #'s are optional):</p>
<pre><code># Header 1 #
## Header 2 ##
###### Header 6
</code></pre>
<h3>Lists</h3>
<p>Ordered, without paragraphs:</p>
<pre><code>1. Foo
2. Bar
</code></pre>
<p>Unordered, with paragraphs:</p>
<pre><code>* A list item.
With multiple paragraphs.
* Bar
</code></pre>
<p>You can nest them:</p>
<pre><code>* Abacus
* answer
* Bubbles
1. bunk
2. bupkis
* BELITTLER
3. burper
* Cunning
</code></pre>
<h3>Blockquotes</h3>
<pre><code>&gt; Email-style angle brackets
&gt; are used for blockquotes.
&gt; &gt; And, they can be nested.
&gt; #### Headers in blockquotes
&gt;
&gt; * You can quote a list.
&gt; * Etc.
</code></pre>
<h3>Code Spans</h3>
<pre><code>`&lt;code&gt;` spans are delimited
by backticks.
You can include literal backticks
like `` `this` ``.
</code></pre>
<h3>Preformatted Code Blocks</h3>
<p>Indent every line of a code block by at least 4 spaces or 1 tab.</p>
<pre><code>This is a normal paragraph.
This is a preformatted
code block.
</code></pre>
<h3>Horizontal Rules</h3>
<p>Three or more dashes or asterisks:</p>
<pre><code>---
* * *
- - - -
</code></pre>
<h3>Manual Line Breaks</h3>
<p>End a line with two or more spaces:</p>
<pre><code>Roses are red,
Violets are blue.
</code></pre>
<h2>Extra Mode</h2>
These formatting features are only available when Extra Mode is enabled.
<h3>Markdown In Html</h3>
<p>Enable markdown in HTML block level elements:</p>
<pre><code>&lt;div markdown=&quot;1&quot;&gt;
Markdown **still** works.
&lt;/div&gt;
</code></pre>
<h3>Fenced Code Blocks</h3>
<p>Code blocks delimited by 3 or more tildas:</p>
<pre><code>~~~
This is a preformatted
code block
~~~
</code></pre>
<h3>Header IDs</h3>
<p>Set the id of headings with <code>{#&lt;id&gt;}</code> at end of heading line:</p>
<pre><code>## My Heading {#myheading}
</code></pre>
<h3>Tables</h3>
<pre><code>Fruit |Color
---------|----------
Apples |Red
Pears |Green
Bananas |Yellow</code></pre>
<h3>Definition Lists</h3>
<pre><code>Term 1
: Definition 1
Term 2
: Definition 2</code></pre>
<h3>Footnotes</h3>
<pre><code>Body text with a footnote [^1]
[^1]: Footnote text here
</code></pre>
<h3>Abbreviations</h3>
<pre><code>MDD &lt;- will have title
*[MDD]: MarkdownDeep
</code></pre>
<p>&nbsp;</p>
</div>

@ -1,211 +0,0 @@
div.mdd_modal
{
position:absolute;
top:0;
left:0;
padding:0;
margin:0;
width:100%;
height:100%;
z-index:1000;
display:none;
font-size:10pt;
background-image:url(mdd_modal_background.png);
}
div.mdd_modal_frame
{
background-color:black;
color:white;
z-index:2000;
margin:0 auto;
margin-top:60px;
border:solid 5px #808080;
position:relative;
border-radius:5px;
-moz-border-radius:5px;
-webkit-border-radius:5px;
}
div.mdd_modal_button
{
position:absolute;
top:-33px;
right:-5px;
padding-left:10px;
padding-right:10px;
padding-top:4px;
padding-bottom:0px;
height:20px;
background-color:#202020;
z-index:1999;
border-radius:4px;
-moz-border-radius:4px;
-webkit-border-radius:4px;
line-height:1em;
}
div.mdd_modal_button a
{
color:Yellow;
text-decoration:none;
}
div.mdd_modal_button a:hover
{
color:Orange;
}
div.mdd_modal_content
{
overflow:scroll;
overflow-x:hidden;
position:relative;
width:100%;
height:100%;
}
div.mdd_ajax_loader
{
background-position: center center;
background-image: url(mdd_ajax_loader.gif);
background-repeat: no-repeat;
width:100%;
height:200px;
}
div.mdd_syntax
{
font-size:12pt;
padding:10px;
}
div.mdd_syntax h2
{
font-size:14pt;
}
div.mdd_syntax h3
{
font-size:12pt;
}
div.mdd_syntax pre
{
font-size:10pt;
border:solid 1px silver;
padding:4px;
background-color:#282828;
}
div.mdd_toolbar_wrap
{
width:100%;
}
div.mdd_toolbar
{
padding:5px;
height:20px;
}
div.mdd_toolbar ul
{
margin:0;
padding:0;
}
div.mdd_toolbar li
{
float:left;
margin:0;
padding:0;
list-style:none;
background-color: #888;
}
div.mdd_toolbar a.mdd_button
{
background-image:url(mdd_toolbar.png);
width:20px;
height:20px;
display:block;
}
span.mdd_sep
{
width:5px;
height:20px;
display:block;
border-left:solid 1px #808080;
margin-left:5px;
}
#mdd_bold { background-position:-1px -1px;}
#mdd_bold:hover { background-position:-1px -23px; }
#mdd_italic { background-position:-23px -1px; }
#mdd_italic:hover { background-position:-23px -23px; }
#mdd_ullist { background-position:-177px -1px; }
#mdd_ullist:hover { background-position:-177px -23px; }
#mdd_ollist { background-position:-155px -1px; }
#mdd_ollist:hover { background-position:-155px -23px; }
#mdd_indent { background-position:-67px -1px; }
#mdd_indent:hover { background-position:-67px -23px; }
#mdd_outdent { background-position:-89px -1px; }
#mdd_outdent:hover { background-position:-89px -23px; }
#mdd_link { background-position:-45px -1px; }
#mdd_link:hover { background-position:-45px -23px; }
#mdd_img { background-position:-133px -1px; }
#mdd_img:hover { background-position:-133px -23px; }
#mdd_hr { background-position:-221px -1px; }
#mdd_hr:hover { background-position:-221px -23px; }
#mdd_code { background-position:-111px -1px; }
#mdd_code:hover { background-position:-111px -23px; }
#mdd_heading { background-position:-199px -1px; }
#mdd_heading:hover { background-position:-199px -23px; }
#mdd_undo { background-position:-243px -1px; }
#mdd_undo:hover { background-position:-243px -23px; }
#mdd_redo { background-position:-265px -1px; }
#mdd_redo:hover { background-position:-265px -23px; }
div.mdd_links
{
float:right;
}
div.mdd_links a
{
text-decoration:none;
color:#a0a0a0;
font-size:smaller;
}
div.mdd_links a:hover
{
color:white;
}
div.mdd_editor_wrap
{
padding-right: 8px;
}
textarea.mdd_editor
{
width:100%;
resize:none;
margin:0;padding: 3px;
}
div.mdd_resizer_wrap
{
width:100%;
}
div.mdd_resizer
{
background:#181818;
background-image:url("mdd_gripper.png");
background-position:center center;
background-repeat:no-repeat;
padding-left:2px;
padding-right:2px;
height:9px;
border:solid 1px #303030;
margin-top:-1px;
cursor:n-resize;
}

File diff suppressed because one or more lines are too long

@ -0,0 +1,252 @@
/**
* Selection save and restore module for Rangy.
* Saves and restores user selections using marker invisible elements in the DOM.
*
* Part of Rangy, a cross-browser JavaScript range and selection library
* https://github.com/timdown/rangy
*
* Depends on Rangy core.
*
* Copyright 2015, Tim Down
* Licensed under the MIT license.
* Version: 1.3.0
* Build date: 10 May 2015
*/
(function(factory, root) {
if (typeof define == "function" && define.amd) {
// AMD. Register as an anonymous module with a dependency on Rangy.
define(["./rangy-core"], factory);
} else if (typeof module != "undefined" && typeof exports == "object") {
// Node/CommonJS style
module.exports = factory( require("rangy") );
} else {
// No AMD or CommonJS support so we use the rangy property of root (probably the global variable)
factory(root.rangy);
}
})(function(rangy) {
rangy.createModule("SaveRestore", ["WrappedRange"], function(api, module) {
var dom = api.dom;
var removeNode = dom.removeNode;
var isDirectionBackward = api.Selection.isDirectionBackward;
var markerTextChar = "\ufeff";
function gEBI(id, doc) {
return (doc || document).getElementById(id);
}
function insertRangeBoundaryMarker(range, atStart) {
var markerId = "selectionBoundary_" + (+new Date()) + "_" + ("" + Math.random()).slice(2);
var markerEl;
var doc = dom.getDocument(range.startContainer);
// Clone the Range and collapse to the appropriate boundary point
var boundaryRange = range.cloneRange();
boundaryRange.collapse(atStart);
// Create the marker element containing a single invisible character using DOM methods and insert it
markerEl = doc.createElement("span");
markerEl.id = markerId;
markerEl.style.lineHeight = "0";
markerEl.style.display = "none";
markerEl.className = "rangySelectionBoundary";
markerEl.appendChild(doc.createTextNode(markerTextChar));
boundaryRange.insertNode(markerEl);
return markerEl;
}
function setRangeBoundary(doc, range, markerId, atStart) {
var markerEl = gEBI(markerId, doc);
if (markerEl) {
range[atStart ? "setStartBefore" : "setEndBefore"](markerEl);
removeNode(markerEl);
} else {
module.warn("Marker element has been removed. Cannot restore selection.");
}
}
function compareRanges(r1, r2) {
return r2.compareBoundaryPoints(r1.START_TO_START, r1);
}
function saveRange(range, direction) {
var startEl, endEl, doc = api.DomRange.getRangeDocument(range), text = range.toString();
var backward = isDirectionBackward(direction);
if (range.collapsed) {
endEl = insertRangeBoundaryMarker(range, false);
return {
document: doc,
markerId: endEl.id,
collapsed: true
};
} else {
endEl = insertRangeBoundaryMarker(range, false);
startEl = insertRangeBoundaryMarker(range, true);
return {
document: doc,
startMarkerId: startEl.id,
endMarkerId: endEl.id,
collapsed: false,
backward: backward,
toString: function() {
return "original text: '" + text + "', new text: '" + range.toString() + "'";
}
};
}
}
function restoreRange(rangeInfo, normalize) {
var doc = rangeInfo.document;
if (typeof normalize == "undefined") {
normalize = true;
}
var range = api.createRange(doc);
if (rangeInfo.collapsed) {
var markerEl = gEBI(rangeInfo.markerId, doc);
if (markerEl) {
markerEl.style.display = "inline";
var previousNode = markerEl.previousSibling;
// Workaround for issue 17
if (previousNode && previousNode.nodeType == 3) {
removeNode(markerEl);
range.collapseToPoint(previousNode, previousNode.length);
} else {
range.collapseBefore(markerEl);
removeNode(markerEl);
}
} else {
module.warn("Marker element has been removed. Cannot restore selection.");
}
} else {
setRangeBoundary(doc, range, rangeInfo.startMarkerId, true);
setRangeBoundary(doc, range, rangeInfo.endMarkerId, false);
}
if (normalize) {
range.normalizeBoundaries();
}
return range;
}
function saveRanges(ranges, direction) {
var rangeInfos = [], range, doc;
var backward = isDirectionBackward(direction);
// Order the ranges by position within the DOM, latest first, cloning the array to leave the original untouched
ranges = ranges.slice(0);
ranges.sort(compareRanges);
for (var i = 0, len = ranges.length; i < len; ++i) {
rangeInfos[i] = saveRange(ranges[i], backward);
}
// Now that all the markers are in place and DOM manipulation over, adjust each range's boundaries to lie
// between its markers
for (i = len - 1; i >= 0; --i) {
range = ranges[i];
doc = api.DomRange.getRangeDocument(range);
if (range.collapsed) {
range.collapseAfter(gEBI(rangeInfos[i].markerId, doc));
} else {
range.setEndBefore(gEBI(rangeInfos[i].endMarkerId, doc));
range.setStartAfter(gEBI(rangeInfos[i].startMarkerId, doc));
}
}
return rangeInfos;
}
function saveSelection(win) {
if (!api.isSelectionValid(win)) {
module.warn("Cannot save selection. This usually happens when the selection is collapsed and the selection document has lost focus.");
return null;
}
var sel = api.getSelection(win);
var ranges = sel.getAllRanges();
var backward = (ranges.length == 1 && sel.isBackward());
var rangeInfos = saveRanges(ranges, backward);
// Ensure current selection is unaffected
if (backward) {
sel.setSingleRange(ranges[0], backward);
} else {
sel.setRanges(ranges);
}
return {
win: win,
rangeInfos: rangeInfos,
restored: false
};
}
function restoreRanges(rangeInfos) {
var ranges = [];
// Ranges are in reverse order of appearance in the DOM. We want to restore earliest first to avoid
// normalization affecting previously restored ranges.
var rangeCount = rangeInfos.length;
for (var i = rangeCount - 1; i >= 0; i--) {
ranges[i] = restoreRange(rangeInfos[i], true);
}
return ranges;
}
function restoreSelection(savedSelection, preserveDirection) {
if (!savedSelection.restored) {
var rangeInfos = savedSelection.rangeInfos;
var sel = api.getSelection(savedSelection.win);
var ranges = restoreRanges(rangeInfos), rangeCount = rangeInfos.length;
if (rangeCount == 1 && preserveDirection && api.features.selectionHasExtend && rangeInfos[0].backward) {
sel.removeAllRanges();
sel.addRange(ranges[0], true);
} else {
sel.setRanges(ranges);
}
savedSelection.restored = true;
}
}
function removeMarkerElement(doc, markerId) {
var markerEl = gEBI(markerId, doc);
if (markerEl) {
removeNode(markerEl);
}
}
function removeMarkers(savedSelection) {
var rangeInfos = savedSelection.rangeInfos;
for (var i = 0, len = rangeInfos.length, rangeInfo; i < len; ++i) {
rangeInfo = rangeInfos[i];
if (rangeInfo.collapsed) {
removeMarkerElement(savedSelection.doc, rangeInfo.markerId);
} else {
removeMarkerElement(savedSelection.doc, rangeInfo.startMarkerId);
removeMarkerElement(savedSelection.doc, rangeInfo.endMarkerId);
}
}
}
api.util.extend(api, {
saveRange: saveRange,
restoreRange: restoreRange,
saveRanges: saveRanges,
restoreRanges: restoreRanges,
saveSelection: saveSelection,
restoreSelection: restoreSelection,
removeMarkerElement: removeMarkerElement,
removeMarkers: removeMarkers
});
});
return rangy;
}, this);

@ -1,274 +0,0 @@
/**
* @license Rangy Inputs, a jQuery plug-in for selection and caret manipulation within textareas and text inputs.
*
* https://github.com/timdown/rangyinputs
*
* For range and selection features for contenteditable, see Rangy.
* http://code.google.com/p/rangy/
*
* Depends on jQuery 1.0 or later.
*
* Copyright 2013, Tim Down
* Licensed under the MIT license.
* Version: 1.1.2
* Build date: 6 September 2013
*/
(function($) {
var UNDEF = "undefined";
var getSelection, setSelection, deleteSelectedText, deleteText, insertText;
var replaceSelectedText, surroundSelectedText, extractSelectedText, collapseSelection;
// Trio of isHost* functions taken from Peter Michaux's article:
// http://peter.michaux.ca/articles/feature-detection-state-of-the-art-browser-scripting
function isHostMethod(object, property) {
var t = typeof object[property];
return t === "function" || (!!(t == "object" && object[property])) || t == "unknown";
}
function isHostProperty(object, property) {
return typeof(object[property]) != UNDEF;
}
function isHostObject(object, property) {
return !!(typeof(object[property]) == "object" && object[property]);
}
function fail(reason) {
if (window.console && window.console.log) {
window.console.log("RangyInputs not supported in your browser. Reason: " + reason);
}
}
function adjustOffsets(el, start, end) {
if (start < 0) {
start += el.value.length;
}
if (typeof end == UNDEF) {
end = start;
}
if (end < 0) {
end += el.value.length;
}
return { start: start, end: end };
}
function makeSelection(el, start, end) {
return {
start: start,
end: end,
length: end - start,
text: el.value.slice(start, end)
};
}
function getBody() {
return isHostObject(document, "body") ? document.body : document.getElementsByTagName("body")[0];
}
$(document).ready(function() {
var testTextArea = document.createElement("textarea");
getBody().appendChild(testTextArea);
if (isHostProperty(testTextArea, "selectionStart") && isHostProperty(testTextArea, "selectionEnd")) {
getSelection = function(el) {
var start = el.selectionStart, end = el.selectionEnd;
return makeSelection(el, start, end);
};
setSelection = function(el, startOffset, endOffset) {
var offsets = adjustOffsets(el, startOffset, endOffset);
el.selectionStart = offsets.start;
el.selectionEnd = offsets.end;
};
collapseSelection = function(el, toStart) {
if (toStart) {
el.selectionEnd = el.selectionStart;
} else {
el.selectionStart = el.selectionEnd;
}
};
} else if (isHostMethod(testTextArea, "createTextRange") && isHostObject(document, "selection") &&
isHostMethod(document.selection, "createRange")) {
getSelection = function(el) {
var start = 0, end = 0, normalizedValue, textInputRange, len, endRange;
var range = document.selection.createRange();
if (range && range.parentElement() == el) {
len = el.value.length;
normalizedValue = el.value.replace(/\r\n/g, "\n");
textInputRange = el.createTextRange();
textInputRange.moveToBookmark(range.getBookmark());
endRange = el.createTextRange();
endRange.collapse(false);
if (textInputRange.compareEndPoints("StartToEnd", endRange) > -1) {
start = end = len;
} else {
start = -textInputRange.moveStart("character", -len);
start += normalizedValue.slice(0, start).split("\n").length - 1;
if (textInputRange.compareEndPoints("EndToEnd", endRange) > -1) {
end = len;
} else {
end = -textInputRange.moveEnd("character", -len);
end += normalizedValue.slice(0, end).split("\n").length - 1;
}
}
}
return makeSelection(el, start, end);
};
// Moving across a line break only counts as moving one character in a TextRange, whereas a line break in
// the textarea value is two characters. This function corrects for that by converting a text offset into a
// range character offset by subtracting one character for every line break in the textarea prior to the
// offset
var offsetToRangeCharacterMove = function(el, offset) {
return offset - (el.value.slice(0, offset).split("\r\n").length - 1);
};
setSelection = function(el, startOffset, endOffset) {
var offsets = adjustOffsets(el, startOffset, endOffset);
var range = el.createTextRange();
var startCharMove = offsetToRangeCharacterMove(el, offsets.start);
range.collapse(true);
if (offsets.start == offsets.end) {
range.move("character", startCharMove);
} else {
range.moveEnd("character", offsetToRangeCharacterMove(el, offsets.end));
range.moveStart("character", startCharMove);
}
range.select();
};
collapseSelection = function(el, toStart) {
var range = document.selection.createRange();
range.collapse(toStart);
range.select();
};
} else {
getBody().removeChild(testTextArea);
fail("No means of finding text input caret position");
return;
}
// Clean up
getBody().removeChild(testTextArea);
deleteText = function(el, start, end, moveSelection) {
var val;
if (start != end) {
val = el.value;
el.value = val.slice(0, start) + val.slice(end);
}
if (moveSelection) {
setSelection(el, start, start);
}
};
deleteSelectedText = function(el) {
var sel = getSelection(el);
deleteText(el, sel.start, sel.end, true);
};
extractSelectedText = function(el) {
var sel = getSelection(el), val;
if (sel.start != sel.end) {
val = el.value;
el.value = val.slice(0, sel.start) + val.slice(sel.end);
}
setSelection(el, sel.start, sel.start);
return sel.text;
};
var updateSelectionAfterInsert = function(el, startIndex, text, selectionBehaviour) {
var endIndex = startIndex + text.length;
selectionBehaviour = (typeof selectionBehaviour == "string") ?
selectionBehaviour.toLowerCase() : "";
if ((selectionBehaviour == "collapsetoend" || selectionBehaviour == "select") && /[\r\n]/.test(text)) {
// Find the length of the actual text inserted, which could vary
// depending on how the browser deals with line breaks
var normalizedText = text.replace(/\r\n/g, "\n").replace(/\r/g, "\n");
endIndex = startIndex + normalizedText.length;
var firstLineBreakIndex = startIndex + normalizedText.indexOf("\n");
if (el.value.slice(firstLineBreakIndex, firstLineBreakIndex + 2) == "\r\n") {
// Browser uses \r\n, so we need to account for extra \r characters
endIndex += normalizedText.match(/\n/g).length;
}
}
switch (selectionBehaviour) {
case "collapsetostart":
setSelection(el, startIndex, startIndex);
break;
case "collapsetoend":
setSelection(el, endIndex, endIndex);
break;
case "select":
setSelection(el, startIndex, endIndex);
break;
}
};
insertText = function(el, text, index, selectionBehaviour) {
var val = el.value;
el.value = val.slice(0, index) + text + val.slice(index);
if (typeof selectionBehaviour == "boolean") {
selectionBehaviour = selectionBehaviour ? "collapseToEnd" : "";
}
updateSelectionAfterInsert(el, index, text, selectionBehaviour);
};
replaceSelectedText = function(el, text, selectionBehaviour) {
var sel = getSelection(el), val = el.value;
el.value = val.slice(0, sel.start) + text + val.slice(sel.end);
updateSelectionAfterInsert(el, sel.start, text, selectionBehaviour || "collapseToEnd");
};
surroundSelectedText = function(el, before, after, selectionBehaviour) {
if (typeof after == UNDEF) {
after = before;
}
var sel = getSelection(el), val = el.value;
el.value = val.slice(0, sel.start) + before + sel.text + after + val.slice(sel.end);
var startIndex = sel.start + before.length;
updateSelectionAfterInsert(el, startIndex, sel.text, selectionBehaviour || "select");
};
function jQuerify(func, returnThis) {
return function() {
var el = this.jquery ? this[0] : this;
var nodeName = el.nodeName.toLowerCase();
if (el.nodeType == 1 && (nodeName == "textarea" || (nodeName == "input" && el.type == "text"))) {
var args = [el].concat(Array.prototype.slice.call(arguments));
var result = func.apply(this, args);
if (!returnThis) {
return result;
}
}
if (returnThis) {
return this;
}
};
}
$.fn.extend({
getSelection: jQuerify(getSelection, false),
setSelection: jQuerify(setSelection, true),
collapseSelection: jQuerify(collapseSelection, true),
deleteSelectedText: jQuerify(deleteSelectedText, true),
deleteText: jQuerify(deleteText, true),
extractSelectedText: jQuerify(extractSelectedText, false),
insertText: jQuerify(insertText, true),
replaceSelectedText: jQuerify(replaceSelectedText, true),
surroundSelectedText: jQuerify(surroundSelectedText, true)
});
});
})(jQuery);

@ -49,7 +49,7 @@ function isBlock(node) {
var voids = [
'area', 'base', 'br', 'col', 'command', 'embed', 'hr', 'img', 'input',
'keygen', 'link', 'meta', 'param', 'source', 'track', 'wbr',
'keygen', 'link', 'meta', 'param', 'source', 'track', 'wbr'
];
function isVoid(node) {
@ -582,6 +582,7 @@ module.exports = [
}
}
];
},{}],4:[function(require,module,exports){
'use strict';
@ -786,11 +787,10 @@ module.exports = {
"param": true,
"source": true,
"track": true,
"video": true,
"wbr": true
};
},{}],7:[function(require,module,exports){
},{}]},{},[1])(1)
});
});

@ -4,10 +4,10 @@
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.10.2/jquery-ui.min.js"></script>
<script src="http://rangy.googlecode.com/svn/trunk/currentrelease/rangy-core.js"></script>
<link rel="stylesheet" href="<%=Url.Content("~/Scripts/mdd_styles.css")%>">
<script type="text/javascript" src="<%=Url.Content("~/Scripts/MarkdownDeepLib.min.js")%>"></script>
<link rel="stylesheet" href="<%=Url.Content("~/App_Themes/jquery-ui.css")%>" />
<link rel="stylesheet" href="<%=Url.Content("~/App_Themes/font-awesome.css")%>" />
<script type="text/javascript" src="<%=Url.Content("~/Scripts/rangy-core.js")%>"></script>
<script type="text/javascript" src="<%=Url.Content("~/Scripts/rangy-selectionsaverestore.js")%>"></script>
<script type="text/javascript" src="<%=Url.Content("~/Scripts/jquery.htmlClean.min.js")%>"></script>
<script type="text/javascript" src="<%=Url.Content("~/Scripts/hallo.js")%>"></script>
<script type="text/javascript" src="<%=Url.Content("~/Scripts/to-markdown.js")%>"></script>
<script type="text/javascript" src="<%=Url.Content("~/Scripts/showdown.js")%>"></script>
@ -38,13 +38,38 @@ jQuery('#vtitle').hallo({
},
toolbar: 'halloToolbarFixed'
});
jQuery('#vcontent').hallo({
plugins: {
'halloformat': {},
'halloheadings': {},
'hallolists': {},
'halloimage': {},
'halloreundo': {}
'halloheadings': {},
'hallolists': {},
'halloimage': {},
'halloreundo': {},
'hallocleanhtml': {
format: false,
allowedTags: [
'i',
'p',
'em',
'strong',
'br',
'div',
'ol',
'ul',
'li',
'a',
'audio',
'video',
'img',
'table',
'tr',
'td',
'th',
'style'
]
},
'halloblacklist': {tags: ['style']},
},
toolbar: 'halloToolbarFixed'
});
@ -53,22 +78,27 @@ var markdownize = function(content) {
var html = content.split("\n").map($.trim).filter(function(line) {
return line != "";
}).join("\n");
return toMarkdown(html);
var tmp = document.createElement("DIV");
tmp.innerHTML = html;
jQuery("style",tmp).remove();
return toMarkdown(tmp.innerHTML);
};
var converter = new showdown.Converter(),
var converter = new showdown.Converter(),
htmlize = function(content) {
return converter.makeHtml(content);
};
// Method that converts the HTML contents to Markdown
var showSource = function(id,content) {
var showSource = function(id,content) {
var markdown = markdownize(content);
if (jQuery('#'+id).get(0).value == markdown) {
return;
}
jQuery('#'+id).get(0).value = markdown;
};
var updateHtml = function(id,content) {
var updateHtml = function(id,content) {
var jView = jQuery('div[for="'+id+'"]');
if (markdownize(jView.html()) == content) {
return;
@ -76,6 +106,7 @@ var markdownize = function(content) {
var html = htmlize(content);
jView.html(html);
};
// Update Markdown every time content is modified
jQuery('.editable').bind('hallomodified', function(event, data) {
showSource(this.attributes["for"].value, data.content);
@ -86,6 +117,7 @@ var markdownize = function(content) {
jQuery('#Title').bind('keyup', function() {
updateHtml(this.id, this.value);
});
showSource("Title",jQuery('#vtitle').html());
showSource("Content",jQuery('#vcontent').html());
@ -122,6 +154,8 @@ function submitFile()
submitFilesTo('PostFile');
}
</script>
<form id="uploads" method="post" enctype="multipart/form-data">
<input type="file" name="attached" id="postedfile" multiple>

@ -267,7 +267,6 @@
<Content Include="RegistrationMail.txt" />
<Content Include="Views\FrontOffice\Writting.ascx" />
<Content Include="Scripts\jquery.metadata.js" />
<Content Include="Scripts\rangyinputs-jquery-1.1.2.js" />
<Content Include="images\sign-in-with-google.png" />
<Content Include="Views\Account\Unregister.aspx" />
<Content Include="Scripts\jquery.timepicker.js" />
@ -298,8 +297,6 @@
<Content Include="Views\Account\Register.ascx" />
<Content Include="Views\Account\ResetPassword.aspx" />
<Content Include="Views\Blogs\NotAuthorized.aspx" />
<Content Include="Scripts\mdd_help.htm" />
<Content Include="Scripts\mdd_styles.css" />
<Content Include="Views\Calendar\Login.aspx" />
<Content Include="Views\Calendar\Auth.aspx" />
<Content Include="Views\Calendar\ChooseCalendar.aspx" />
@ -377,6 +374,9 @@
<Content Include="fonts\fontawesome-webfont.woff" />
<Content Include="Scripts\to-markdown.js" />
<Content Include="Scripts\showdown.js" />
<Content Include="Scripts\rangy-core.js" />
<Content Include="Scripts\rangy-selectionsaverestore.js" />
<Content Include="Scripts\jquery.htmlClean.min.js" />
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<Import Project="$(MSBuildExtensionsPath)\Microsoft\VisualStudio\v10.0\WebApplications\Microsoft.WebApplication.targets" />

Loading…