Статьи

Реализация TitleCapitalization в StackEdit

Работая над сообщениями для PHP-канала здесь, в SitePoint, я часто забываю, как правильно использовать заглавные буквы. Я обычно заканчиваю тем, что иду к TitleCapitalization для быстрого исправления, но я часто фантазирую о наличии кнопки рядом с полем заголовка StackEdit для быстрого автоматического применения. Что ж, мы уже рассмотрели, как запустить и запустить локальный экземпляр (или несколько) StackEdit. Почему бы не создать кнопку тоже?

03

Готовиться

Чтобы подготовиться к обновлению, нам нужно проверить локальную копию StackEdit. Я, конечно, буду использовать мою верную старую коробку Homestead Improved , как здесь . Вы можете использовать свою собственную ОС Linux, это зависит от вас, но это, безусловно, самое простое.

git clone https://github.com/swader/homestead-improved hi_stackedit cd hi_stackedit vagrant up vagrant ssh 

Оказавшись внутри виртуальной машины, мы клонируем StackEdit.

 cd ~/Code git clone https://github.com/benweet/stackedit cd stackedit npm install --no-bin-link 

Обратите внимание, что если вы получаете ошибки «Не удалось разрешить» во время выполнения этой команды и кучу других ошибок, как правило, «подробного» узла, это просто означает, что некоторые зависимости пропали. Перейдите в package.json и удалите значение хэштега из строки 23 и строки 28, если они все еще там. Эти теги ссылаются на версию, которая больше не существует, и автор StackEdit до сих пор не обновил файлы StackEdit, чтобы отразить это на момент написания этой статьи.

 bower install 

Это займет некоторое время. Если у вас установлен BowerPHP , вы можете использовать его вместо этого.

Чтобы запустить локальную копию, выполните следующее:

 (export PORT=5000 && node server.js) 

Затем зайдите на homestead.app:5000 в своем браузере (или на любой хост, который вы настроили, если не по умолчанию homestead.app ).

Реализация

Хорошо, давайте приступим к этому. Реализация будет состоять из двух частей — пользовательского интерфейса и логики.

UI

Давайте добавим кнопку.

StackEdit несколько сложнее расширять с точки зрения пользовательского интерфейса. Сам проект, после установки, содержит более 30000 файлов с загруженными зависимостями и партией. Это нелепо для веб-приложения и очень трудно индексировать для любой IDE, особенно если учесть, что JavaScript немного грязный. Есть несколько шагов в добавлении кнопки в интерфейс. Взгляд, на который мы пойдем, таков:

02

Значок «галочка» рядом с заголовком документа в форме глифика, который соответствует остальному интерфейсу в зависимости от используемой темы. Я использовал галочку, потому что глифы уже включены в Bootstrap в StackEdit. Это может быть не идеально с точки зрения контекста, но это самый быстрый способ получить то, что мы хотим, без редактирования слишком большого количества файлов (и мы будем редактировать многие из них по умолчанию, добавление к этим издержкам не имеет смысла).

Мы должны отредактировать представление public/res/html/bodyEditor.html — мы добавим новый контейнер значков вокруг строки 44 :

 <li><div class="working-indicator"></div></li> <li><div class="capitalize-button"></div></li> <li><a class="btn btn-success file-title-navbar" href="#" title="Rename document"> </a></li> 

Мы добавили контейнер «кнопка-заглавная буква» после контейнера «рабочий индикатор», поэтому наша кнопка появляется рядом с заголовком, где она больше всего соответствует контексту. Это всего лишь контейнер, хотя.

Все кнопки в пользовательском интерфейсе StackEdit созданы с использованием JS. Это происходит в файле public/res/libs/Markdown.Editor.js . Сначала добавим метку кнопки. В верхней части файла находится массив defaultStrings . Отредактируйте его так, чтобы он включал нашу метку заглавных букв, например:

 [...] help: "Markdown Editing Help", titlecapitalization: "Autocapitalize Title" }; 

Затем прокрутите вниз до функции makeSpritedButtonRow в том же файле и добавьте следующую if (helpOptions) { чуть выше блока if (helpOptions) { :

 buttons.titlecapitalization = makeButton("wmd-titlecapitalization", getString("titlecapitalization"), "-240px", bindCommand(function (chunk, postProcessing) { alert("Hello"); })); 

Это создаст кнопку, которая соответствует остальной части темы редактора, и присвоит ей атрибут title с заданной нами строкой, поэтому мы видим ее, когда наводим курсор мыши на кнопку. Это также заставит его сказать «Привет» при нажатии. Однако он все равно не будет отображаться в интерфейсе. Для этого нам нужно отредактировать public/res/core.js

Найти комментарий // Add customized buttons в этот файл и перейти в конец этого блока. Там добавьте следующее:

 $("#wmd-titlecapitalization").append($('<i class="icon-check">')).prependTo($('.capitalize-button')); 

Это найдет наш контейнер с кнопками и вставит в него нашу вновь созданную кнопку. Если вы теперь обновите редактор в режиме отладки ( homestead.app:5000/editor?debug ) и нажмете кнопку, вы должны увидеть предупреждение «Hello», как определено обратным вызовом в Markdown.Editor.js .

логика

Теперь, когда кнопка была добавлена, давайте сделаем так, как мы хотим.

Во-первых, давайте выберем текст поля заголовка. Отредактируйте Markdown.Editor.js . Заменить alert("Hello"); в обратном вызове кнопки со следующим:

 console.log($(".title-container a").text()); 

При нажатии кнопки теперь должен появиться заголовок текущего документа в консоли. Все идет нормально.

Чтобы получить логику того, что мы хотим сделать, мы собираемся «позаимствовать» код на TitleCapitalization.com . Если вы посмотрите на источник, то заметите, что все это есть в нижнем теге скрипта. Очистив это немного, чтобы удалить специфичные для сайта вещи, мы получим следующее:

 (function(){ var prepositions = [ 'a', 'abaft', 'aboard', 'about', 'above', 'absent', 'across', 'afore', 'after', 'against', 'along', 'alongside', 'amid', 'amidst', 'among', 'amongst', 'an', 'apropos', 'apud', 'around', 'as', 'aside', 'astride', 'at', 'athwart', 'atop', 'barring', 'before', 'behind', 'below', 'beneath', 'beside', 'besides', 'between', 'beyond', 'but', 'by', 'circa', 'concerning', 'despite', 'down', 'during', 'except', 'excluding', 'failing', 'following', 'for', 'from', 'given', 'in', 'including', 'inside', 'into', 'lest', 'like', 'mid', 'midst', 'minus', 'modulo', 'near', 'next', 'notwithstanding', 'of', 'off', 'on', 'onto', 'opposite', 'out', 'outside', 'over', 'pace', 'past', 'per', 'plus', 'pro', 'qua', 'regarding', 'round', 'sans', // while it technically can be a preoposition, // (http://www.merriam-webster.com/thesaurus/save[preposition]) // it is usually used as a verb // 'save', 'since', 'than', 'through', 'thru', 'throughout', 'thruout', 'till', 'times', 'to', 'toward', 'towards', 'under', 'underneath', 'unlike', 'until', 'unto', 'up', 'upon', 'versus', 'vs\.', 'vs', 'v\.', 'v', 'via', 'vice', 'with', 'within', 'without', 'worth' ]; var articles = [ 'a', 'an', 'the' ]; var conjunctions = [ 'and', 'but', 'for', 'so', 'nor', 'or', 'yet' ]; // var small = "(a|an|and|as|at|but|by|en|for|if|in|of|on|or|the|to|v[.]?|via|vs[.]?)"; var punct = "([!\"#$%&'()*+,./:;<=>?@[\\\\\\]^_`{|}~-]*)"; var all_lower_case = '(' + (prepositions.concat(articles).concat(conjunctions)).join('|') + ')'; console.log('all lower case', all_lower_case); window.titleCaps = function(title){ var parts = [], split = /[:.;?!] |(?: |^)["Ò]/g, index = 0; title = title.replace(/[\u2018\u2019]/g, "'") .replace(/[\u201C\u201D]/g, '"'); while (true) { var m = split.exec(title); parts.push( title.substring(index, m ? m.index : title.length) .replace(/\b([A-Za-z][az.'Õ]*)\b/g, function(all){ return /[A-Za-z]\.[A-Za-z]/.test(all) ? all : upper(all); }) //.replace(RegExp("\\b" + small + "\\b", "ig"), lower) //.replace(RegExp("^" + punct + small + "\\b", "ig"), function(all, punct, word){ // return punct + upper(word); //}) //.replace(RegExp("\\b" + small + punct + "$", "ig"), upper)); .replace(RegExp("\\b" + all_lower_case + "\\b", "ig"), lower) .replace(RegExp("^" + punct + all_lower_case + "\\b", "ig"), function(all, punct, word){ return punct + upper(word); }) .replace(RegExp("\\b" + all_lower_case + punct + "$", "ig"), upper)); index = split.lastIndex; if ( m ) parts.push( m[0] ); else break; } return parts.join("").replace(/ V(s?)\. /ig, " v$1. ") .replace(/(['Õ])S\b/ig, "$1s") .replace(/\b(AT&T|Q&A)\b/ig, function(all){ return all.toUpperCase(); }); }; function lower(word){ return word.toLowerCase(); } function upper(word){ return word.substr(0,1).toUpperCase() + word.substr(1); } })(); о (function(){ var prepositions = [ 'a', 'abaft', 'aboard', 'about', 'above', 'absent', 'across', 'afore', 'after', 'against', 'along', 'alongside', 'amid', 'amidst', 'among', 'amongst', 'an', 'apropos', 'apud', 'around', 'as', 'aside', 'astride', 'at', 'athwart', 'atop', 'barring', 'before', 'behind', 'below', 'beneath', 'beside', 'besides', 'between', 'beyond', 'but', 'by', 'circa', 'concerning', 'despite', 'down', 'during', 'except', 'excluding', 'failing', 'following', 'for', 'from', 'given', 'in', 'including', 'inside', 'into', 'lest', 'like', 'mid', 'midst', 'minus', 'modulo', 'near', 'next', 'notwithstanding', 'of', 'off', 'on', 'onto', 'opposite', 'out', 'outside', 'over', 'pace', 'past', 'per', 'plus', 'pro', 'qua', 'regarding', 'round', 'sans', // while it technically can be a preoposition, // (http://www.merriam-webster.com/thesaurus/save[preposition]) // it is usually used as a verb // 'save', 'since', 'than', 'through', 'thru', 'throughout', 'thruout', 'till', 'times', 'to', 'toward', 'towards', 'under', 'underneath', 'unlike', 'until', 'unto', 'up', 'upon', 'versus', 'vs\.', 'vs', 'v\.', 'v', 'via', 'vice', 'with', 'within', 'without', 'worth' ]; var articles = [ 'a', 'an', 'the' ]; var conjunctions = [ 'and', 'but', 'for', 'so', 'nor', 'or', 'yet' ]; // var small = "(a|an|and|as|at|but|by|en|for|if|in|of|on|or|the|to|v[.]?|via|vs[.]?)"; var punct = "([!\"#$%&'()*+,./:;<=>?@[\\\\\\]^_`{|}~-]*)"; var all_lower_case = '(' + (prepositions.concat(articles).concat(conjunctions)).join('|') + ')'; console.log('all lower case', all_lower_case); window.titleCaps = function(title){ var parts = [], split = /[:.;?!] |(?: |^)["Ò]/g, index = 0; title = title.replace(/[\u2018\u2019]/g, "'") .replace(/[\u201C\u201D]/g, '"'); while (true) { var m = split.exec(title); parts.push( title.substring(index, m ? m.index : title.length) .replace(/\b([A-Za-z][az.'Õ]*)\b/g, function(all){ return /[A-Za-z]\.[A-Za-z]/.test(all) ? all : upper(all); }) //.replace(RegExp("\\b" + small + "\\b", "ig"), lower) //.replace(RegExp("^" + punct + small + "\\b", "ig"), function(all, punct, word){ // return punct + upper(word); //}) //.replace(RegExp("\\b" + small + punct + "$", "ig"), upper)); .replace(RegExp("\\b" + all_lower_case + "\\b", "ig"), lower) .replace(RegExp("^" + punct + all_lower_case + "\\b", "ig"), function(all, punct, word){ return punct + upper(word); }) .replace(RegExp("\\b" + all_lower_case + punct + "$", "ig"), upper)); index = split.lastIndex; if ( m ) parts.push( m[0] ); else break; } return parts.join("").replace(/ V(s?)\. /ig, " v$1. ") .replace(/(['Õ])S\b/ig, "$1s") .replace(/\b(AT&T|Q&A)\b/ig, function(all){ return all.toUpperCase(); }); }; function lower(word){ return word.toLowerCase(); } function upper(word){ return word.substr(0,1).toUpperCase() + word.substr(1); } })(); по (function(){ var prepositions = [ 'a', 'abaft', 'aboard', 'about', 'above', 'absent', 'across', 'afore', 'after', 'against', 'along', 'alongside', 'amid', 'amidst', 'among', 'amongst', 'an', 'apropos', 'apud', 'around', 'as', 'aside', 'astride', 'at', 'athwart', 'atop', 'barring', 'before', 'behind', 'below', 'beneath', 'beside', 'besides', 'between', 'beyond', 'but', 'by', 'circa', 'concerning', 'despite', 'down', 'during', 'except', 'excluding', 'failing', 'following', 'for', 'from', 'given', 'in', 'including', 'inside', 'into', 'lest', 'like', 'mid', 'midst', 'minus', 'modulo', 'near', 'next', 'notwithstanding', 'of', 'off', 'on', 'onto', 'opposite', 'out', 'outside', 'over', 'pace', 'past', 'per', 'plus', 'pro', 'qua', 'regarding', 'round', 'sans', // while it technically can be a preoposition, // (http://www.merriam-webster.com/thesaurus/save[preposition]) // it is usually used as a verb // 'save', 'since', 'than', 'through', 'thru', 'throughout', 'thruout', 'till', 'times', 'to', 'toward', 'towards', 'under', 'underneath', 'unlike', 'until', 'unto', 'up', 'upon', 'versus', 'vs\.', 'vs', 'v\.', 'v', 'via', 'vice', 'with', 'within', 'without', 'worth' ]; var articles = [ 'a', 'an', 'the' ]; var conjunctions = [ 'and', 'but', 'for', 'so', 'nor', 'or', 'yet' ]; // var small = "(a|an|and|as|at|but|by|en|for|if|in|of|on|or|the|to|v[.]?|via|vs[.]?)"; var punct = "([!\"#$%&'()*+,./:;<=>?@[\\\\\\]^_`{|}~-]*)"; var all_lower_case = '(' + (prepositions.concat(articles).concat(conjunctions)).join('|') + ')'; console.log('all lower case', all_lower_case); window.titleCaps = function(title){ var parts = [], split = /[:.;?!] |(?: |^)["Ò]/g, index = 0; title = title.replace(/[\u2018\u2019]/g, "'") .replace(/[\u201C\u201D]/g, '"'); while (true) { var m = split.exec(title); parts.push( title.substring(index, m ? m.index : title.length) .replace(/\b([A-Za-z][az.'Õ]*)\b/g, function(all){ return /[A-Za-z]\.[A-Za-z]/.test(all) ? all : upper(all); }) //.replace(RegExp("\\b" + small + "\\b", "ig"), lower) //.replace(RegExp("^" + punct + small + "\\b", "ig"), function(all, punct, word){ // return punct + upper(word); //}) //.replace(RegExp("\\b" + small + punct + "$", "ig"), upper)); .replace(RegExp("\\b" + all_lower_case + "\\b", "ig"), lower) .replace(RegExp("^" + punct + all_lower_case + "\\b", "ig"), function(all, punct, word){ return punct + upper(word); }) .replace(RegExp("\\b" + all_lower_case + punct + "$", "ig"), upper)); index = split.lastIndex; if ( m ) parts.push( m[0] ); else break; } return parts.join("").replace(/ V(s?)\. /ig, " v$1. ") .replace(/(['Õ])S\b/ig, "$1s") .replace(/\b(AT&T|Q&A)\b/ig, function(all){ return all.toUpperCase(); }); }; function lower(word){ return word.toLowerCase(); } function upper(word){ return word.substr(0,1).toUpperCase() + word.substr(1); } })(); по (function(){ var prepositions = [ 'a', 'abaft', 'aboard', 'about', 'above', 'absent', 'across', 'afore', 'after', 'against', 'along', 'alongside', 'amid', 'amidst', 'among', 'amongst', 'an', 'apropos', 'apud', 'around', 'as', 'aside', 'astride', 'at', 'athwart', 'atop', 'barring', 'before', 'behind', 'below', 'beneath', 'beside', 'besides', 'between', 'beyond', 'but', 'by', 'circa', 'concerning', 'despite', 'down', 'during', 'except', 'excluding', 'failing', 'following', 'for', 'from', 'given', 'in', 'including', 'inside', 'into', 'lest', 'like', 'mid', 'midst', 'minus', 'modulo', 'near', 'next', 'notwithstanding', 'of', 'off', 'on', 'onto', 'opposite', 'out', 'outside', 'over', 'pace', 'past', 'per', 'plus', 'pro', 'qua', 'regarding', 'round', 'sans', // while it technically can be a preoposition, // (http://www.merriam-webster.com/thesaurus/save[preposition]) // it is usually used as a verb // 'save', 'since', 'than', 'through', 'thru', 'throughout', 'thruout', 'till', 'times', 'to', 'toward', 'towards', 'under', 'underneath', 'unlike', 'until', 'unto', 'up', 'upon', 'versus', 'vs\.', 'vs', 'v\.', 'v', 'via', 'vice', 'with', 'within', 'without', 'worth' ]; var articles = [ 'a', 'an', 'the' ]; var conjunctions = [ 'and', 'but', 'for', 'so', 'nor', 'or', 'yet' ]; // var small = "(a|an|and|as|at|but|by|en|for|if|in|of|on|or|the|to|v[.]?|via|vs[.]?)"; var punct = "([!\"#$%&'()*+,./:;<=>?@[\\\\\\]^_`{|}~-]*)"; var all_lower_case = '(' + (prepositions.concat(articles).concat(conjunctions)).join('|') + ')'; console.log('all lower case', all_lower_case); window.titleCaps = function(title){ var parts = [], split = /[:.;?!] |(?: |^)["Ò]/g, index = 0; title = title.replace(/[\u2018\u2019]/g, "'") .replace(/[\u201C\u201D]/g, '"'); while (true) { var m = split.exec(title); parts.push( title.substring(index, m ? m.index : title.length) .replace(/\b([A-Za-z][az.'Õ]*)\b/g, function(all){ return /[A-Za-z]\.[A-Za-z]/.test(all) ? all : upper(all); }) //.replace(RegExp("\\b" + small + "\\b", "ig"), lower) //.replace(RegExp("^" + punct + small + "\\b", "ig"), function(all, punct, word){ // return punct + upper(word); //}) //.replace(RegExp("\\b" + small + punct + "$", "ig"), upper)); .replace(RegExp("\\b" + all_lower_case + "\\b", "ig"), lower) .replace(RegExp("^" + punct + all_lower_case + "\\b", "ig"), function(all, punct, word){ return punct + upper(word); }) .replace(RegExp("\\b" + all_lower_case + punct + "$", "ig"), upper)); index = split.lastIndex; if ( m ) parts.push( m[0] ); else break; } return parts.join("").replace(/ V(s?)\. /ig, " v$1. ") .replace(/(['Õ])S\b/ig, "$1s") .replace(/\b(AT&T|Q&A)\b/ig, function(all){ return all.toUpperCase(); }); }; function lower(word){ return word.toLowerCase(); } function upper(word){ return word.substr(0,1).toUpperCase() + word.substr(1); } })(); на то (function(){ var prepositions = [ 'a', 'abaft', 'aboard', 'about', 'above', 'absent', 'across', 'afore', 'after', 'against', 'along', 'alongside', 'amid', 'amidst', 'among', 'amongst', 'an', 'apropos', 'apud', 'around', 'as', 'aside', 'astride', 'at', 'athwart', 'atop', 'barring', 'before', 'behind', 'below', 'beneath', 'beside', 'besides', 'between', 'beyond', 'but', 'by', 'circa', 'concerning', 'despite', 'down', 'during', 'except', 'excluding', 'failing', 'following', 'for', 'from', 'given', 'in', 'including', 'inside', 'into', 'lest', 'like', 'mid', 'midst', 'minus', 'modulo', 'near', 'next', 'notwithstanding', 'of', 'off', 'on', 'onto', 'opposite', 'out', 'outside', 'over', 'pace', 'past', 'per', 'plus', 'pro', 'qua', 'regarding', 'round', 'sans', // while it technically can be a preoposition, // (http://www.merriam-webster.com/thesaurus/save[preposition]) // it is usually used as a verb // 'save', 'since', 'than', 'through', 'thru', 'throughout', 'thruout', 'till', 'times', 'to', 'toward', 'towards', 'under', 'underneath', 'unlike', 'until', 'unto', 'up', 'upon', 'versus', 'vs\.', 'vs', 'v\.', 'v', 'via', 'vice', 'with', 'within', 'without', 'worth' ]; var articles = [ 'a', 'an', 'the' ]; var conjunctions = [ 'and', 'but', 'for', 'so', 'nor', 'or', 'yet' ]; // var small = "(a|an|and|as|at|but|by|en|for|if|in|of|on|or|the|to|v[.]?|via|vs[.]?)"; var punct = "([!\"#$%&'()*+,./:;<=>?@[\\\\\\]^_`{|}~-]*)"; var all_lower_case = '(' + (prepositions.concat(articles).concat(conjunctions)).join('|') + ')'; console.log('all lower case', all_lower_case); window.titleCaps = function(title){ var parts = [], split = /[:.;?!] |(?: |^)["Ò]/g, index = 0; title = title.replace(/[\u2018\u2019]/g, "'") .replace(/[\u201C\u201D]/g, '"'); while (true) { var m = split.exec(title); parts.push( title.substring(index, m ? m.index : title.length) .replace(/\b([A-Za-z][az.'Õ]*)\b/g, function(all){ return /[A-Za-z]\.[A-Za-z]/.test(all) ? all : upper(all); }) //.replace(RegExp("\\b" + small + "\\b", "ig"), lower) //.replace(RegExp("^" + punct + small + "\\b", "ig"), function(all, punct, word){ // return punct + upper(word); //}) //.replace(RegExp("\\b" + small + punct + "$", "ig"), upper)); .replace(RegExp("\\b" + all_lower_case + "\\b", "ig"), lower) .replace(RegExp("^" + punct + all_lower_case + "\\b", "ig"), function(all, punct, word){ return punct + upper(word); }) .replace(RegExp("\\b" + all_lower_case + punct + "$", "ig"), upper)); index = split.lastIndex; if ( m ) parts.push( m[0] ); else break; } return parts.join("").replace(/ V(s?)\. /ig, " v$1. ") .replace(/(['Õ])S\b/ig, "$1s") .replace(/\b(AT&T|Q&A)\b/ig, function(all){ return all.toUpperCase(); }); }; function lower(word){ return word.toLowerCase(); } function upper(word){ return word.substr(0,1).toUpperCase() + word.substr(1); } })(); в (function(){ var prepositions = [ 'a', 'abaft', 'aboard', 'about', 'above', 'absent', 'across', 'afore', 'after', 'against', 'along', 'alongside', 'amid', 'amidst', 'among', 'amongst', 'an', 'apropos', 'apud', 'around', 'as', 'aside', 'astride', 'at', 'athwart', 'atop', 'barring', 'before', 'behind', 'below', 'beneath', 'beside', 'besides', 'between', 'beyond', 'but', 'by', 'circa', 'concerning', 'despite', 'down', 'during', 'except', 'excluding', 'failing', 'following', 'for', 'from', 'given', 'in', 'including', 'inside', 'into', 'lest', 'like', 'mid', 'midst', 'minus', 'modulo', 'near', 'next', 'notwithstanding', 'of', 'off', 'on', 'onto', 'opposite', 'out', 'outside', 'over', 'pace', 'past', 'per', 'plus', 'pro', 'qua', 'regarding', 'round', 'sans', // while it technically can be a preoposition, // (http://www.merriam-webster.com/thesaurus/save[preposition]) // it is usually used as a verb // 'save', 'since', 'than', 'through', 'thru', 'throughout', 'thruout', 'till', 'times', 'to', 'toward', 'towards', 'under', 'underneath', 'unlike', 'until', 'unto', 'up', 'upon', 'versus', 'vs\.', 'vs', 'v\.', 'v', 'via', 'vice', 'with', 'within', 'without', 'worth' ]; var articles = [ 'a', 'an', 'the' ]; var conjunctions = [ 'and', 'but', 'for', 'so', 'nor', 'or', 'yet' ]; // var small = "(a|an|and|as|at|but|by|en|for|if|in|of|on|or|the|to|v[.]?|via|vs[.]?)"; var punct = "([!\"#$%&'()*+,./:;<=>?@[\\\\\\]^_`{|}~-]*)"; var all_lower_case = '(' + (prepositions.concat(articles).concat(conjunctions)).join('|') + ')'; console.log('all lower case', all_lower_case); window.titleCaps = function(title){ var parts = [], split = /[:.;?!] |(?: |^)["Ò]/g, index = 0; title = title.replace(/[\u2018\u2019]/g, "'") .replace(/[\u201C\u201D]/g, '"'); while (true) { var m = split.exec(title); parts.push( title.substring(index, m ? m.index : title.length) .replace(/\b([A-Za-z][az.'Õ]*)\b/g, function(all){ return /[A-Za-z]\.[A-Za-z]/.test(all) ? all : upper(all); }) //.replace(RegExp("\\b" + small + "\\b", "ig"), lower) //.replace(RegExp("^" + punct + small + "\\b", "ig"), function(all, punct, word){ // return punct + upper(word); //}) //.replace(RegExp("\\b" + small + punct + "$", "ig"), upper)); .replace(RegExp("\\b" + all_lower_case + "\\b", "ig"), lower) .replace(RegExp("^" + punct + all_lower_case + "\\b", "ig"), function(all, punct, word){ return punct + upper(word); }) .replace(RegExp("\\b" + all_lower_case + punct + "$", "ig"), upper)); index = split.lastIndex; if ( m ) parts.push( m[0] ); else break; } return parts.join("").replace(/ V(s?)\. /ig, " v$1. ") .replace(/(['Õ])S\b/ig, "$1s") .replace(/\b(AT&T|Q&A)\b/ig, function(all){ return all.toUpperCase(); }); }; function lower(word){ return word.toLowerCase(); } function upper(word){ return word.substr(0,1).toUpperCase() + word.substr(1); } })(); 

Если вы вставите это прямо в консоль прямо сейчас, у вас будет доступ к корневой функции с названием «titleCaps», которая принимает строку и печатает строку с заглавными буквами. Это именно то, что нам нужно.

Измените обратный вызов для кнопки еще раз, и измените его на это:

 var titleContainer = $('.title-container a'); var capitalized = capitalize($(titleContainer).text()); $(titleContainer).text(capitalized); $(".input-file-title").val(capitalized); 

Теперь все, что нам не хватает — это функция с capitalize Просматривая код Markdown.Editor.js , мы видим, что универсальные функции там, как есть (см., Например, properlyEncoded закодированный). Таким образом, нам не нужно думать о том, чтобы включить наши тоже. В конце файла, перед последним })(); добавьте следующее:

 var prepositions = [ 'a', 'abaft', 'aboard', 'about', 'above', 'absent', 'across', 'afore', 'after', 'against', 'along', 'alongside', 'amid', 'amidst', 'among', 'amongst', 'an', 'apropos', 'apud', 'around', 'as', 'aside', 'astride', 'at', 'athwart', 'atop', 'barring', 'before', 'behind', 'below', 'beneath', 'beside', 'besides', 'between', 'beyond', 'but', 'by', 'circa', 'concerning', 'despite', 'down', 'during', 'except', 'excluding', 'failing', 'following', 'for', 'from', 'given', 'in', 'including', 'inside', 'into', 'lest', 'like', 'mid', 'midst', 'minus', 'modulo', 'near', 'next', 'notwithstanding', 'of', 'off', 'on', 'onto', 'opposite', 'out', 'outside', 'over', 'pace', 'past', 'per', 'plus', 'pro', 'qua', 'regarding', 'round', 'sans', 'since', 'than', 'through', 'thru', 'throughout', 'thruout', 'till', 'times', 'to', 'toward', 'towards', 'under', 'underneath', 'unlike', 'until', 'unto', 'up', 'upon', 'versus', 'vs\.', 'vs', 'v\.', 'v', 'via', 'vice', 'with', 'within', 'without', 'worth' ]; var articles = [ 'a', 'an', 'the' ]; var conjunctions = [ 'and', 'but', 'for', 'so', 'nor', 'or', 'yet' ]; var punct = "([!\"#$%&'()*+,./:;<=>?@[\\\\\\]^_`{|}~-]*)"; var all_lower_case = '(' + (prepositions.concat(articles).concat(conjunctions)).join('|') + ')'; console.log('all lower case', all_lower_case); var capitalize = function(title){ var parts = [], split = /[:.;?!] |(?: |^)["Ò]/g, index = 0; title = title.replace(/[\u2018\u2019]/g, "'") .replace(/[\u201C\u201D]/g, '"'); while (true) { var m = split.exec(title); parts.push( title.substring(index, m ? m.index : title.length) .replace(/\b([A-Za-z][az.'Õ]*)\b/g, function(all){ return /[A-Za-z]\.[A-Za-z]/.test(all) ? all : upper(all); }) .replace(RegExp("\\b" + all_lower_case + "\\b", "ig"), lower) .replace(RegExp("^" + punct + all_lower_case + "\\b", "ig"), function(all, punct, word){ return punct + upper(word); }) .replace(RegExp("\\b" + all_lower_case + punct + "$", "ig"), upper)); index = split.lastIndex; if ( m ) parts.push( m[0] ); else break; } return parts.join("").replace(/ V(s?)\. /ig, " v$1. ") .replace(/(['Õ])S\b/ig, "$1s") .replace(/\b(AT&T|Q&A)\b/ig, function(all){ return all.toUpperCase(); }); }; function lower(word){ return word.toLowerCase(); } function upper(word){ return word.substr(0,1).toUpperCase() + word.substr(1); } о var prepositions = [ 'a', 'abaft', 'aboard', 'about', 'above', 'absent', 'across', 'afore', 'after', 'against', 'along', 'alongside', 'amid', 'amidst', 'among', 'amongst', 'an', 'apropos', 'apud', 'around', 'as', 'aside', 'astride', 'at', 'athwart', 'atop', 'barring', 'before', 'behind', 'below', 'beneath', 'beside', 'besides', 'between', 'beyond', 'but', 'by', 'circa', 'concerning', 'despite', 'down', 'during', 'except', 'excluding', 'failing', 'following', 'for', 'from', 'given', 'in', 'including', 'inside', 'into', 'lest', 'like', 'mid', 'midst', 'minus', 'modulo', 'near', 'next', 'notwithstanding', 'of', 'off', 'on', 'onto', 'opposite', 'out', 'outside', 'over', 'pace', 'past', 'per', 'plus', 'pro', 'qua', 'regarding', 'round', 'sans', 'since', 'than', 'through', 'thru', 'throughout', 'thruout', 'till', 'times', 'to', 'toward', 'towards', 'under', 'underneath', 'unlike', 'until', 'unto', 'up', 'upon', 'versus', 'vs\.', 'vs', 'v\.', 'v', 'via', 'vice', 'with', 'within', 'without', 'worth' ]; var articles = [ 'a', 'an', 'the' ]; var conjunctions = [ 'and', 'but', 'for', 'so', 'nor', 'or', 'yet' ]; var punct = "([!\"#$%&'()*+,./:;<=>?@[\\\\\\]^_`{|}~-]*)"; var all_lower_case = '(' + (prepositions.concat(articles).concat(conjunctions)).join('|') + ')'; console.log('all lower case', all_lower_case); var capitalize = function(title){ var parts = [], split = /[:.;?!] |(?: |^)["Ò]/g, index = 0; title = title.replace(/[\u2018\u2019]/g, "'") .replace(/[\u201C\u201D]/g, '"'); while (true) { var m = split.exec(title); parts.push( title.substring(index, m ? m.index : title.length) .replace(/\b([A-Za-z][az.'Õ]*)\b/g, function(all){ return /[A-Za-z]\.[A-Za-z]/.test(all) ? all : upper(all); }) .replace(RegExp("\\b" + all_lower_case + "\\b", "ig"), lower) .replace(RegExp("^" + punct + all_lower_case + "\\b", "ig"), function(all, punct, word){ return punct + upper(word); }) .replace(RegExp("\\b" + all_lower_case + punct + "$", "ig"), upper)); index = split.lastIndex; if ( m ) parts.push( m[0] ); else break; } return parts.join("").replace(/ V(s?)\. /ig, " v$1. ") .replace(/(['Õ])S\b/ig, "$1s") .replace(/\b(AT&T|Q&A)\b/ig, function(all){ return all.toUpperCase(); }); }; function lower(word){ return word.toLowerCase(); } function upper(word){ return word.substr(0,1).toUpperCase() + word.substr(1); } по var prepositions = [ 'a', 'abaft', 'aboard', 'about', 'above', 'absent', 'across', 'afore', 'after', 'against', 'along', 'alongside', 'amid', 'amidst', 'among', 'amongst', 'an', 'apropos', 'apud', 'around', 'as', 'aside', 'astride', 'at', 'athwart', 'atop', 'barring', 'before', 'behind', 'below', 'beneath', 'beside', 'besides', 'between', 'beyond', 'but', 'by', 'circa', 'concerning', 'despite', 'down', 'during', 'except', 'excluding', 'failing', 'following', 'for', 'from', 'given', 'in', 'including', 'inside', 'into', 'lest', 'like', 'mid', 'midst', 'minus', 'modulo', 'near', 'next', 'notwithstanding', 'of', 'off', 'on', 'onto', 'opposite', 'out', 'outside', 'over', 'pace', 'past', 'per', 'plus', 'pro', 'qua', 'regarding', 'round', 'sans', 'since', 'than', 'through', 'thru', 'throughout', 'thruout', 'till', 'times', 'to', 'toward', 'towards', 'under', 'underneath', 'unlike', 'until', 'unto', 'up', 'upon', 'versus', 'vs\.', 'vs', 'v\.', 'v', 'via', 'vice', 'with', 'within', 'without', 'worth' ]; var articles = [ 'a', 'an', 'the' ]; var conjunctions = [ 'and', 'but', 'for', 'so', 'nor', 'or', 'yet' ]; var punct = "([!\"#$%&'()*+,./:;<=>?@[\\\\\\]^_`{|}~-]*)"; var all_lower_case = '(' + (prepositions.concat(articles).concat(conjunctions)).join('|') + ')'; console.log('all lower case', all_lower_case); var capitalize = function(title){ var parts = [], split = /[:.;?!] |(?: |^)["Ò]/g, index = 0; title = title.replace(/[\u2018\u2019]/g, "'") .replace(/[\u201C\u201D]/g, '"'); while (true) { var m = split.exec(title); parts.push( title.substring(index, m ? m.index : title.length) .replace(/\b([A-Za-z][az.'Õ]*)\b/g, function(all){ return /[A-Za-z]\.[A-Za-z]/.test(all) ? all : upper(all); }) .replace(RegExp("\\b" + all_lower_case + "\\b", "ig"), lower) .replace(RegExp("^" + punct + all_lower_case + "\\b", "ig"), function(all, punct, word){ return punct + upper(word); }) .replace(RegExp("\\b" + all_lower_case + punct + "$", "ig"), upper)); index = split.lastIndex; if ( m ) parts.push( m[0] ); else break; } return parts.join("").replace(/ V(s?)\. /ig, " v$1. ") .replace(/(['Õ])S\b/ig, "$1s") .replace(/\b(AT&T|Q&A)\b/ig, function(all){ return all.toUpperCase(); }); }; function lower(word){ return word.toLowerCase(); } function upper(word){ return word.substr(0,1).toUpperCase() + word.substr(1); } по var prepositions = [ 'a', 'abaft', 'aboard', 'about', 'above', 'absent', 'across', 'afore', 'after', 'against', 'along', 'alongside', 'amid', 'amidst', 'among', 'amongst', 'an', 'apropos', 'apud', 'around', 'as', 'aside', 'astride', 'at', 'athwart', 'atop', 'barring', 'before', 'behind', 'below', 'beneath', 'beside', 'besides', 'between', 'beyond', 'but', 'by', 'circa', 'concerning', 'despite', 'down', 'during', 'except', 'excluding', 'failing', 'following', 'for', 'from', 'given', 'in', 'including', 'inside', 'into', 'lest', 'like', 'mid', 'midst', 'minus', 'modulo', 'near', 'next', 'notwithstanding', 'of', 'off', 'on', 'onto', 'opposite', 'out', 'outside', 'over', 'pace', 'past', 'per', 'plus', 'pro', 'qua', 'regarding', 'round', 'sans', 'since', 'than', 'through', 'thru', 'throughout', 'thruout', 'till', 'times', 'to', 'toward', 'towards', 'under', 'underneath', 'unlike', 'until', 'unto', 'up', 'upon', 'versus', 'vs\.', 'vs', 'v\.', 'v', 'via', 'vice', 'with', 'within', 'without', 'worth' ]; var articles = [ 'a', 'an', 'the' ]; var conjunctions = [ 'and', 'but', 'for', 'so', 'nor', 'or', 'yet' ]; var punct = "([!\"#$%&'()*+,./:;<=>?@[\\\\\\]^_`{|}~-]*)"; var all_lower_case = '(' + (prepositions.concat(articles).concat(conjunctions)).join('|') + ')'; console.log('all lower case', all_lower_case); var capitalize = function(title){ var parts = [], split = /[:.;?!] |(?: |^)["Ò]/g, index = 0; title = title.replace(/[\u2018\u2019]/g, "'") .replace(/[\u201C\u201D]/g, '"'); while (true) { var m = split.exec(title); parts.push( title.substring(index, m ? m.index : title.length) .replace(/\b([A-Za-z][az.'Õ]*)\b/g, function(all){ return /[A-Za-z]\.[A-Za-z]/.test(all) ? all : upper(all); }) .replace(RegExp("\\b" + all_lower_case + "\\b", "ig"), lower) .replace(RegExp("^" + punct + all_lower_case + "\\b", "ig"), function(all, punct, word){ return punct + upper(word); }) .replace(RegExp("\\b" + all_lower_case + punct + "$", "ig"), upper)); index = split.lastIndex; if ( m ) parts.push( m[0] ); else break; } return parts.join("").replace(/ V(s?)\. /ig, " v$1. ") .replace(/(['Õ])S\b/ig, "$1s") .replace(/\b(AT&T|Q&A)\b/ig, function(all){ return all.toUpperCase(); }); }; function lower(word){ return word.toLowerCase(); } function upper(word){ return word.substr(0,1).toUpperCase() + word.substr(1); } на то var prepositions = [ 'a', 'abaft', 'aboard', 'about', 'above', 'absent', 'across', 'afore', 'after', 'against', 'along', 'alongside', 'amid', 'amidst', 'among', 'amongst', 'an', 'apropos', 'apud', 'around', 'as', 'aside', 'astride', 'at', 'athwart', 'atop', 'barring', 'before', 'behind', 'below', 'beneath', 'beside', 'besides', 'between', 'beyond', 'but', 'by', 'circa', 'concerning', 'despite', 'down', 'during', 'except', 'excluding', 'failing', 'following', 'for', 'from', 'given', 'in', 'including', 'inside', 'into', 'lest', 'like', 'mid', 'midst', 'minus', 'modulo', 'near', 'next', 'notwithstanding', 'of', 'off', 'on', 'onto', 'opposite', 'out', 'outside', 'over', 'pace', 'past', 'per', 'plus', 'pro', 'qua', 'regarding', 'round', 'sans', 'since', 'than', 'through', 'thru', 'throughout', 'thruout', 'till', 'times', 'to', 'toward', 'towards', 'under', 'underneath', 'unlike', 'until', 'unto', 'up', 'upon', 'versus', 'vs\.', 'vs', 'v\.', 'v', 'via', 'vice', 'with', 'within', 'without', 'worth' ]; var articles = [ 'a', 'an', 'the' ]; var conjunctions = [ 'and', 'but', 'for', 'so', 'nor', 'or', 'yet' ]; var punct = "([!\"#$%&'()*+,./:;<=>?@[\\\\\\]^_`{|}~-]*)"; var all_lower_case = '(' + (prepositions.concat(articles).concat(conjunctions)).join('|') + ')'; console.log('all lower case', all_lower_case); var capitalize = function(title){ var parts = [], split = /[:.;?!] |(?: |^)["Ò]/g, index = 0; title = title.replace(/[\u2018\u2019]/g, "'") .replace(/[\u201C\u201D]/g, '"'); while (true) { var m = split.exec(title); parts.push( title.substring(index, m ? m.index : title.length) .replace(/\b([A-Za-z][az.'Õ]*)\b/g, function(all){ return /[A-Za-z]\.[A-Za-z]/.test(all) ? all : upper(all); }) .replace(RegExp("\\b" + all_lower_case + "\\b", "ig"), lower) .replace(RegExp("^" + punct + all_lower_case + "\\b", "ig"), function(all, punct, word){ return punct + upper(word); }) .replace(RegExp("\\b" + all_lower_case + punct + "$", "ig"), upper)); index = split.lastIndex; if ( m ) parts.push( m[0] ); else break; } return parts.join("").replace(/ V(s?)\. /ig, " v$1. ") .replace(/(['Õ])S\b/ig, "$1s") .replace(/\b(AT&T|Q&A)\b/ig, function(all){ return all.toUpperCase(); }); }; function lower(word){ return word.toLowerCase(); } function upper(word){ return word.substr(0,1).toUpperCase() + word.substr(1); } в var prepositions = [ 'a', 'abaft', 'aboard', 'about', 'above', 'absent', 'across', 'afore', 'after', 'against', 'along', 'alongside', 'amid', 'amidst', 'among', 'amongst', 'an', 'apropos', 'apud', 'around', 'as', 'aside', 'astride', 'at', 'athwart', 'atop', 'barring', 'before', 'behind', 'below', 'beneath', 'beside', 'besides', 'between', 'beyond', 'but', 'by', 'circa', 'concerning', 'despite', 'down', 'during', 'except', 'excluding', 'failing', 'following', 'for', 'from', 'given', 'in', 'including', 'inside', 'into', 'lest', 'like', 'mid', 'midst', 'minus', 'modulo', 'near', 'next', 'notwithstanding', 'of', 'off', 'on', 'onto', 'opposite', 'out', 'outside', 'over', 'pace', 'past', 'per', 'plus', 'pro', 'qua', 'regarding', 'round', 'sans', 'since', 'than', 'through', 'thru', 'throughout', 'thruout', 'till', 'times', 'to', 'toward', 'towards', 'under', 'underneath', 'unlike', 'until', 'unto', 'up', 'upon', 'versus', 'vs\.', 'vs', 'v\.', 'v', 'via', 'vice', 'with', 'within', 'without', 'worth' ]; var articles = [ 'a', 'an', 'the' ]; var conjunctions = [ 'and', 'but', 'for', 'so', 'nor', 'or', 'yet' ]; var punct = "([!\"#$%&'()*+,./:;<=>?@[\\\\\\]^_`{|}~-]*)"; var all_lower_case = '(' + (prepositions.concat(articles).concat(conjunctions)).join('|') + ')'; console.log('all lower case', all_lower_case); var capitalize = function(title){ var parts = [], split = /[:.;?!] |(?: |^)["Ò]/g, index = 0; title = title.replace(/[\u2018\u2019]/g, "'") .replace(/[\u201C\u201D]/g, '"'); while (true) { var m = split.exec(title); parts.push( title.substring(index, m ? m.index : title.length) .replace(/\b([A-Za-z][az.'Õ]*)\b/g, function(all){ return /[A-Za-z]\.[A-Za-z]/.test(all) ? all : upper(all); }) .replace(RegExp("\\b" + all_lower_case + "\\b", "ig"), lower) .replace(RegExp("^" + punct + all_lower_case + "\\b", "ig"), function(all, punct, word){ return punct + upper(word); }) .replace(RegExp("\\b" + all_lower_case + punct + "$", "ig"), upper)); index = split.lastIndex; if ( m ) parts.push( m[0] ); else break; } return parts.join("").replace(/ V(s?)\. /ig, " v$1. ") .replace(/(['Õ])S\b/ig, "$1s") .replace(/\b(AT&T|Q&A)\b/ig, function(all){ return all.toUpperCase(); }); }; function lower(word){ return word.toLowerCase(); } function upper(word){ return word.substr(0,1).toUpperCase() + word.substr(1); } 

Если вы протестируете это сейчас, вы заметите, что заголовок типа «Hello world» превращается в «Hello World». Нажав на поле заголовка, вы заметите, что это относится и к тексту внутри — все было правильно написано заглавными буквами:

01

Вывод

В этом посте мы реализовали желаемую новую функцию в StackEdit, редакторе MarkDown, сначала разместив ее локально. Мы добавили кнопку, украли функциональность из TitleCapitalization и переработали ее в нашу среду. Теперь мы можем использовать это обновление для отправки запроса на извлечение владельцу проекта, если мы того пожелаем. К тому времени, когда вы прочитаете это, оно может быть принято и отклонено, но в любом случае наша локальная копия имеет реализованную функциональность, и мы можем работать с ней так, как задумано.

Комментарии? Обратная связь? Дай мне знать!