markdown-it-diaspora-mention
Version:
diaspora* mentions for markdown-it markdown parser.
581 lines (538 loc) • 22.6 kB
JavaScript
/*! markdown-it-diaspora-mention 1.2.0 https://github.com/diaspora/markdown-it-diaspora-mention @license MIT */(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.markdownitDiasporaMention = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
require('../../modules/es6.array.find');
module.exports = require('../../modules/_core').Array.find;
},{"../../modules/_core":9,"../../modules/es6.array.find":33}],2:[function(require,module,exports){
module.exports = function(it){
if(typeof it != 'function')throw TypeError(it + ' is not a function!');
return it;
};
},{}],3:[function(require,module,exports){
// 22.1.3.31 Array.prototype[@@unscopables]
var UNSCOPABLES = require('./_wks')('unscopables')
, ArrayProto = Array.prototype;
if(ArrayProto[UNSCOPABLES] == undefined)require('./_hide')(ArrayProto, UNSCOPABLES, {});
module.exports = function(key){
ArrayProto[UNSCOPABLES][key] = true;
};
},{"./_hide":18,"./_wks":32}],4:[function(require,module,exports){
var isObject = require('./_is-object');
module.exports = function(it){
if(!isObject(it))throw TypeError(it + ' is not an object!');
return it;
};
},{"./_is-object":22}],5:[function(require,module,exports){
// 0 -> Array#forEach
// 1 -> Array#map
// 2 -> Array#filter
// 3 -> Array#some
// 4 -> Array#every
// 5 -> Array#find
// 6 -> Array#findIndex
var ctx = require('./_ctx')
, IObject = require('./_iobject')
, toObject = require('./_to-object')
, toLength = require('./_to-length')
, asc = require('./_array-species-create');
module.exports = function(TYPE, $create){
var IS_MAP = TYPE == 1
, IS_FILTER = TYPE == 2
, IS_SOME = TYPE == 3
, IS_EVERY = TYPE == 4
, IS_FIND_INDEX = TYPE == 6
, NO_HOLES = TYPE == 5 || IS_FIND_INDEX
, create = $create || asc;
return function($this, callbackfn, that){
var O = toObject($this)
, self = IObject(O)
, f = ctx(callbackfn, that, 3)
, length = toLength(self.length)
, index = 0
, result = IS_MAP ? create($this, length) : IS_FILTER ? create($this, 0) : undefined
, val, res;
for(;length > index; index++)if(NO_HOLES || index in self){
val = self[index];
res = f(val, index, O);
if(TYPE){
if(IS_MAP)result[index] = res; // map
else if(res)switch(TYPE){
case 3: return true; // some
case 5: return val; // find
case 6: return index; // findIndex
case 2: result.push(val); // filter
} else if(IS_EVERY)return false; // every
}
}
return IS_FIND_INDEX ? -1 : IS_SOME || IS_EVERY ? IS_EVERY : result;
};
};
},{"./_array-species-create":7,"./_ctx":10,"./_iobject":20,"./_to-length":28,"./_to-object":29}],6:[function(require,module,exports){
var isObject = require('./_is-object')
, isArray = require('./_is-array')
, SPECIES = require('./_wks')('species');
module.exports = function(original){
var C;
if(isArray(original)){
C = original.constructor;
// cross-realm fallback
if(typeof C == 'function' && (C === Array || isArray(C.prototype)))C = undefined;
if(isObject(C)){
C = C[SPECIES];
if(C === null)C = undefined;
}
} return C === undefined ? Array : C;
};
},{"./_is-array":21,"./_is-object":22,"./_wks":32}],7:[function(require,module,exports){
// 9.4.2.3 ArraySpeciesCreate(originalArray, length)
var speciesConstructor = require('./_array-species-constructor');
module.exports = function(original, length){
return new (speciesConstructor(original))(length);
};
},{"./_array-species-constructor":6}],8:[function(require,module,exports){
var toString = {}.toString;
module.exports = function(it){
return toString.call(it).slice(8, -1);
};
},{}],9:[function(require,module,exports){
var core = module.exports = {version: '2.4.0'};
if(typeof __e == 'number')__e = core; // eslint-disable-line no-undef
},{}],10:[function(require,module,exports){
// optional / simple context binding
var aFunction = require('./_a-function');
module.exports = function(fn, that, length){
aFunction(fn);
if(that === undefined)return fn;
switch(length){
case 1: return function(a){
return fn.call(that, a);
};
case 2: return function(a, b){
return fn.call(that, a, b);
};
case 3: return function(a, b, c){
return fn.call(that, a, b, c);
};
}
return function(/* ...args */){
return fn.apply(that, arguments);
};
};
},{"./_a-function":2}],11:[function(require,module,exports){
// 7.2.1 RequireObjectCoercible(argument)
module.exports = function(it){
if(it == undefined)throw TypeError("Can't call method on " + it);
return it;
};
},{}],12:[function(require,module,exports){
// Thank's IE8 for his funny defineProperty
module.exports = !require('./_fails')(function(){
return Object.defineProperty({}, 'a', {get: function(){ return 7; }}).a != 7;
});
},{"./_fails":15}],13:[function(require,module,exports){
var isObject = require('./_is-object')
, document = require('./_global').document
// in old IE typeof document.createElement is 'object'
, is = isObject(document) && isObject(document.createElement);
module.exports = function(it){
return is ? document.createElement(it) : {};
};
},{"./_global":16,"./_is-object":22}],14:[function(require,module,exports){
var global = require('./_global')
, core = require('./_core')
, hide = require('./_hide')
, redefine = require('./_redefine')
, ctx = require('./_ctx')
, PROTOTYPE = 'prototype';
var $export = function(type, name, source){
var IS_FORCED = type & $export.F
, IS_GLOBAL = type & $export.G
, IS_STATIC = type & $export.S
, IS_PROTO = type & $export.P
, IS_BIND = type & $export.B
, target = IS_GLOBAL ? global : IS_STATIC ? global[name] || (global[name] = {}) : (global[name] || {})[PROTOTYPE]
, exports = IS_GLOBAL ? core : core[name] || (core[name] = {})
, expProto = exports[PROTOTYPE] || (exports[PROTOTYPE] = {})
, key, own, out, exp;
if(IS_GLOBAL)source = name;
for(key in source){
// contains in native
own = !IS_FORCED && target && target[key] !== undefined;
// export native or passed
out = (own ? target : source)[key];
// bind timers to global for call from export context
exp = IS_BIND && own ? ctx(out, global) : IS_PROTO && typeof out == 'function' ? ctx(Function.call, out) : out;
// extend global
if(target)redefine(target, key, out, type & $export.U);
// export
if(exports[key] != out)hide(exports, key, exp);
if(IS_PROTO && expProto[key] != out)expProto[key] = out;
}
};
global.core = core;
// type bitmap
$export.F = 1; // forced
$export.G = 2; // global
$export.S = 4; // static
$export.P = 8; // proto
$export.B = 16; // bind
$export.W = 32; // wrap
$export.U = 64; // safe
$export.R = 128; // real proto method for `library`
module.exports = $export;
},{"./_core":9,"./_ctx":10,"./_global":16,"./_hide":18,"./_redefine":25}],15:[function(require,module,exports){
module.exports = function(exec){
try {
return !!exec();
} catch(e){
return true;
}
};
},{}],16:[function(require,module,exports){
// https://github.com/zloirock/core-js/issues/86#issuecomment-115759028
var global = module.exports = typeof window != 'undefined' && window.Math == Math
? window : typeof self != 'undefined' && self.Math == Math ? self : Function('return this')();
if(typeof __g == 'number')__g = global; // eslint-disable-line no-undef
},{}],17:[function(require,module,exports){
var hasOwnProperty = {}.hasOwnProperty;
module.exports = function(it, key){
return hasOwnProperty.call(it, key);
};
},{}],18:[function(require,module,exports){
var dP = require('./_object-dp')
, createDesc = require('./_property-desc');
module.exports = require('./_descriptors') ? function(object, key, value){
return dP.f(object, key, createDesc(1, value));
} : function(object, key, value){
object[key] = value;
return object;
};
},{"./_descriptors":12,"./_object-dp":23,"./_property-desc":24}],19:[function(require,module,exports){
module.exports = !require('./_descriptors') && !require('./_fails')(function(){
return Object.defineProperty(require('./_dom-create')('div'), 'a', {get: function(){ return 7; }}).a != 7;
});
},{"./_descriptors":12,"./_dom-create":13,"./_fails":15}],20:[function(require,module,exports){
// fallback for non-array-like ES3 and non-enumerable old V8 strings
var cof = require('./_cof');
module.exports = Object('z').propertyIsEnumerable(0) ? Object : function(it){
return cof(it) == 'String' ? it.split('') : Object(it);
};
},{"./_cof":8}],21:[function(require,module,exports){
// 7.2.2 IsArray(argument)
var cof = require('./_cof');
module.exports = Array.isArray || function isArray(arg){
return cof(arg) == 'Array';
};
},{"./_cof":8}],22:[function(require,module,exports){
module.exports = function(it){
return typeof it === 'object' ? it !== null : typeof it === 'function';
};
},{}],23:[function(require,module,exports){
var anObject = require('./_an-object')
, IE8_DOM_DEFINE = require('./_ie8-dom-define')
, toPrimitive = require('./_to-primitive')
, dP = Object.defineProperty;
exports.f = require('./_descriptors') ? Object.defineProperty : function defineProperty(O, P, Attributes){
anObject(O);
P = toPrimitive(P, true);
anObject(Attributes);
if(IE8_DOM_DEFINE)try {
return dP(O, P, Attributes);
} catch(e){ /* empty */ }
if('get' in Attributes || 'set' in Attributes)throw TypeError('Accessors not supported!');
if('value' in Attributes)O[P] = Attributes.value;
return O;
};
},{"./_an-object":4,"./_descriptors":12,"./_ie8-dom-define":19,"./_to-primitive":30}],24:[function(require,module,exports){
module.exports = function(bitmap, value){
return {
enumerable : !(bitmap & 1),
configurable: !(bitmap & 2),
writable : !(bitmap & 4),
value : value
};
};
},{}],25:[function(require,module,exports){
var global = require('./_global')
, hide = require('./_hide')
, has = require('./_has')
, SRC = require('./_uid')('src')
, TO_STRING = 'toString'
, $toString = Function[TO_STRING]
, TPL = ('' + $toString).split(TO_STRING);
require('./_core').inspectSource = function(it){
return $toString.call(it);
};
(module.exports = function(O, key, val, safe){
var isFunction = typeof val == 'function';
if(isFunction)has(val, 'name') || hide(val, 'name', key);
if(O[key] === val)return;
if(isFunction)has(val, SRC) || hide(val, SRC, O[key] ? '' + O[key] : TPL.join(String(key)));
if(O === global){
O[key] = val;
} else {
if(!safe){
delete O[key];
hide(O, key, val);
} else {
if(O[key])O[key] = val;
else hide(O, key, val);
}
}
// add fake Function#toString for correct work wrapped methods / constructors with methods like LoDash isNative
})(Function.prototype, TO_STRING, function toString(){
return typeof this == 'function' && this[SRC] || $toString.call(this);
});
},{"./_core":9,"./_global":16,"./_has":17,"./_hide":18,"./_uid":31}],26:[function(require,module,exports){
var global = require('./_global')
, SHARED = '__core-js_shared__'
, store = global[SHARED] || (global[SHARED] = {});
module.exports = function(key){
return store[key] || (store[key] = {});
};
},{"./_global":16}],27:[function(require,module,exports){
// 7.1.4 ToInteger
var ceil = Math.ceil
, floor = Math.floor;
module.exports = function(it){
return isNaN(it = +it) ? 0 : (it > 0 ? floor : ceil)(it);
};
},{}],28:[function(require,module,exports){
// 7.1.15 ToLength
var toInteger = require('./_to-integer')
, min = Math.min;
module.exports = function(it){
return it > 0 ? min(toInteger(it), 0x1fffffffffffff) : 0; // pow(2, 53) - 1 == 9007199254740991
};
},{"./_to-integer":27}],29:[function(require,module,exports){
// 7.1.13 ToObject(argument)
var defined = require('./_defined');
module.exports = function(it){
return Object(defined(it));
};
},{"./_defined":11}],30:[function(require,module,exports){
// 7.1.1 ToPrimitive(input [, PreferredType])
var isObject = require('./_is-object');
// instead of the ES6 spec version, we didn't implement @@toPrimitive case
// and the second argument - flag - preferred type is a string
module.exports = function(it, S){
if(!isObject(it))return it;
var fn, val;
if(S && typeof (fn = it.toString) == 'function' && !isObject(val = fn.call(it)))return val;
if(typeof (fn = it.valueOf) == 'function' && !isObject(val = fn.call(it)))return val;
if(!S && typeof (fn = it.toString) == 'function' && !isObject(val = fn.call(it)))return val;
throw TypeError("Can't convert object to primitive value");
};
},{"./_is-object":22}],31:[function(require,module,exports){
var id = 0
, px = Math.random();
module.exports = function(key){
return 'Symbol('.concat(key === undefined ? '' : key, ')_', (++id + px).toString(36));
};
},{}],32:[function(require,module,exports){
var store = require('./_shared')('wks')
, uid = require('./_uid')
, Symbol = require('./_global').Symbol
, USE_SYMBOL = typeof Symbol == 'function';
var $exports = module.exports = function(name){
return store[name] || (store[name] =
USE_SYMBOL && Symbol[name] || (USE_SYMBOL ? Symbol : uid)('Symbol.' + name));
};
$exports.store = store;
},{"./_global":16,"./_shared":26,"./_uid":31}],33:[function(require,module,exports){
;
// 22.1.3.8 Array.prototype.find(predicate, thisArg = undefined)
var $export = require('./_export')
, $find = require('./_array-methods')(5)
, KEY = 'find'
, forced = true;
// Shouldn't skip holes
if(KEY in [])Array(1)[KEY](function(){ forced = false; });
$export($export.P + $export.F * forced, 'Array', {
find: function find(callbackfn/*, that = undefined */){
return $find(this, callbackfn, arguments.length > 1 ? arguments[1] : undefined);
}
});
require('./_add-to-unscopables')(KEY);
},{"./_add-to-unscopables":3,"./_array-methods":5,"./_export":14}],34:[function(require,module,exports){
;
var _slicedToArray = function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"]) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } }; }();
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
require("core-js/fn/array/find");
var mentionOpen = function mentionOpen(tokens, idx) {
return "<a href=\"" + tokens[idx].content + "\" class=\"" + tokens[idx].linkclass + "\">";
},
mentionClose = function mentionClose() {
return "</a>";
},
mentionText = function mentionText(tokens, idx) {
return tokens[idx].content;
},
linkOpenRegExp = /^<a[>\s]/i,
linkCloseRegExp = /^<\/a\s*>/i,
isLinkOpen = function isLinkOpen(str) {
return linkOpenRegExp.test(str);
},
isLinkClose = function isLinkClose(str) {
return linkCloseRegExp.test(str);
},
mentionRegExpPattern = "@\\{(?:([^}]+); )?([^\\} ]+)\\}",
mentionRegExp = new RegExp(mentionRegExpPattern),
mentionRegExpGlobal = new RegExp(mentionRegExpPattern, "g");
var MentionPlugin = function () {
function MentionPlugin(md) {
var _ref = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : { mentions: [], allowHovercards: false },
mentions = _ref.mentions,
allowHovercards = _ref.allowHovercards,
currentUserId = _ref.currentUserId;
_classCallCheck(this, MentionPlugin);
this.mentions = mentions;
this.allowHovercards = allowHovercards;
this.currentUserId = currentUserId;
this.escapeHtml = md.utils.escapeHtml;
md.core.ruler.after("inline", "mention", this.parseMentions.bind(this));
/* eslint-disable camelcase */
md.renderer.rules.mention_open = mentionOpen;
md.renderer.rules.mention_text = mentionText;
md.renderer.rules.mention_close = mentionClose;
/* eslint-enable camelcase */
}
_createClass(MentionPlugin, [{
key: "findPersonById",
value: function findPersonById(id) {
return this.mentions.find(function (m) {
return id === m.diaspora_id || id === m.handle;
});
}
}, {
key: "mentionLinkClass",
value: function mentionLinkClass(person) {
return this.allowHovercards && person.guid !== this.currentUserId ? "mention hovercardable" : "mention";
}
/*
* Skips content inside of markdown links (between link_open and link_close)
* Modifies this.inMarkdownLink and this.markdownLinkStartLevel to keep track of the current state
*/
}, {
key: "skipMarkdownLink",
value: function skipMarkdownLink(currentToken) {
if (this.inMarkdownLink) {
if (currentToken.level === this.markdownLinkStartLevel || currentToken.type === "link_close") {
this.inMarkdownLink = false;
}
return true;
}
if (currentToken.type === "link_open") {
this.markdownLinkStartLevel = currentToken.level;
this.inMarkdownLink = true;
return true;
}
return false;
}
/*
* Skips content inside of inline html links
* Modifies this.htmlLinkLevel to keep track of the current state
*/
}, {
key: "skipHtmlLink",
value: function skipHtmlLink(currentToken) {
if (currentToken.type === "html_inline") {
if (isLinkClose(currentToken.content) && this.htmlLinkLevel > 0) {
this.htmlLinkLevel--;
}
if (isLinkOpen(currentToken.content)) {
this.htmlLinkLevel++;
}
}
return this.htmlLinkLevel > 0;
}
/*
* Returns a list of the tokens needed for rendering all mentions inside of the current token
*/
}, {
key: "mentionTokens",
value: function mentionTokens(currentToken, state) {
var _this = this;
var text = currentToken.content,
level = currentToken.level,
tokens = [],
token = void 0;
var matches = text.match(mentionRegExpGlobal);
if (matches === null) {
return [currentToken];
}
matches.forEach(function (match) {
var _match$match = match.match(mentionRegExp),
_match$match2 = _slicedToArray(_match$match, 3),
matchedText = _match$match2[0],
name = _match$match2[1],
diasporaId = _match$match2[2],
pos = text.indexOf(match);
if (pos > 0) {
token = new state.Token("text", "", 0);
token.content = text.slice(0, pos);
token.level = level;
tokens.push(token);
}
token = new state.Token("text", "", 0);
token.content = "@";
token.level = level;
tokens.push(token);
var person = _this.findPersonById(diasporaId);
if (person) {
token = new state.Token("mention_open", "", 1);
token.content = person.url || "/people/" + person.guid;
token.linkclass = _this.mentionLinkClass(person);
token.level = level++;
tokens.push(token);
token = new state.Token("mention_text", "", 0);
token.content = _this.escapeHtml(name ? name : person.name).trim();
token.level = level;
tokens.push(token);
token = new state.Token("mention_close", "", -1);
token.level = --level;
tokens.push(token);
} else {
token = new state.Token("text", "", 0);
token.content = name ? name : diasporaId;
token.level = level;
tokens.push(token);
}
text = text.slice(pos + matchedText.length);
});
if (text.length > 0) {
token = new state.Token("text", "", 0);
token.content = text;
token.level = state.level;
tokens.push(token);
}
return tokens;
}
}, {
key: "parseMentions",
value: function parseMentions(state) {
var _this2 = this;
state.tokens.forEach(function (blockToken) {
if (blockToken.type !== "inline") {
return;
}
_this2.inMarkdownLink = false;
_this2.htmlLinkLevel = 0;
blockToken.children = blockToken.children.map(function (currentToken) {
if (_this2.skipMarkdownLink(currentToken) || _this2.skipHtmlLink(currentToken) || currentToken.type !== "text") {
return [currentToken];
}
return _this2.mentionTokens(currentToken, state);
}).reduce(function (a, b) {
return a.concat(b);
}, []);
return;
});
}
}]);
return MentionPlugin;
}();
module.exports = function (md, opts) {
return new MentionPlugin(md, opts);
};
},{"core-js/fn/array/find":1}]},{},[34])(34)
});