Merge branch 'mentions-with-dots' into new

This commit is contained in:
2022-07-09 15:24:08 +03:00
15 changed files with 298 additions and 145 deletions

View File

@@ -58,6 +58,7 @@ As you can see, the component accepts some props:
| ---- | ---- | -------- | | ---- | ---- | -------- |
| value | String | The text to highlight (**v-model**). | | value | String | The text to highlight (**v-model**). |
| extractUrlsWithoutProtocol | Boolean | As the name says, when active, the compoponet will try to match URLs even when a protocol (http://, https://) is not found. **Defaults to true** | | extractUrlsWithoutProtocol | Boolean | As the name says, when active, the compoponet will try to match URLs even when a protocol (http://, https://) is not found. **Defaults to true** |
| mentionsWithDots | Boolean | Whether a mention can contain a dot. **Defaults to false** |
| caretColor | String | A valid HEX color (eg. #ccc, #ff4545). | | caretColor | String | A valid HEX color (eg. #ccc, #ff4545). |
| placeholder | String | A placeholder to show when no text is entered. | | placeholder | String | A placeholder to show when no text is entered. |
| usernameClass | String | The CSS class(es) that will be added to a @username match. | | usernameClass | String | The CSS class(es) that will be added to a @username match. |

View File

@@ -641,6 +641,91 @@ module.exports = function(module) {
}; };
/***/ }),
/***/ "8875":
/***/ (function(module, exports, __webpack_require__) {
var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;// addapted from the document.currentScript polyfill by Adam Miller
// MIT license
// source: https://github.com/amiller-gh/currentScript-polyfill
// added support for Firefox https://bugzilla.mozilla.org/show_bug.cgi?id=1620505
(function (root, factory) {
if (true) {
!(__WEBPACK_AMD_DEFINE_ARRAY__ = [], __WEBPACK_AMD_DEFINE_FACTORY__ = (factory),
__WEBPACK_AMD_DEFINE_RESULT__ = (typeof __WEBPACK_AMD_DEFINE_FACTORY__ === 'function' ?
(__WEBPACK_AMD_DEFINE_FACTORY__.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__)) : __WEBPACK_AMD_DEFINE_FACTORY__),
__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
} else {}
}(typeof self !== 'undefined' ? self : this, function () {
function getCurrentScript () {
var descriptor = Object.getOwnPropertyDescriptor(document, 'currentScript')
// for chrome
if (!descriptor && 'currentScript' in document && document.currentScript) {
return document.currentScript
}
// for other browsers with native support for currentScript
if (descriptor && descriptor.get !== getCurrentScript && document.currentScript) {
return document.currentScript
}
// IE 8-10 support script readyState
// IE 11+ & Firefox support stack trace
try {
throw new Error();
}
catch (err) {
// Find the second match for the "at" string to get file src url from stack.
var ieStackRegExp = /.*at [^(]*\((.*):(.+):(.+)\)$/ig,
ffStackRegExp = /@([^@]*):(\d+):(\d+)\s*$/ig,
stackDetails = ieStackRegExp.exec(err.stack) || ffStackRegExp.exec(err.stack),
scriptLocation = (stackDetails && stackDetails[1]) || false,
line = (stackDetails && stackDetails[2]) || false,
currentLocation = document.location.href.replace(document.location.hash, ''),
pageSource,
inlineScriptSourceRegExp,
inlineScriptSource,
scripts = document.getElementsByTagName('script'); // Live NodeList collection
if (scriptLocation === currentLocation) {
pageSource = document.documentElement.outerHTML;
inlineScriptSourceRegExp = new RegExp('(?:[^\\n]+?\\n){0,' + (line - 2) + '}[^<]*<script>([\\d\\D]*?)<\\/script>[\\d\\D]*', 'i');
inlineScriptSource = pageSource.replace(inlineScriptSourceRegExp, '$1').trim();
}
for (var i = 0; i < scripts.length; i++) {
// If ready state is interactive, return the script tag
if (scripts[i].readyState === 'interactive') {
return scripts[i];
}
// If src matches, return the script tag
if (scripts[i].src === scriptLocation) {
return scripts[i];
}
// If inline source matches, return the script tag
if (
scriptLocation === currentLocation &&
scripts[i].innerHTML &&
scripts[i].innerHTML.trim() === inlineScriptSource
) {
return scripts[i];
}
}
// If no match, return null
return null;
}
};
return getCurrentScript
}));
/***/ }), /***/ }),
/***/ "c8ba": /***/ "c8ba":
@@ -668,49 +753,6 @@ try {
module.exports = g; module.exports = g;
/***/ }),
/***/ "f6fd":
/***/ (function(module, exports) {
// document.currentScript polyfill by Adam Miller
// MIT license
(function(document){
var currentScript = "currentScript",
scripts = document.getElementsByTagName('script'); // Live NodeList collection
// If browser needs currentScript polyfill, add get currentScript() to the document object
if (!(currentScript in document)) {
Object.defineProperty(document, currentScript, {
get: function(){
// IE 6-10 supports script readyState
// IE 10+ support stack trace
try { throw new Error(); }
catch (err) {
// Find the second match for the "at" string to get file src url from stack.
// Specifically works with the format of stack traces in IE.
var i, res = ((/.*at [^\(]*\((.*):.+:.+\)$/ig).exec(err.stack) || [false])[1];
// For all scripts on the page, if src matches or if ready state is interactive, return the script tag
for(i in scripts){
if(scripts[i].src == res || scripts[i].readyState == "interactive"){
return scripts[i];
}
}
// If no match, return null
return null;
}
}
});
}
})(document);
/***/ }), /***/ }),
/***/ "fb15": /***/ "fb15":
@@ -723,13 +765,20 @@ __webpack_require__.r(__webpack_exports__);
// This file is imported into lib/wc client bundles. // This file is imported into lib/wc client bundles.
if (typeof window !== 'undefined') { if (typeof window !== 'undefined') {
var currentScript = window.document.currentScript
if (true) { if (true) {
__webpack_require__("f6fd") var getCurrentScript = __webpack_require__("8875")
currentScript = getCurrentScript()
// for backward compatibility, because previously we directly included the polyfill
if (!('currentScript' in document)) {
Object.defineProperty(document, 'currentScript', { get: getCurrentScript })
}
} }
var setPublicPath_i var src = currentScript && currentScript.src.match(/(.+\/)[^/]+\.js(\?.*)?$/)
if ((setPublicPath_i = window.document.currentScript) && (setPublicPath_i = setPublicPath_i.src.match(/(.+\/)[^/]+\.js(\?.*)?$/))) { if (src) {
__webpack_require__.p = setPublicPath_i[1] // eslint-disable-line __webpack_require__.p = src[1] // eslint-disable-line
} }
} }
@@ -1088,20 +1137,29 @@ const validMention = _regexSupplant(
{ validMentionPrecedingChars, atSigns }, { validMentionPrecedingChars, atSigns },
'g' 'g'
) )
const validDotMention = _regexSupplant(
'(#{validMentionPrecedingChars})' + // $1: Preceding character
'(#{atSigns})' + // $2: At mark
'([a-zA-Z0-9_\.]{1,20})', // $3: Screen name
// '(/[a-zA-Z][a-zA-Z0-9_-]{0,24})?', // $4: List (optional)
{ validMentionPrecedingChars, atSigns },
'g'
)
// CONCATENATED MODULE: ./src/utils/extractMentions.js // CONCATENATED MODULE: ./src/utils/extractMentions.js
// Extracts mentions from text. // Extracts mentions from text.
/* harmony default export */ var extractMentions = (function (text) { /* harmony default export */ var extractMentions = (function (text, options) {
if (!text || !text.match(atSigns)) { if (!text || !text.match(atSigns)) {
return [] return []
} }
const mentions = [] const mentions = []
const mentionRegex = options.mentionsWithDots ? validDotMention : validMention
text.replace(validMention, function (match, before, atSign, mentionText, offset, chunk) { text.replace(mentionRegex, function (match, before, atSign, mentionText, offset, chunk) {
const after = chunk.slice(offset + match.length) const after = chunk.slice(offset + match.length)
if (!after.match(endMentionMatch)) { if (!after.match(endMentionMatch)) {
const startPosition = offset + before.length const startPosition = offset + before.length
@@ -1291,7 +1349,7 @@ const extractUrlsWithIndices = function (text, options = DEFAULT_PROTOCOL_OPTION
/* harmony default export */ var extract = (function (text, options) { /* harmony default export */ var extract = (function (text, options) {
const entities = extractUrls(text, options) const entities = extractUrls(text, options)
.concat(extractMentions(text)) .concat(extractMentions(text, options))
.concat(extractHashtags(text)) .concat(extractHashtags(text))
if (entities.length === 0) { if (entities.length === 0) {
@@ -1356,7 +1414,8 @@ const OPTIONS_NOT_ATTRIBUTES = {
invisibleTagAttrs: true, invisibleTagAttrs: true,
linkAttributeBlock: true, linkAttributeBlock: true,
htmlEscapeNonEntities: true, htmlEscapeNonEntities: true,
extractUrlsWithoutProtocol: true extractUrlsWithoutProtocol: true,
mentionsWithDots: true
} }
/* harmony default export */ var extractHtmlAttrs = (function (options) { /* harmony default export */ var extractHtmlAttrs = (function (options) {
@@ -1606,7 +1665,8 @@ function _insertTag (text, classes = '') {
const defaultOptions = { const defaultOptions = {
targetBlank: true, targetBlank: true,
extractUrlsWithoutProtocol: true extractUrlsWithoutProtocol: true,
mentionsWithDots: false
} }
function utils_link (text, options = defaultOptions) { function utils_link (text, options = defaultOptions) {
@@ -1668,13 +1728,17 @@ function src_autoLink (text, options) {
return utils_link(text, options) return utils_link(text, options)
} }
/* harmony default export */ var src = ({ /* harmony default export */ var src_0 = ({
name: 'VueHighlights', name: 'VueHighlights',
props: { props: {
extractUrlsWithoutProtocol: { extractUrlsWithoutProtocol: {
type: Boolean, type: Boolean,
default: true default: true
}, },
mentionsWithDots: {
type: Boolean,
default: false
},
caretColor: { caretColor: {
type: String, type: String,
default: '#ccc' default: '#ccc'
@@ -1697,7 +1761,8 @@ function src_autoLink (text, options) {
}, },
computedBody () { computedBody () {
return highlight(this.body, { return highlight(this.body, {
extractUrlsWithoutProtocol: this.extractUrlsWithoutProtocol extractUrlsWithoutProtocol: this.extractUrlsWithoutProtocol,
mentionsWithDots: this.mentionsWithDots
}) })
} }
}, },
@@ -1810,7 +1875,7 @@ function src_autoLink (text, options) {
/* concated harmony reexport autoLink */__webpack_require__.d(__webpack_exports__, "autoLink", function() { return src_autoLink; }); /* concated harmony reexport autoLink */__webpack_require__.d(__webpack_exports__, "autoLink", function() { return src_autoLink; });
/* harmony default export */ var entry_lib = __webpack_exports__["default"] = (src); /* harmony default export */ var entry_lib = __webpack_exports__["default"] = (src_0);

File diff suppressed because one or more lines are too long

View File

@@ -650,6 +650,91 @@ module.exports = function(module) {
}; };
/***/ }),
/***/ "8875":
/***/ (function(module, exports, __webpack_require__) {
var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;// addapted from the document.currentScript polyfill by Adam Miller
// MIT license
// source: https://github.com/amiller-gh/currentScript-polyfill
// added support for Firefox https://bugzilla.mozilla.org/show_bug.cgi?id=1620505
(function (root, factory) {
if (true) {
!(__WEBPACK_AMD_DEFINE_ARRAY__ = [], __WEBPACK_AMD_DEFINE_FACTORY__ = (factory),
__WEBPACK_AMD_DEFINE_RESULT__ = (typeof __WEBPACK_AMD_DEFINE_FACTORY__ === 'function' ?
(__WEBPACK_AMD_DEFINE_FACTORY__.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__)) : __WEBPACK_AMD_DEFINE_FACTORY__),
__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
} else {}
}(typeof self !== 'undefined' ? self : this, function () {
function getCurrentScript () {
var descriptor = Object.getOwnPropertyDescriptor(document, 'currentScript')
// for chrome
if (!descriptor && 'currentScript' in document && document.currentScript) {
return document.currentScript
}
// for other browsers with native support for currentScript
if (descriptor && descriptor.get !== getCurrentScript && document.currentScript) {
return document.currentScript
}
// IE 8-10 support script readyState
// IE 11+ & Firefox support stack trace
try {
throw new Error();
}
catch (err) {
// Find the second match for the "at" string to get file src url from stack.
var ieStackRegExp = /.*at [^(]*\((.*):(.+):(.+)\)$/ig,
ffStackRegExp = /@([^@]*):(\d+):(\d+)\s*$/ig,
stackDetails = ieStackRegExp.exec(err.stack) || ffStackRegExp.exec(err.stack),
scriptLocation = (stackDetails && stackDetails[1]) || false,
line = (stackDetails && stackDetails[2]) || false,
currentLocation = document.location.href.replace(document.location.hash, ''),
pageSource,
inlineScriptSourceRegExp,
inlineScriptSource,
scripts = document.getElementsByTagName('script'); // Live NodeList collection
if (scriptLocation === currentLocation) {
pageSource = document.documentElement.outerHTML;
inlineScriptSourceRegExp = new RegExp('(?:[^\\n]+?\\n){0,' + (line - 2) + '}[^<]*<script>([\\d\\D]*?)<\\/script>[\\d\\D]*', 'i');
inlineScriptSource = pageSource.replace(inlineScriptSourceRegExp, '$1').trim();
}
for (var i = 0; i < scripts.length; i++) {
// If ready state is interactive, return the script tag
if (scripts[i].readyState === 'interactive') {
return scripts[i];
}
// If src matches, return the script tag
if (scripts[i].src === scriptLocation) {
return scripts[i];
}
// If inline source matches, return the script tag
if (
scriptLocation === currentLocation &&
scripts[i].innerHTML &&
scripts[i].innerHTML.trim() === inlineScriptSource
) {
return scripts[i];
}
}
// If no match, return null
return null;
}
};
return getCurrentScript
}));
/***/ }), /***/ }),
/***/ "c8ba": /***/ "c8ba":
@@ -677,49 +762,6 @@ try {
module.exports = g; module.exports = g;
/***/ }),
/***/ "f6fd":
/***/ (function(module, exports) {
// document.currentScript polyfill by Adam Miller
// MIT license
(function(document){
var currentScript = "currentScript",
scripts = document.getElementsByTagName('script'); // Live NodeList collection
// If browser needs currentScript polyfill, add get currentScript() to the document object
if (!(currentScript in document)) {
Object.defineProperty(document, currentScript, {
get: function(){
// IE 6-10 supports script readyState
// IE 10+ support stack trace
try { throw new Error(); }
catch (err) {
// Find the second match for the "at" string to get file src url from stack.
// Specifically works with the format of stack traces in IE.
var i, res = ((/.*at [^\(]*\((.*):.+:.+\)$/ig).exec(err.stack) || [false])[1];
// For all scripts on the page, if src matches or if ready state is interactive, return the script tag
for(i in scripts){
if(scripts[i].src == res || scripts[i].readyState == "interactive"){
return scripts[i];
}
}
// If no match, return null
return null;
}
}
});
}
})(document);
/***/ }), /***/ }),
/***/ "fb15": /***/ "fb15":
@@ -732,13 +774,20 @@ __webpack_require__.r(__webpack_exports__);
// This file is imported into lib/wc client bundles. // This file is imported into lib/wc client bundles.
if (typeof window !== 'undefined') { if (typeof window !== 'undefined') {
var currentScript = window.document.currentScript
if (true) { if (true) {
__webpack_require__("f6fd") var getCurrentScript = __webpack_require__("8875")
currentScript = getCurrentScript()
// for backward compatibility, because previously we directly included the polyfill
if (!('currentScript' in document)) {
Object.defineProperty(document, 'currentScript', { get: getCurrentScript })
}
} }
var setPublicPath_i var src = currentScript && currentScript.src.match(/(.+\/)[^/]+\.js(\?.*)?$/)
if ((setPublicPath_i = window.document.currentScript) && (setPublicPath_i = setPublicPath_i.src.match(/(.+\/)[^/]+\.js(\?.*)?$/))) { if (src) {
__webpack_require__.p = setPublicPath_i[1] // eslint-disable-line __webpack_require__.p = src[1] // eslint-disable-line
} }
} }
@@ -1097,20 +1146,29 @@ const validMention = _regexSupplant(
{ validMentionPrecedingChars, atSigns }, { validMentionPrecedingChars, atSigns },
'g' 'g'
) )
const validDotMention = _regexSupplant(
'(#{validMentionPrecedingChars})' + // $1: Preceding character
'(#{atSigns})' + // $2: At mark
'([a-zA-Z0-9_\.]{1,20})', // $3: Screen name
// '(/[a-zA-Z][a-zA-Z0-9_-]{0,24})?', // $4: List (optional)
{ validMentionPrecedingChars, atSigns },
'g'
)
// CONCATENATED MODULE: ./src/utils/extractMentions.js // CONCATENATED MODULE: ./src/utils/extractMentions.js
// Extracts mentions from text. // Extracts mentions from text.
/* harmony default export */ var extractMentions = (function (text) { /* harmony default export */ var extractMentions = (function (text, options) {
if (!text || !text.match(atSigns)) { if (!text || !text.match(atSigns)) {
return [] return []
} }
const mentions = [] const mentions = []
const mentionRegex = options.mentionsWithDots ? validDotMention : validMention
text.replace(validMention, function (match, before, atSign, mentionText, offset, chunk) { text.replace(mentionRegex, function (match, before, atSign, mentionText, offset, chunk) {
const after = chunk.slice(offset + match.length) const after = chunk.slice(offset + match.length)
if (!after.match(endMentionMatch)) { if (!after.match(endMentionMatch)) {
const startPosition = offset + before.length const startPosition = offset + before.length
@@ -1300,7 +1358,7 @@ const extractUrlsWithIndices = function (text, options = DEFAULT_PROTOCOL_OPTION
/* harmony default export */ var extract = (function (text, options) { /* harmony default export */ var extract = (function (text, options) {
const entities = extractUrls(text, options) const entities = extractUrls(text, options)
.concat(extractMentions(text)) .concat(extractMentions(text, options))
.concat(extractHashtags(text)) .concat(extractHashtags(text))
if (entities.length === 0) { if (entities.length === 0) {
@@ -1365,7 +1423,8 @@ const OPTIONS_NOT_ATTRIBUTES = {
invisibleTagAttrs: true, invisibleTagAttrs: true,
linkAttributeBlock: true, linkAttributeBlock: true,
htmlEscapeNonEntities: true, htmlEscapeNonEntities: true,
extractUrlsWithoutProtocol: true extractUrlsWithoutProtocol: true,
mentionsWithDots: true
} }
/* harmony default export */ var extractHtmlAttrs = (function (options) { /* harmony default export */ var extractHtmlAttrs = (function (options) {
@@ -1615,7 +1674,8 @@ function _insertTag (text, classes = '') {
const defaultOptions = { const defaultOptions = {
targetBlank: true, targetBlank: true,
extractUrlsWithoutProtocol: true extractUrlsWithoutProtocol: true,
mentionsWithDots: false
} }
function utils_link (text, options = defaultOptions) { function utils_link (text, options = defaultOptions) {
@@ -1677,13 +1737,17 @@ function src_autoLink (text, options) {
return utils_link(text, options) return utils_link(text, options)
} }
/* harmony default export */ var src = ({ /* harmony default export */ var src_0 = ({
name: 'VueHighlights', name: 'VueHighlights',
props: { props: {
extractUrlsWithoutProtocol: { extractUrlsWithoutProtocol: {
type: Boolean, type: Boolean,
default: true default: true
}, },
mentionsWithDots: {
type: Boolean,
default: false
},
caretColor: { caretColor: {
type: String, type: String,
default: '#ccc' default: '#ccc'
@@ -1706,7 +1770,8 @@ function src_autoLink (text, options) {
}, },
computedBody () { computedBody () {
return highlight(this.body, { return highlight(this.body, {
extractUrlsWithoutProtocol: this.extractUrlsWithoutProtocol extractUrlsWithoutProtocol: this.extractUrlsWithoutProtocol,
mentionsWithDots: this.mentionsWithDots
}) })
} }
}, },
@@ -1819,7 +1884,7 @@ function src_autoLink (text, options) {
/* concated harmony reexport autoLink */__webpack_require__.d(__webpack_exports__, "autoLink", function() { return src_autoLink; }); /* concated harmony reexport autoLink */__webpack_require__.d(__webpack_exports__, "autoLink", function() { return src_autoLink; });
/* harmony default export */ var entry_lib = __webpack_exports__["default"] = (src); /* harmony default export */ var entry_lib = __webpack_exports__["default"] = (src_0);

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -21,6 +21,7 @@
:placeholder="placeholder" :placeholder="placeholder"
:caretColor="caretColor" :caretColor="caretColor"
:extractUrlsWithoutProtocol="options.extractUrlsWithoutProtocol" :extractUrlsWithoutProtocol="options.extractUrlsWithoutProtocol"
:mentionsWithDots="options.mentionsWithDots"
/> />
</div> </div>
@@ -28,14 +29,18 @@
<div id="options" class="content-container"> <div id="options" class="content-container">
<h4>Options (props)</h4> <h4>Options (props)</h4>
<div class="flex center"> <div class="flex center">
<label for="ep" class="mr-lg cursor-pointer"> <label for="ep" class="cursor-pointer">
<input id="ep" type="checkbox" v-model="options.extractUrlsWithoutProtocol"> <input id="ep" type="checkbox" v-model="options.extractUrlsWithoutProtocol">
extractUrlsWithoutProtocol extractUrlsWithoutProtocol
</label> </label>
<label for="tb" class="cursor-pointer"> <label for="tb" class="mx-lg cursor-pointer">
<input id="tb" type="checkbox" v-model="options.targetBlank"> <input id="tb" type="checkbox" v-model="options.targetBlank">
targetBlank targetBlank
</label> </label>
<label for="md" class="cursor-pointer">
<input id="md" type="checkbox" v-model="options.mentionsWithDots">
mentionsWithDots
</label>
</div> </div>
<div class="flex center mt-sm text-left relative"> <div class="flex center mt-sm text-left relative">
@@ -130,6 +135,7 @@ export default {
options: { options: {
targetBlank: true, targetBlank: true,
extractUrlsWithoutProtocol: true, extractUrlsWithoutProtocol: true,
mentionsWithDots: false,
usernameClass: 'highlights username', usernameClass: 'highlights username',
usernameUrlBase: '#/', usernameUrlBase: '#/',
hashtagClass: 'highlights hashtag', hashtagClass: 'highlights hashtag',

44
package-lock.json generated
View File

@@ -6652,13 +6652,13 @@
} }
}, },
"node_modules/cssnano": { "node_modules/cssnano": {
"version": "4.1.10", "version": "4.1.11",
"resolved": "https://registry.npmjs.org/cssnano/-/cssnano-4.1.10.tgz", "resolved": "https://registry.npmjs.org/cssnano/-/cssnano-4.1.11.tgz",
"integrity": "sha512-5wny+F6H4/8RgNlaqab4ktc3e0/blKutmq8yNlBFXA//nSFFAqAngjNVRzUvCgYROULmZZUoosL/KSoZo5aUaQ==", "integrity": "sha512-6gZm2htn7xIPJOHY824ERgj8cNPgPxyCSnkXc4v7YvNW+TdVfzgngHcEhy/8D11kUWRUMbke+tC+AUcUsnMz2g==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"cosmiconfig": "^5.0.0", "cosmiconfig": "^5.0.0",
"cssnano-preset-default": "^4.0.7", "cssnano-preset-default": "^4.0.8",
"is-resolvable": "^1.0.0", "is-resolvable": "^1.0.0",
"postcss": "^7.0.0" "postcss": "^7.0.0"
}, },
@@ -6667,9 +6667,9 @@
} }
}, },
"node_modules/cssnano-preset-default": { "node_modules/cssnano-preset-default": {
"version": "4.0.7", "version": "4.0.8",
"resolved": "https://registry.npmjs.org/cssnano-preset-default/-/cssnano-preset-default-4.0.7.tgz", "resolved": "https://registry.npmjs.org/cssnano-preset-default/-/cssnano-preset-default-4.0.8.tgz",
"integrity": "sha512-x0YHHx2h6p0fCl1zY9L9roD7rnlltugGu7zXSKQx6k2rYw0Hi3IqxcoAGF7u9Q5w1nt7vK0ulxV8Lo+EvllGsA==", "integrity": "sha512-LdAyHuq+VRyeVREFmuxUZR1TXjQm8QQU/ktoo/x7bz+SdOge1YKc5eMN6pRW7YWBmyq59CqYba1dJ5cUukEjLQ==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"css-declaration-sorter": "^4.0.1", "css-declaration-sorter": "^4.0.1",
@@ -6700,7 +6700,7 @@
"postcss-ordered-values": "^4.1.2", "postcss-ordered-values": "^4.1.2",
"postcss-reduce-initial": "^4.0.3", "postcss-reduce-initial": "^4.0.3",
"postcss-reduce-transforms": "^4.0.2", "postcss-reduce-transforms": "^4.0.2",
"postcss-svgo": "^4.0.2", "postcss-svgo": "^4.0.3",
"postcss-unique-selectors": "^4.0.1" "postcss-unique-selectors": "^4.0.1"
}, },
"engines": { "engines": {
@@ -18760,9 +18760,9 @@
} }
}, },
"node_modules/ws": { "node_modules/ws": {
"version": "5.2.2", "version": "5.2.3",
"resolved": "https://registry.npmjs.org/ws/-/ws-5.2.2.tgz", "resolved": "https://registry.npmjs.org/ws/-/ws-5.2.3.tgz",
"integrity": "sha512-jaHFD6PFv6UgoIVda6qZllptQsMlDEJkTQcybzzXDYM1XO9Y8em691FGMPmM46WGyLU4z9KMgQN+qrux/nhlHA==", "integrity": "sha512-jZArVERrMsKUatIdnLzqvcfydI85dvd/Fp1u/VOpfdDWQ4c9qWXe+VIeAbQ5FrDwciAkr+lzofXLz3Kuf26AOA==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"async-limiter": "~1.0.0" "async-limiter": "~1.0.0"
@@ -24148,21 +24148,21 @@
"dev": true "dev": true
}, },
"cssnano": { "cssnano": {
"version": "4.1.10", "version": "4.1.11",
"resolved": "https://registry.npmjs.org/cssnano/-/cssnano-4.1.10.tgz", "resolved": "https://registry.npmjs.org/cssnano/-/cssnano-4.1.11.tgz",
"integrity": "sha512-5wny+F6H4/8RgNlaqab4ktc3e0/blKutmq8yNlBFXA//nSFFAqAngjNVRzUvCgYROULmZZUoosL/KSoZo5aUaQ==", "integrity": "sha512-6gZm2htn7xIPJOHY824ERgj8cNPgPxyCSnkXc4v7YvNW+TdVfzgngHcEhy/8D11kUWRUMbke+tC+AUcUsnMz2g==",
"dev": true, "dev": true,
"requires": { "requires": {
"cosmiconfig": "^5.0.0", "cosmiconfig": "^5.0.0",
"cssnano-preset-default": "^4.0.7", "cssnano-preset-default": "^4.0.8",
"is-resolvable": "^1.0.0", "is-resolvable": "^1.0.0",
"postcss": "^7.0.0" "postcss": "^7.0.0"
} }
}, },
"cssnano-preset-default": { "cssnano-preset-default": {
"version": "4.0.7", "version": "4.0.8",
"resolved": "https://registry.npmjs.org/cssnano-preset-default/-/cssnano-preset-default-4.0.7.tgz", "resolved": "https://registry.npmjs.org/cssnano-preset-default/-/cssnano-preset-default-4.0.8.tgz",
"integrity": "sha512-x0YHHx2h6p0fCl1zY9L9roD7rnlltugGu7zXSKQx6k2rYw0Hi3IqxcoAGF7u9Q5w1nt7vK0ulxV8Lo+EvllGsA==", "integrity": "sha512-LdAyHuq+VRyeVREFmuxUZR1TXjQm8QQU/ktoo/x7bz+SdOge1YKc5eMN6pRW7YWBmyq59CqYba1dJ5cUukEjLQ==",
"dev": true, "dev": true,
"requires": { "requires": {
"css-declaration-sorter": "^4.0.1", "css-declaration-sorter": "^4.0.1",
@@ -24193,7 +24193,7 @@
"postcss-ordered-values": "^4.1.2", "postcss-ordered-values": "^4.1.2",
"postcss-reduce-initial": "^4.0.3", "postcss-reduce-initial": "^4.0.3",
"postcss-reduce-transforms": "^4.0.2", "postcss-reduce-transforms": "^4.0.2",
"postcss-svgo": "^4.0.2", "postcss-svgo": "^4.0.3",
"postcss-unique-selectors": "^4.0.1" "postcss-unique-selectors": "^4.0.1"
} }
}, },
@@ -33945,9 +33945,9 @@
} }
}, },
"ws": { "ws": {
"version": "5.2.2", "version": "5.2.3",
"resolved": "https://registry.npmjs.org/ws/-/ws-5.2.2.tgz", "resolved": "https://registry.npmjs.org/ws/-/ws-5.2.3.tgz",
"integrity": "sha512-jaHFD6PFv6UgoIVda6qZllptQsMlDEJkTQcybzzXDYM1XO9Y8em691FGMPmM46WGyLU4z9KMgQN+qrux/nhlHA==", "integrity": "sha512-jZArVERrMsKUatIdnLzqvcfydI85dvd/Fp1u/VOpfdDWQ4c9qWXe+VIeAbQ5FrDwciAkr+lzofXLz3Kuf26AOA==",
"dev": true, "dev": true,
"requires": { "requires": {
"async-limiter": "~1.0.0" "async-limiter": "~1.0.0"

View File

@@ -15,6 +15,10 @@ export default {
type: Boolean, type: Boolean,
default: true default: true
}, },
mentionsWithDots: {
type: Boolean,
default: false
},
caretColor: { caretColor: {
type: String, type: String,
default: '#ccc' default: '#ccc'
@@ -37,7 +41,8 @@ export default {
}, },
computedBody () { computedBody () {
return highlight(this.body, { return highlight(this.body, {
extractUrlsWithoutProtocol: this.extractUrlsWithoutProtocol extractUrlsWithoutProtocol: this.extractUrlsWithoutProtocol,
mentionsWithDots: this.mentionsWithDots
}) })
} }
}, },

View File

@@ -8,7 +8,7 @@ import removeOverlappingEntities from './removeOverlappingEntities'
export default function (text, options) { export default function (text, options) {
const entities = extractUrls(text, options) const entities = extractUrls(text, options)
.concat(extractMentions(text)) .concat(extractMentions(text, options))
.concat(extractHashtags(text)) .concat(extractHashtags(text))
if (entities.length === 0) { if (entities.length === 0) {

View File

@@ -17,7 +17,8 @@ const OPTIONS_NOT_ATTRIBUTES = {
invisibleTagAttrs: true, invisibleTagAttrs: true,
linkAttributeBlock: true, linkAttributeBlock: true,
htmlEscapeNonEntities: true, htmlEscapeNonEntities: true,
extractUrlsWithoutProtocol: true extractUrlsWithoutProtocol: true,
mentionsWithDots: true
} }
export default function (options) { export default function (options) {

View File

@@ -1,15 +1,16 @@
// Extracts mentions from text. // Extracts mentions from text.
import { atSigns, endMentionMatch, validMention } from './regex' import { atSigns, endMentionMatch, validMention, validDotMention } from './regex'
export default function (text) { export default function (text, options) {
if (!text || !text.match(atSigns)) { if (!text || !text.match(atSigns)) {
return [] return []
} }
const mentions = [] const mentions = []
const mentionRegex = options.mentionsWithDots ? validDotMention : validMention
text.replace(validMention, function (match, before, atSign, mentionText, offset, chunk) { text.replace(mentionRegex, function (match, before, atSign, mentionText, offset, chunk) {
const after = chunk.slice(offset + match.length) const after = chunk.slice(offset + match.length)
if (!after.match(endMentionMatch)) { if (!after.match(endMentionMatch)) {
const startPosition = offset + before.length const startPosition = offset + before.length

View File

@@ -4,7 +4,8 @@ import autoHighlight from './autoHighlight'
const defaultOptions = { const defaultOptions = {
targetBlank: true, targetBlank: true,
extractUrlsWithoutProtocol: true extractUrlsWithoutProtocol: true,
mentionsWithDots: false
} }
export function link (text, options = defaultOptions) { export function link (text, options = defaultOptions) {

View File

@@ -194,3 +194,11 @@ export const validMention = regexSupplant(
{ validMentionPrecedingChars, atSigns }, { validMentionPrecedingChars, atSigns },
'g' 'g'
) )
export const validDotMention = regexSupplant(
'(#{validMentionPrecedingChars})' + // $1: Preceding character
'(#{atSigns})' + // $2: At mark
'([a-zA-Z0-9_\.]{1,20})', // $3: Screen name
// '(/[a-zA-Z][a-zA-Z0-9_-]{0,24})?', // $4: List (optional)
{ validMentionPrecedingChars, atSigns },
'g'
)