UNPKG

bbcode-react-native-view

Version:
164 lines (133 loc) 3.63 kB
const tagsDoesNotHaveChildren = ['img']; const parseOptions = (tag, tagName, content) => { const matches = tag.match(/=(\'|")?(.*)(\'|")?[^\]]*\]/); if (tagName === 'url') { if (matches === null) { return { url: content }; } return { url: matches[2] }; } else if (tagName === 'img') { return { url: content }; } else if (tagName === 'color') { if (matches !== null) { return { color: matches[2] }; } } return null; }; const parseText = (text) => { let tagMap = []; tagMap.push({ tagName: undefined, content: text }); return tagMap; }; const parseTagChildren = (tagName, content) => { if (tagsDoesNotHaveChildren.indexOf(tagName) !== -1) { return []; } switch (tagName) { case 'list': const elements = content.split('\n'); const tagMap = []; for (let i = 0; i < elements.length; i++) { const element = elements[i]; if (!element.length) { continue; } tagMap.push({ tagRaw: element, tagName: undefined, content: element.substr(3), children: Parser(element.substr(3)) }); } return tagMap; default: return Parser(content); } }; const Parser = (message) => { let index = 0; let tagMap = []; const matches = message.match(/(?:\[([a-z0-9_]+)(=|\])|\[\/([a-z0-9_]+)])/gi); if (matches === null) { return [ { tagName: undefined, content: message, children: [] } ]; } while (index < matches.length) { let tag = matches[index]; index++; if (tag.substr(-1) !== ']') { // missing close tags const openPosition = message.indexOf(tag); const closePosition = message.indexOf(']'); tag = message.substring(openPosition, closePosition + 1); } const tagPosition = message.indexOf(tag); if (tagPosition > 0) { const tagContent = message.substr(0, tagPosition); const textMap = parseText(tagContent); for (let i = 0; i < textMap.length; i++) { tagMap.push(textMap[i]); } message = message.substr(tagPosition + tag.length); } else { message = message.substr(tag.length); } let tagName = tag.substr(1), splitterPosition = tagName.indexOf('='); if (splitterPosition !== -1) { tagName = tagName.substring(0, splitterPosition); } else { tagName = tagName.substr(0, tagName.length - 1); } let closeTagIndex = index, closeTag; while (closeTagIndex < matches.length) { // loop to find close tag. const closeTag_ = matches[closeTagIndex]; closeTagIndex++; if (closeTag_.toLowerCase() === `[/${tagName.toLowerCase()}]`) { closeTag = closeTag_; break; } } if (closeTag) { const closeTagPosition = message.indexOf(closeTag); const tagContent = message.substr(0, closeTagPosition); message = message.substr(closeTagPosition + closeTag.length); const tagNameLower = tagName.toLowerCase(); tagMap.push({ tagRaw: `${tag}${tagContent}${closeTag}`, tagName: tagNameLower, content: tagContent, options: parseOptions(tag, tagNameLower, tagContent), children: parseTagChildren(tagNameLower, tagContent) }); index = closeTagIndex; } } if (message.length > 0) { const textMap = parseText(message); for (let i = 0; i < textMap.length; i++) { tagMap.push(textMap[i]); } } return tagMap; }; module.exports = Parser;