Unverified Commit b4a4318d by Sofiya Semenova Committed by GitHub

Merge pull request #16705 from edx/sofiya/1552

Educator 1552 Implement roving tabindex for WYSIWYG editor for discussions
parents 8752480a a1f0679f
......@@ -7,6 +7,9 @@
DiscussionUtil.wmdEditors = {};
DiscussionUtil.leftKey = 37;
DiscussionUtil.rightKey = 39;
DiscussionUtil.getTemplate = function(id) {
return $('script#' + id).html();
};
......@@ -539,6 +542,38 @@
};
};
DiscussionUtil.handleKeypressInToolbar = function(event) {
var $currentButton, $nextButton, $toolbar, $allButtons,
keyPressed, nextIndex, currentButtonIndex,
validKeyPress, toolbarHasButtons;
$currentButton = $(event.target);
keyPressed = event.which || event.keyCode;
$toolbar = $currentButton.parent();
$allButtons = $toolbar.children('.wmd-button');
validKeyPress = keyPressed === this.leftKey || keyPressed === this.rightKey;
toolbarHasButtons = $allButtons.length > 0;
if (validKeyPress && toolbarHasButtons) {
currentButtonIndex = $allButtons.index($currentButton);
nextIndex = keyPressed === this.leftKey ? currentButtonIndex - 1 : currentButtonIndex + 1;
nextIndex = Math.max(Math.min(nextIndex, $allButtons.length - 1), 0);
$nextButton = $($allButtons[nextIndex]);
this.moveSelectionToNextItem($currentButton, $nextButton);
}
};
DiscussionUtil.moveSelectionToNextItem = function(prevItem, nextItem) {
prevItem.attr('aria-selected', 'false');
prevItem.attr('tabindex', '-1');
nextItem.attr('aria-selected', 'true');
nextItem.attr('tabindex', '0');
nextItem.focus();
};
return DiscussionUtil;
}).call(this);
}).call(window);
......@@ -62,7 +62,10 @@
DiscussionThreadView.prototype.events = {
'click .discussion-submit-post': 'submitComment',
'click .add-response-btn': 'scrollToAddResponse'
'click .add-response-btn': 'scrollToAddResponse',
'keydown .wmd-button': function(event) {
return DiscussionUtil.handleKeypressInToolbar(event);
}
};
DiscussionThreadView.prototype.$ = function(selector) {
......
......@@ -137,7 +137,10 @@
'change .post-option-input': 'postOptionChange',
'click .cancel': 'cancel',
'click .add-post-cancel': 'cancel',
'reset .forum-new-post-form': 'updateStyles'
'reset .forum-new-post-form': 'updateStyles',
'keydown .wmd-button': function(event) {
return DiscussionUtil.handleKeypressInToolbar(event);
}
};
NewPostView.prototype.toggleGroupDropdown = function($target) {
......
// needs Markdown.Converter.js at the moment
(function() {
(function() {
var util = {},
position = {},
ui = {},
......@@ -62,7 +62,7 @@
// - getConverter() returns the markdown converter object that was passed to the constructor
// - run() actually starts the editor; should be called after all necessary plugins are registered. Calling this more than once is a no-op.
// - refreshPreview() forces the preview to be updated. This method is only available after run() was called.
Markdown.Editor = function(markdownConverter, idPostfix, help, imageUploadHandler) {
Markdown.Editor = function(markdownConverter, idPostfix, help, imageUploadHandler) {
idPostfix = idPostfix || '';
var hooks = this.hooks = new Markdown.HookCollection();
......@@ -107,7 +107,7 @@
var forceRefresh = that.refreshPreview = function() { previewManager.refresh(true); };
forceRefresh();
};
};
};
// before: contains all the text in the input box BEFORE the selection.
......@@ -116,11 +116,11 @@
// startRegex: a regular expression to find the start tag
// endRegex: a regular expresssion to find the end tag
Chunks.prototype.findTags = function(startRegex, endRegex) {
Chunks.prototype.findTags = function(startRegex, endRegex) {
var chunkObj = this;
var regex;
if (startRegex) {
if (startRegex) {
regex = util.extendRegExp(startRegex, '', '$');
this.before = this.before.replace(regex,
......@@ -138,7 +138,7 @@
});
}
if (endRegex) {
if (endRegex) {
regex = util.extendRegExp(endRegex, '', '$');
this.selection = this.selection.replace(regex,
......@@ -174,7 +174,7 @@
};
Chunks.prototype.skipLines = function(nLinesBefore, nLinesAfter, findExtraNewlines) {
Chunks.prototype.skipLines = function(nLinesBefore, nLinesAfter, findExtraNewlines) {
if (nLinesBefore === undefined) {
nLinesBefore = 1;
}
......@@ -205,7 +205,7 @@
this.endTag = this.endTag.replace(/(\n*$)/, '');
this.after = this.after + re.$1;
if (this.before) {
if (this.before) {
regexText = replacementText = '';
while (nLinesBefore--) {
......@@ -219,7 +219,7 @@
this.before = this.before.replace(new re(regexText + '$', ''), replacementText);
}
if (this.after) {
if (this.after) {
regexText = replacementText = '';
while (nLinesAfter--) {
......@@ -264,7 +264,7 @@
// Returns true if the DOM element is visible, false if it's hidden.
// Checks if display is anything other than none.
util.isVisible = function(elem) {
util.isVisible = function(elem) {
if (window.getComputedStyle) {
// Most browsers
return window.getComputedStyle(elem, null).getPropertyValue('display') !== 'none';
......@@ -318,7 +318,7 @@
// The flags are unchanged.
//
// regex is a RegExp, pre and post are strings.
util.extendRegExp = function(regex, pre, post) {
util.extendRegExp = function(regex, pre, post) {
if (pre === null || pre === undefined) {
pre = '';
}
......@@ -363,7 +363,7 @@
return elem.offsetWidth || elem.scrollWidth;
};
position.getPageSize = function() {
position.getPageSize = function() {
var scrollWidth, scrollHeight;
var innerWidth, innerHeight;
......@@ -404,7 +404,7 @@
// Handles pushing and popping TextareaStates for undo/redo commands.
// I should rename the stack variables to list.
function UndoManager(callback, panels) {
function UndoManager(callback, panels) {
var undoObj = this;
var undoStack = []; // A stack of undo states
var stackPtr = 0; // The index of the current state
......@@ -453,7 +453,7 @@
};
// Removes the last state and restores it.
this.undo = function() {
this.undo = function() {
if (undoObj.canUndo()) {
if (lastState) {
// What about setting state -1 to null or checking for undefined?
......@@ -476,8 +476,8 @@
};
// Redo an action.
this.redo = function() {
if (undoObj.canRedo()) {
this.redo = function() {
if (undoObj.canRedo()) {
undoStack[++stackPtr].restore();
if (callback) {
......@@ -516,10 +516,10 @@
}
};
var handleCtrlYZ = function(event) {
var handleCtrlYZ = function(event) {
var handled = false;
if (event.ctrlKey || event.metaKey) {
if (event.ctrlKey || event.metaKey) {
// IE and Opera do not support charCode.
var keyCode = event.charCode || event.keyCode;
var keyCodeChar = String.fromCharCode(keyCode);
......@@ -555,8 +555,8 @@
};
// Set the mode depending on what is going on in the input area.
var handleModeChange = function(event) {
if (!event.ctrlKey && !event.metaKey) {
var handleModeChange = function(event) {
if (!event.ctrlKey && !event.metaKey) {
var keyCode = event.keyCode;
if ((keyCode >= 33 && keyCode <= 40) || (keyCode >= 63232 && keyCode <= 63235)) {
......@@ -630,7 +630,7 @@
// The input textarea state/contents.
// This is used to implement undo/redo by the undo manager.
function TextareaState(panels, isInitialState) {
function TextareaState(panels, isInitialState) {
// Aliases
var stateObj = this;
var inputArea = panels.input;
......@@ -646,23 +646,23 @@
this.scrollTop = inputArea.scrollTop;
if (!this.text && inputArea.selectionStart || inputArea.selectionStart === 0) {
this.text = inputArea.value;
}
}
};
// Sets the selected text in the input box after we've performed an
// operation.
this.setInputAreaSelection = function() {
this.setInputAreaSelection = function() {
if (!util.isVisible(inputArea)) {
return;
}
if (inputArea.selectionStart !== undefined && !uaSniffed.isOpera) {
if (inputArea.selectionStart !== undefined && !uaSniffed.isOpera) {
inputArea.focus();
inputArea.selectionStart = stateObj.start;
inputArea.selectionEnd = stateObj.end;
inputArea.scrollTop = stateObj.scrollTop;
}
else if (doc.selection) {
else if (doc.selection) {
if (doc.activeElement && doc.activeElement !== inputArea) {
return;
}
......@@ -677,12 +677,12 @@
}
};
this.setInputAreaSelectionStartEnd = function() {
if (!panels.ieCachedRange && (inputArea.selectionStart || inputArea.selectionStart === 0)) {
this.setInputAreaSelectionStartEnd = function() {
if (!panels.ieCachedRange && (inputArea.selectionStart || inputArea.selectionStart === 0)) {
stateObj.start = inputArea.selectionStart;
stateObj.end = inputArea.selectionEnd;
}
else if (doc.selection) {
else if (doc.selection) {
stateObj.text = util.fixEolChars(inputArea.value);
// IE loses the selection in the textarea when buttons are
......@@ -723,7 +723,7 @@
};
// Restore this state into the input area.
this.restore = function() {
this.restore = function() {
if (stateObj.text != undefined && stateObj.text != inputArea.value) {
inputArea.value = stateObj.text;
}
......@@ -732,7 +732,7 @@
};
// Gets a collection of HTML chunks from the inptut textarea.
this.getChunks = function() {
this.getChunks = function() {
var chunk = new Chunks();
chunk.before = util.fixEolChars(stateObj.text.substring(0, stateObj.start));
chunk.startTag = '';
......@@ -745,7 +745,7 @@
};
// Sets the TextareaState properties given a chunk of markdown.
this.setChunks = function(chunk) {
this.setChunks = function(chunk) {
chunk.before = chunk.before + chunk.startTag;
chunk.after = chunk.endTag + chunk.after;
......@@ -757,7 +757,7 @@
this.init();
}
function PreviewManager(converter, panels, previewPushCallback) {
function PreviewManager(converter, panels, previewPushCallback) {
var managerObj = this;
var timeout;
var elapsedTime;
......@@ -766,7 +766,7 @@
var startType = 'delayed'; // The other legal value is "manual"
// Adds event listeners to elements
var setupEvents = function(inputElem, listener) {
var setupEvents = function(inputElem, listener) {
util.addEvent(inputElem, 'input', listener);
inputElem.onpaste = listener;
inputElem.ondrop = listener;
......@@ -775,7 +775,7 @@
util.addEvent(inputElem, 'keydown', listener);
};
var getDocScrollTop = function() {
var getDocScrollTop = function() {
var result = 0;
if (window.innerHeight) {
......@@ -793,7 +793,7 @@
return result;
};
var makePreviewHtml = function() {
var makePreviewHtml = function() {
// If there is no registered preview panel
// there is nothing to do.
if (!panels.preview)
......@@ -821,13 +821,13 @@
};
// setTimeout is already used. Used as an event listener.
var applyTimeout = function() {
var applyTimeout = function() {
if (timeout) {
clearTimeout(timeout);
timeout = undefined;
}
if (startType !== 'manual') {
if (startType !== 'manual') {
var delay = 0;
if (startType === 'delayed') {
......@@ -854,7 +854,7 @@
}
};
this.refresh = function(requiresRefresh) {
this.refresh = function(requiresRefresh) {
if (requiresRefresh) {
oldInputText = '';
makePreviewHtml();
......@@ -904,7 +904,7 @@
}
};
var pushPreviewHtml = function(text) {
var pushPreviewHtml = function(text) {
var emptyTop = position.getTop(panels.input) - getDocScrollTop();
if (panels.preview) {
......@@ -930,7 +930,7 @@
}
};
var init = function() {
var init = function() {
setupEvents(panels.input, applyTimeout);
makePreviewHtml();
......@@ -946,7 +946,7 @@
// And download dialog
// Most of this has been moved to CSS but the div creation and
// browser-specific hacks remain here.
ui.createBackground = function() {
ui.createBackground = function() {
var background = doc.createElement('div'),
style = background.style;
......@@ -999,7 +999,7 @@
defaultInputText,
callback,
imageIsDecorativeLabel,
imageUploadHandler) {
imageUploadHandler) {
// These variables need to be declared at this level since they are used
// in multiple functions.
var dialog, // The dialog box.
......@@ -1108,7 +1108,7 @@
imageIsDecorativeLabel: imageIsDecorativeLabel,
imageUploadHandler: imageUploadHandler
});
dialog.setAttribute('dir', doc.head.getAttribute('dir'));
dialog.setAttribute('dir', doc.head.getAttribute('dir'));
dialog.setAttribute('role', 'dialog');
dialog.setAttribute('tabindex', '-1');
dialog.setAttribute('aria-labelledby', 'editorDialogTitle');
......@@ -1184,7 +1184,7 @@
// Why is this in a zero-length timeout?
// Is it working around a browser bug?
setTimeout(function() {
setTimeout(function() {
createDialog();
var defTextLen = defaultInputText.length;
......@@ -1204,7 +1204,7 @@
}, 0);
};
function UIManager(postfix, panels, undoManager, previewManager, commandManager, helpOptions, imageUploadHandler) {
function UIManager(postfix, panels, undoManager, previewManager, commandManager, helpOptions, imageUploadHandler) {
var inputBox = panels.input,
buttons = {}; // buttons.undo, buttons.link, etc. The actual DOM elements.
......@@ -1215,9 +1215,9 @@
keyEvent = 'keypress';
}
util.addEvent(inputBox, keyEvent, function(key) {
util.addEvent(inputBox, keyEvent, function(key) {
// Check to see if we have a button key and, if so execute the callback.
if ((key.ctrlKey || key.metaKey) && !key.altKey && !key.shiftKey) {
if ((key.ctrlKey || key.metaKey) && !key.altKey && !key.shiftKey) {
var keyCode = key.charCode || key.keyCode;
var keyCodeStr = String.fromCharCode(keyCode).toLowerCase();
......@@ -1303,10 +1303,10 @@
// Perform the button's action.
function doClick(button) {
function doClick(button) {
inputBox.focus();
if (button.textOp) {
if (button.textOp) {
if (undoManager) {
undoManager.setCommandMode();
}
......@@ -1336,7 +1336,7 @@
// Yes this is awkward and I think it sucks, but there's
// no real workaround. Only the image and link code
// create dialogs and require the function pointers.
var fixupInputArea = function() {
var fixupInputArea = function() {
inputBox.focus();
if (chunks) {
......@@ -1351,7 +1351,7 @@
if (!noCleanup) {
fixupInputArea();
}
}
}
if (button.execute) {
......@@ -1359,7 +1359,7 @@
}
}
function setupButton(button, isEnabled) {
function setupButton(button, isEnabled) {
var normalYShift = '0px';
var disabledYShift = '-20px';
var highlightYShift = '-40px';
......@@ -1429,7 +1429,7 @@
return function() { method.apply(commandManager, arguments); };
}
function makeSpritedButtonRow() {
function makeSpritedButtonRow() {
var buttonBar = panels.buttonBar;
var normalYShift = '0px';
......@@ -1442,9 +1442,9 @@
buttonRow.className = 'wmd-button-row';
buttonRow = buttonBar.appendChild(buttonRow);
var xPosition = 0;
var makeButton = function(id, title, XShift, textOp) {
var makeButton = function(id, title, XShift, textOp, tabIndex) {
var button = document.createElement('button');
button.tabIndex = 0;
button.tabIndex = tabIndex;
button.className = 'wmd-button';
button.style.left = xPosition + 'px';
xPosition += 25;
......@@ -1468,35 +1468,35 @@
xPosition += 25;
};
buttons.bold = makeButton('wmd-bold-button', gettext('Bold (Ctrl+B)'), '0px', bindCommand('doBold'));
buttons.italic = makeButton('wmd-italic-button', gettext('Italic (Ctrl+I)'), '-20px', bindCommand('doItalic'));
buttons.bold = makeButton('wmd-bold-button', gettext('Bold (Ctrl+B)'), '0px', bindCommand('doBold'), 0);
buttons.italic = makeButton('wmd-italic-button', gettext('Italic (Ctrl+I)'), '-20px', bindCommand('doItalic'), -1);
makeSpacer(1);
buttons.link = makeButton('wmd-link-button', gettext('Hyperlink (Ctrl+L)'), '-40px', bindCommand(function(chunk, postProcessing) {
return this.doLinkOrImage(chunk, postProcessing, false);
}));
buttons.quote = makeButton('wmd-quote-button', gettext('Blockquote (Ctrl+Q)'), '-60px', bindCommand('doBlockquote'));
buttons.code = makeButton('wmd-code-button', gettext('Code Sample (Ctrl+K)'), '-80px', bindCommand('doCode'));
}), -1);
buttons.quote = makeButton('wmd-quote-button', gettext('Blockquote (Ctrl+Q)'), '-60px', bindCommand('doBlockquote'), -1);
buttons.code = makeButton('wmd-code-button', gettext('Code Sample (Ctrl+K)'), '-80px', bindCommand('doCode'), -1);
buttons.image = makeButton('wmd-image-button', gettext('Image (Ctrl+G)'), '-100px', bindCommand(function(chunk, postProcessing) {
return this.doLinkOrImage(chunk, postProcessing, true, imageUploadHandler);
}));
}), -1);
makeSpacer(2);
buttons.olist = makeButton('wmd-olist-button', gettext('Numbered List (Ctrl+O)'), '-120px', bindCommand(function(chunk, postProcessing) {
this.doList(chunk, postProcessing, true);
}));
}), -1);
buttons.ulist = makeButton('wmd-ulist-button', gettext('Bulleted List (Ctrl+U)'), '-140px', bindCommand(function(chunk, postProcessing) {
this.doList(chunk, postProcessing, false);
}));
buttons.heading = makeButton('wmd-heading-button', gettext('Heading (Ctrl+H)'), '-160px', bindCommand('doHeading'));
buttons.hr = makeButton('wmd-hr-button', gettext('Horizontal Rule (Ctrl+R)'), '-180px', bindCommand('doHorizontalRule'));
}), -1);
buttons.heading = makeButton('wmd-heading-button', gettext('Heading (Ctrl+H)'), '-160px', bindCommand('doHeading'), -1);
buttons.hr = makeButton('wmd-hr-button', gettext('Horizontal Rule (Ctrl+R)'), '-180px', bindCommand('doHorizontalRule'), -1);
makeSpacer(3);
buttons.undo = makeButton('wmd-undo-button', gettext('Undo (Ctrl+Z)'), '-200px', null);
buttons.undo = makeButton('wmd-undo-button', gettext('Undo (Ctrl+Z)'), '-200px', null, -1);
buttons.undo.execute = function(manager) { if (manager) manager.undo(); };
var redoTitle = /win/.test(nav.platform.toLowerCase()) ?
gettext('Redo (Ctrl+Y)') :
gettext('Redo (Ctrl+Shift+Z)'); // mac and other non-Windows platforms
buttons.redo = makeButton('wmd-redo-button', redoTitle, '-220px', null);
buttons.redo = makeButton('wmd-redo-button', redoTitle, '-220px', null, -1);
buttons.redo.execute = function(manager) { if (manager) manager.redo(); };
if (helpOptions) {
......@@ -1526,7 +1526,7 @@
}
}
this.setUndoRedoButtonStates = setUndoRedoButtonStates;
this.setUndoRedoButtonStates = setUndoRedoButtonStates;
}
function CommandManager(pluginHooks) {
......@@ -1570,7 +1570,7 @@
// chunk: The selected region that will be enclosed with */**
// nStars: 1 for italics, 2 for bold
// insertText: If you just click the button without highlighting text, this gets inserted
commandProto.doBorI = function(chunk, postProcessing, nStars, insertText) {
commandProto.doBorI = function(chunk, postProcessing, nStars, insertText) {
// Get rid of whitespace and fixup newlines.
chunk.trimWhitespace();
chunk.selection = chunk.selection.replace(/\n{2,}/g, '\n');
......@@ -1595,7 +1595,7 @@
var whitespace = re.$1;
chunk.before = chunk.before + starsAfter + whitespace;
}
else {
else {
// In most cases, if you don't have any selected text and click the button
// you'll get a selected, marked up region with the default text inserted.
if (!chunk.selection && !starsAfter) {
......@@ -1611,7 +1611,7 @@
return;
};
commandProto.stripLinkDefs = function(text, defsToAdd) {
commandProto.stripLinkDefs = function(text, defsToAdd) {
text = text.replace(/^[ ]{0,3}\[(\d+)\]:[ \t]*\n?[ \t]*<?(\S+?)>?[ \t]*\n?[ \t]*(?:(\n*)["(](.+?)[")][ \t]*)?(?:\n+|$)/gm,
function(totalMatch, id, link, newlines, title) {
defsToAdd[id] = totalMatch.replace(/\s*$/, '');
......@@ -1626,7 +1626,7 @@
return text;
};
commandProto.addLinkDef = function(chunk, linkDef) {
commandProto.addLinkDef = function(chunk, linkDef) {
var refNumber = 0; // The current reference number
var defsToAdd = {}; //
// Start with a clean slate by removing all previous link definitions.
......@@ -1707,12 +1707,12 @@
chunk.findTags(/\s*!?\[/, /\][ ]?(?:\n[ ]*)?(\[.*?\])?/);
var background;
if (chunk.endTag.length > 1 && chunk.startTag.length > 0) {
if (chunk.endTag.length > 1 && chunk.startTag.length > 0) {
chunk.startTag = chunk.startTag.replace(/!?\[/, '');
chunk.endTag = '';
this.addLinkDef(chunk, null);
this.addLinkDef(chunk, null);
}
else {
else {
// We're moving start and end tag back into the selection, since (as we're in the else block) we're not
// *removing* a link, but *adding* one, so whatever findTags() found is now back to being part of the
// link text. linkEnteredCallback takes care of escaping any brackets.
......@@ -1808,7 +1808,7 @@
// When making a list, hitting shift-enter will put your cursor on the next line
// at the current indent level.
commandProto.doAutoindent = function(chunk, postProcessing) {
commandProto.doAutoindent = function(chunk, postProcessing) {
var commandMgr = this,
fakeSelection = false;
......@@ -1850,7 +1850,7 @@
}
};
commandProto.doBlockquote = function(chunk, postProcessing) {
commandProto.doBlockquote = function(chunk, postProcessing) {
chunk.selection = chunk.selection.replace(/^(\n*)([^\r]+?)(\n*)$/,
function(totalMatch, newlinesBefore, text, newlinesAfter) {
chunk.before += newlinesBefore;
......@@ -1945,7 +1945,7 @@
}
);
var replaceBlanksInTags = function(useBracket) {
var replaceBlanksInTags = function(useBracket) {
var replacement = useBracket ? '> ' : '';
if (chunk.startTag) {
......@@ -1992,13 +1992,13 @@
}
};
commandProto.doCode = function(chunk, postProcessing) {
commandProto.doCode = function(chunk, postProcessing) {
var hasTextBefore = /\S[ ]*$/.test(chunk.before);
var hasTextAfter = /^[ ]*\S/.test(chunk.after);
// Use 'four space' markdown if the selection is on its own
// line or is multiline.
if ((!hasTextAfter && !hasTextBefore) || /\n/.test(chunk.selection)) {
if ((!hasTextAfter && !hasTextBefore) || /\n/.test(chunk.selection)) {
chunk.before = chunk.before.replace(/[ ]{4}$/,
function(totalMatch) {
chunk.selection = totalMatch + chunk.selection;
......@@ -2055,7 +2055,7 @@
}
};
commandProto.doList = function(chunk, postProcessing, isNumberedList) {
commandProto.doList = function(chunk, postProcessing, isNumberedList) {
// These are identical except at the very beginning and end.
// Should probably use the regex extension function to make this clearer.
var previousItemsRegex = /(\n|^)(([ ]{0,3}([*+-]|\d+[.])[ \t]+.*)(\n.+|\n{2,}([*+-].*|\d+[.])[ \t]+.*|\n{2,}[ \t]+\S.*)*)\n*$/;
......@@ -2083,7 +2083,7 @@
};
// Fixes the prefixes of the other list items.
var getPrefixedItem = function(itemText) {
var getPrefixedItem = function(itemText) {
// The numbering flag is unset when called by autoindent.
if (isNumberedList === undefined) {
isNumberedList = /^\s*\d/.test(itemText);
......@@ -2105,7 +2105,7 @@
chunk.startTag = '';
}
if (chunk.startTag) {
if (chunk.startTag) {
var hasDigits = /\d+[.]/.test(chunk.startTag);
chunk.startTag = '';
chunk.selection = chunk.selection.replace(/\n[ ]{4}/g, '\n');
......@@ -2151,10 +2151,10 @@
chunk.startTag = prefix;
var spaces = prefix.replace(/./g, ' ');
this.wrap(chunk, SETTINGS.lineLength - spaces.length);
chunk.selection = chunk.selection.replace(/\n/g, '\n' + spaces);
chunk.selection = chunk.selection.replace(/\n/g, '\n' + spaces);
};
commandProto.doHeading = function(chunk, postProcessing) {
commandProto.doHeading = function(chunk, postProcessing) {
// Remove leading/trailing whitespace and reduce internal spaces to single spaces.
chunk.selection = chunk.selection.replace(/\s+/g, ' ');
chunk.selection = chunk.selection.replace(/(^\s+|\s+$)/g, '');
......@@ -2196,7 +2196,7 @@
// If it's already a level 1 header, it's removed.
var headerLevelToCreate = headerLevel == 0 ? 2 : headerLevel - 1;
if (headerLevelToCreate > 0) {
if (headerLevelToCreate > 0) {
// The button only creates level 1 and 2 underline headers.
// Why not have it iterate over hash header levels? Wouldn't that be easier and cleaner?
var headerChar = headerLevelToCreate >= 2 ? '-' : '=';
......@@ -2215,5 +2215,5 @@
chunk.startTag = '----------\n';
chunk.selection = '';
chunk.skipLines(2, 1, true);
};
};
})();
......@@ -13,7 +13,7 @@ set -e
# Violations thresholds for failing the build
export LOWER_PYLINT_THRESHOLD=1000
export UPPER_PYLINT_THRESHOLD=5900
export ESLINT_THRESHOLD=9134
export ESLINT_THRESHOLD=9543
export STYLELINT_THRESHOLD=973
XSSLINT_THRESHOLDS=`cat scripts/xsslint_thresholds.json`
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment