{"version":3,"file":"ReadMore-Bz7duiP5.js","sources":["../../../node_modules/html-truncate/lib/truncate.js","../../../frontend/src/Components/ReadMore/ReadMore.tsx"],"sourcesContent":["/**\n * Truncate HTML string and keep tag safe.\n *\n * @method truncate\n * @param {String} string string needs to be truncated\n * @param {Number} maxLength length of truncated string\n * @param {Object} options (optional)\n * @param {Boolean} [options.keepImageTag] flag to specify if keep image tag, false by default\n * @param {Boolean} [options.truncateLastWord] truncates last word, true by default\n * @param {Number} [options.slop] tolerance when options.truncateLastWord is false before we give up and just truncate at the maxLength position, 10 by default (but not greater than maxLength)\n * @param {Boolean|String} [options.ellipsis] omission symbol for truncated string, '...' by default\n * @return {String} truncated string\n */\nfunction truncate(string, maxLength, options) {\n var EMPTY_OBJECT = {},\n EMPTY_STRING = '',\n DEFAULT_TRUNCATE_SYMBOL = '...',\n DEFAULT_SLOP = 10 > maxLength ? maxLength : 10,\n EXCLUDE_TAGS = ['img', 'br'], // non-closed tags\n items = [], // stack for saving tags\n total = 0, // record how many characters we traced so far\n content = EMPTY_STRING, // truncated text storage\n KEY_VALUE_REGEX = '([\\\\w|-]+\\\\s*(=\\\\s*\"[^\"]*\")?\\\\s*)*',\n IS_CLOSE_REGEX = '\\\\s*\\\\/?\\\\s*',\n CLOSE_REGEX = '\\\\s*\\\\/\\\\s*',\n SELF_CLOSE_REGEX = new RegExp('<\\\\/?\\\\w+\\\\s*' + KEY_VALUE_REGEX + CLOSE_REGEX + '>'),\n HTML_TAG_REGEX = new RegExp('<\\\\/?\\\\w+\\\\s*' + KEY_VALUE_REGEX + IS_CLOSE_REGEX + '>'),\n URL_REGEX = /(((ftp|https?):\\/\\/)[\\-\\w@:%_\\+.~#?,&\\/\\/=]+)|((mailto:)?[_.\\w\\-]+@([\\w][\\w\\-]+\\.)+[a-zA-Z]{2,3})/g, // Simple regexp\n IMAGE_TAG_REGEX = new RegExp('<img\\\\s*' + KEY_VALUE_REGEX + IS_CLOSE_REGEX + '>'),\n WORD_BREAK_REGEX = new RegExp('\\\\W+', 'g'),\n matches = true,\n result,\n index,\n tail,\n tag,\n selfClose;\n\n /**\n * Remove image tag\n *\n * @private\n * @method _removeImageTag\n * @param {String} string not-yet-processed string\n * @return {String} string without image tags\n */\n function _removeImageTag(string) {\n var match = IMAGE_TAG_REGEX.exec(string),\n index,\n len;\n\n if (!match) {\n return string;\n }\n\n index = match.index;\n len = match[0].length;\n\n return string.substring(0, index) + string.substring(index + len);\n }\n\n /**\n * Dump all close tags and append to truncated content while reaching upperbound\n *\n * @private\n * @method _dumpCloseTag\n * @param {String[]} tags a list of tags which should be closed\n * @return {String} well-formatted html\n */\n function _dumpCloseTag(tags) {\n var html = '';\n\n tags.reverse().forEach(function (tag, index) {\n // dump non-excluded tags only\n if (-1 === EXCLUDE_TAGS.indexOf(tag)) {\n html += '</' + tag + '>';\n }\n });\n\n return html;\n }\n\n /**\n * Process tag string to get pure tag name\n *\n * @private\n * @method _getTag\n * @param {String} string original html\n * @return {String} tag name\n */\n function _getTag(string) {\n var tail = string.indexOf(' ');\n\n // TODO:\n // we have to figure out how to handle non-well-formatted HTML case\n if (-1 === tail) {\n tail = string.indexOf('>');\n if (-1 === tail) {\n throw new Error('HTML tag is not well-formed : ' + string);\n }\n }\n\n return string.substring(1, tail);\n }\n\n\n /**\n * Get the end position for String#substring()\n *\n * If options.truncateLastWord is FALSE, we try to the end position up to\n * options.slop characters to avoid breaking in the middle of a word.\n *\n * @private\n * @method _getEndPosition\n * @param {String} string original html\n * @param {Number} tailPos (optional) provided to avoid extending the slop into trailing HTML tag\n * @return {Number} maxLength\n */\n function _getEndPosition (string, tailPos) {\n var defaultPos = maxLength - total,\n position = defaultPos,\n isShort = defaultPos < options.slop,\n slopPos = isShort ? defaultPos : options.slop - 1,\n substr,\n startSlice = isShort ? 0 : defaultPos - options.slop,\n endSlice = tailPos || (defaultPos + options.slop),\n result;\n\n if (!options.truncateLastWord) {\n\n substr = string.slice(startSlice, endSlice);\n\n if (tailPos && substr.length <= tailPos) {\n position = substr.length;\n }\n else {\n while ((result = WORD_BREAK_REGEX.exec(substr)) !== null) {\n // a natural break position before the hard break position\n if (result.index < slopPos) {\n position = defaultPos - (slopPos - result.index);\n // keep seeking closer to the hard break position\n // unless a natural break is at position 0\n if (result.index === 0 && defaultPos <= 1) break;\n }\n // a natural break position exactly at the hard break position\n else if (result.index === slopPos) {\n position = defaultPos;\n break; // seek no more\n }\n // a natural break position after the hard break position\n else {\n position = defaultPos + (result.index - slopPos);\n break; // seek no more\n }\n }\n }\n if (string.charAt(position - 1).match(/\\s$/)) position--;\n }\n return position;\n }\n\n options = options || EMPTY_OBJECT;\n options.ellipsis = (undefined !== options.ellipsis) ? options.ellipsis : DEFAULT_TRUNCATE_SYMBOL;\n options.truncateLastWord = (undefined !== options.truncateLastWord) ? options.truncateLastWord : true;\n options.slop = (undefined !== options.slop) ? options.slop : DEFAULT_SLOP;\n\n while (matches) {\n matches = HTML_TAG_REGEX.exec(string);\n\n if (!matches) {\n if (total >= maxLength) { break; }\n\n matches = URL_REGEX.exec(string);\n if (!matches || matches.index >= maxLength) {\n content += string.substring(0, _getEndPosition(string));\n break;\n }\n\n while (matches) {\n result = matches[0];\n index = matches.index;\n content += string.substring(0, (index + result.length) - total);\n string = string.substring(index + result.length);\n matches = URL_REGEX.exec(string);\n }\n break;\n }\n\n result = matches[0];\n index = matches.index;\n\n if (total + index > maxLength) {\n // exceed given `maxLength`, dump everything to clear stack\n content += string.substring(0, _getEndPosition(string, index));\n break;\n } else {\n total += index;\n content += string.substring(0, index);\n }\n\n if ('/' === result[1]) {\n // move out open tag\n items.pop();\n selfClose=null;\n } else {\n selfClose = SELF_CLOSE_REGEX.exec(result);\n if (!selfClose) {\n tag = _getTag(result);\n\n items.push(tag);\n }\n }\n\n if (selfClose) {\n content += selfClose[0];\n } else {\n content += result;\n }\n string = string.substring(index + result.length);\n }\n\n if (string.length > maxLength - total && options.ellipsis) {\n content += options.ellipsis;\n }\n content += _dumpCloseTag(items);\n\n if (!options.keepImageTag) {\n content = _removeImageTag(content);\n }\n\n return content;\n}\n\nmodule.exports = truncate;\n","import React, { useState } from 'react';\nimport { Link as ButtonLink } from '@mui/material';\nimport { FormattedMessage } from 'react-intl';\nimport PropTypes from 'prop-types';\nimport truncate from 'html-truncate';\n\nimport { HtmlToMUIMapper, stripHtml } from '../../Utils';\n\nfunction ReadMore({ content, maxLength = 1000, expand = true }: any) {\n const [open, setOpen] = useState(false);\n const stripedContent = stripHtml(content);\n const truncatedContent = truncate(content, maxLength, { ellipsis: '…' });\n const displayReadMore = stripedContent.length > maxLength;\n\n if (expand || open || !displayReadMore) {\n return <HtmlToMUIMapper content={content} />;\n }\n\n return (\n <>\n <HtmlToMUIMapper content={truncatedContent} />\n\n {displayReadMore && (\n <ButtonLink\n component=\"button\"\n onClick={() => setOpen(!open)}\n variant=\"body1\"\n underline=\"hover\"\n sx={{ ml: 1 }}\n >\n <strong>\n <FormattedMessage id=\"BUTTONS.READ_MORE\" />\n </strong>\n </ButtonLink>\n )}\n </>\n );\n}\n\nReadMore.propTypes = {\n content: PropTypes.string.isRequired,\n maxLength: PropTypes.number,\n expand: PropTypes.bool,\n};\n\nexport default ReadMore;\n"],"names":["truncate","string","maxLength","options","EMPTY_OBJECT","EMPTY_STRING","DEFAULT_TRUNCATE_SYMBOL","DEFAULT_SLOP","EXCLUDE_TAGS","items","total","content","KEY_VALUE_REGEX","IS_CLOSE_REGEX","CLOSE_REGEX","SELF_CLOSE_REGEX","HTML_TAG_REGEX","URL_REGEX","IMAGE_TAG_REGEX","WORD_BREAK_REGEX","matches","result","index","tag","selfClose","_removeImageTag","match","len","_dumpCloseTag","tags","html","_getTag","tail","_getEndPosition","tailPos","defaultPos","position","isShort","slopPos","substr","startSlice","endSlice","truncate_1","ReadMore","_ref","_ref$maxLength","_ref$expand","expand","_useState","useState","_useState2","_slicedToArray","open","setOpen","stripedContent","stripHtml","truncatedContent","ellipsis","displayReadMore","length","React","createElement","HtmlToMUIMapper","Fragment","ButtonLink","component","onClick","variant","underline","sx","ml","FormattedMessage","id","propTypes","PropTypes","isRequired","number","bool"],"mappings":"qLAaA,SAASA,EAASC,EAAQC,EAAWC,EAAS,CAC1C,IAAIC,EAAe,CAAE,EACjBC,EAAe,GACfC,EAA0B,MAC1BC,EAAe,GAAKL,EAAYA,EAAY,GAC5CM,EAAe,CAAC,MAAO,IAAI,EAC3BC,EAAQ,CAAA,EACRC,EAAQ,EACRC,EAAUN,EACVO,EAAkB,qCAClBC,EAAiB,eACjBC,EAAc,cACdC,EAAmB,IAAI,OAAO,gBAAkBH,EAAkBE,EAAc,GAAG,EACnFE,EAAiB,IAAI,OAAO,gBAAkBJ,EAAkBC,EAAiB,GAAG,EACpFI,EAAY,qGACZC,EAAkB,IAAI,OAAO,WAAaN,EAAkBC,EAAiB,GAAG,EAChFM,EAAmB,IAAI,OAAO,OAAQ,GAAG,EACzCC,EAAU,GACVC,EACAC,EAEAC,EACAC,EAUJ,SAASC,EAAgBxB,EAAQ,CAC7B,IAAIyB,EAAQR,EAAgB,KAAKjB,CAAM,EACnCqB,EACAK,EAEJ,OAAKD,GAILJ,EAAQI,EAAM,MACdC,EAAMD,EAAM,CAAC,EAAE,OAERzB,EAAO,UAAU,EAAGqB,CAAK,EAAIrB,EAAO,UAAUqB,EAAQK,CAAG,GANrD1B,CAOnB,CAUI,SAAS2B,EAAcC,EAAM,CACzB,IAAIC,EAAO,GAEX,OAAAD,EAAK,QAAS,EAAC,QAAQ,SAAUN,EAAKD,EAAO,CAE9Bd,EAAa,QAAQe,CAAG,IAA/B,KACAO,GAAQ,KAAOP,EAAM,IAErC,CAAS,EAEMO,CACf,CAUI,SAASC,EAAQ9B,EAAQ,CACrB,IAAI+B,EAAO/B,EAAO,QAAQ,GAAG,EAI7B,GAAW+B,IAAP,KACAA,EAAO/B,EAAO,QAAQ,GAAG,EACd+B,IAAP,IACA,MAAM,IAAI,MAAM,iCAAmC/B,CAAM,EAIjE,OAAOA,EAAO,UAAU,EAAG+B,CAAI,CACvC,CAeI,SAASC,EAAiBhC,EAAQiC,EAAS,CACvC,IAAIC,EAAajC,EAAYQ,EACzB0B,EAAWD,EACXE,EAAUF,EAAahC,EAAQ,KAC/BmC,EAAUD,EAAUF,EAAahC,EAAQ,KAAO,EAChDoC,EACAC,EAAaH,EAAU,EAAIF,EAAahC,EAAQ,KAChDsC,EAAWP,GAAYC,EAAahC,EAAQ,KAC5CkB,EAEJ,GAAI,CAAClB,EAAQ,iBAAkB,CAI3B,GAFAoC,EAAStC,EAAO,MAAMuC,EAAYC,CAAQ,EAEtCP,GAAWK,EAAO,QAAUL,EAC5BE,EAAWG,EAAO,WAGlB,OAAQlB,EAASF,EAAiB,KAAKoB,CAAM,KAAO,MAEhD,GAAIlB,EAAO,MAAQiB,GAIf,GAHAF,EAAWD,GAAcG,EAAUjB,EAAO,OAGtCA,EAAO,QAAU,GAAKc,GAAc,EAAG,cAGtCd,EAAO,QAAUiB,EAAS,CAC/BF,EAAWD,EACX,KACxB,KAEyB,CACDC,EAAWD,GAAcd,EAAO,MAAQiB,GACxC,KACxB,CAGgBrC,EAAO,OAAOmC,EAAW,CAAC,EAAE,MAAM,KAAK,GAAGA,GAC1D,CACQ,OAAOA,CACf,CAOI,IALAjC,EAAUA,GAAWC,EACrBD,EAAQ,SAA0BA,EAAQ,WAAtB,OAAkCA,EAAQ,SAAWG,EACzEH,EAAQ,iBAAkCA,EAAQ,mBAAtB,OAA0CA,EAAQ,iBAAmB,GACjGA,EAAQ,KAAsBA,EAAQ,OAAtB,OAA8BA,EAAQ,KAAOI,EAEtDa,GAAS,CAGZ,GAFAA,EAAUJ,EAAe,KAAKf,CAAM,EAEhC,CAACmB,EAAS,CACV,GAAIV,GAASR,EAAa,MAG1B,GADAkB,EAAUH,EAAU,KAAKhB,CAAM,EAC3B,CAACmB,GAAWA,EAAQ,OAASlB,EAAW,CACxCS,GAAWV,EAAO,UAAU,EAAGgC,EAAgBhC,CAAM,CAAC,EACtD,KAChB,CAEY,KAAOmB,GACHC,EAASD,EAAQ,CAAC,EAClBE,EAAQF,EAAQ,MAChBT,GAAWV,EAAO,UAAU,EAAIqB,EAAQD,EAAO,OAAUX,CAAK,EAC9DT,EAASA,EAAO,UAAUqB,EAAQD,EAAO,MAAM,EAC/CD,EAAUH,EAAU,KAAKhB,CAAM,EAEnC,KACZ,CAKQ,GAHAoB,EAASD,EAAQ,CAAC,EAClBE,EAAQF,EAAQ,MAEZV,EAAQY,EAAQpB,EAAW,CAE3BS,GAAWV,EAAO,UAAU,EAAGgC,EAAgBhC,EAAQqB,CAAK,CAAC,EAC7D,KACZ,MACYZ,GAASY,EACTX,GAAWV,EAAO,UAAU,EAAGqB,CAAK,EAG5BD,EAAO,CAAC,IAAhB,KAEAZ,EAAM,IAAK,EACXe,EAAU,OAEVA,EAAYT,EAAiB,KAAKM,CAAM,EACnCG,IACDD,EAAMQ,EAAQV,CAAM,EAEpBZ,EAAM,KAAKc,CAAG,IAIlBC,EACAb,GAAWa,EAAU,CAAC,EAEtBb,GAAWU,EAEfpB,EAASA,EAAO,UAAUqB,EAAQD,EAAO,MAAM,CACvD,CAEI,OAAIpB,EAAO,OAASC,EAAYQ,GAASP,EAAQ,WAC7CQ,GAAWR,EAAQ,UAEvBQ,GAAWiB,EAAcnB,CAAK,EAEzBN,EAAQ,eACTQ,EAAUc,EAAgBd,CAAO,GAG9BA,CACX,CAEA,OAAA+B,EAAiB1C;01BChOjB,SAAS2C,GAAQC,EAAoD,CAAA,IAAjDjC,EAAOiC,EAAPjC,QAAOkC,EAAAD,EAAE1C,UAAAA,EAAS2C,IAAG,OAAA,IAAIA,EAAAC,EAAAF,EAAEG,OAAAA,EAAMD,IAAG,OAAA,GAAIA,EAC1DE,EAAwBC,EAAAA,SAAS,EAAK,EAACC,EAAAC,EAAAH,EAAA,CAAA,EAAhCI,EAAIF,EAAA,CAAA,EAAEG,EAAOH,EAAA,CAAA,EACdI,EAAiBC,EAAU5C,CAAO,EAClC6C,EAAmBxD,EAASW,EAAST,EAAW,CAAEuD,SAAU,GAAA,CAAK,EACjEC,EAAkBJ,EAAeK,OAASzD,EAE5C6C,OAAAA,GAAUK,GAAQ,CAACM,EACdE,EAAAC,cAACC,EAAe,CAACnD,QAAAA,CAAAA,CAAmB,IAI3CkD,cAAAD,EAAAG,SAAA,KACEH,EAAAC,cAACC,EAAe,CAACnD,QAAS6C,CAAmB,CAAA,EAE5CE,GACCE,EAAAC,cAACG,EAAU,CACTC,UAAU,SACVC,QAAS,UAAF,CAAQb,OAAAA,EAAQ,CAACD,CAAI,CAAC,EAC7Be,QAAQ,QACRC,UAAU,QACVC,GAAI,CAAEC,GAAI,CAAA,CAAE,EAEZT,EAAAA,cAAA,SAAA,KACED,EAAAC,cAACU,EAAgB,CAACC,GAAG,mBAAqB,CAAA,CACpC,CACE,CAEd,CAEN,CAEA7B,GAAS8B,UAAY,CACnB9D,QAAS+D,EAAUzE,OAAO0E,WAC1BzE,UAAWwE,EAAUE,OACrB7B,OAAQ2B,EAAUG,IACpB","x_google_ignoreList":[0]}