This program converts legacy markup in the form seen in the tests to the resulting markdown seen in the test's respective comment.
The full program is as uploaded as a snippet, or you may see below
let tests = [
"OneMatch$$$TwoMatch" // [One Match](OneMatch)[Two Match](TwoMatch)
, "OneMatch$$$TwoMatch$$$ThreeMatch" // [One Match](OneMatch)[Two Match](TwoMatch)[Three Match](ThreeMatch)
, "E$$$scapeMatch" // Escape Match
, "SimpleMatch" // [Simple Match](SimpleMatch)
, "Prefixed$$$MatchyMatch" // Prefixed [Matchy Match](MatchyMatch)
, "MatchMatchWith$$$Suffix" // [Match Match With](MatchMatchWith) Suffix
, "MatchesWithPlural$$$s" // [Matches With Plural](MatchesWithPlural)s
, "This$$$Gets$$$Escaped" // This Gets Escaped
]
The $$$
delimits valid matches. Furthermore, a match is only valid if it is composed of two or more StartCased words.
Possible matches are checked against a regex and either formatted, or just returned:
function parseWord(word) {
let linkRE = /\b[A-Z][a-z]+([A-Z][a-z]+)+\b/g
let validLinks = word.match(linkRE)
let stripped = word.replace(/\${3}/, '')
if (validLinks) {
return formatLinks(validLinks, stripped)
}
return _.startCase(stripped)
}
If we are to format the match we find the difference between the matched link and the entire found word. From there we decide whether to add the difference as a prefix or suffix to the link:
function formatLinks(matches, stripped) {
let formatted_links = []
for (match of matches) {
let diff = difference(match, stripped)
if (isSimpleLink(diff)) {
formatted_links.push(formatAsSimpleLink(diff))
} else if (hasPrefix(diff)) {
formatted_links.push(formatAsPrefixedLink(diff))
} else if (hasSuffix(diff)) {
formatted_links.push(formatAsSuffixedLink(diff))
}
}
// There might be multiple links within a word
// in which case we join them and strip any duplicated parts
// (which are otherwise interpreted as suffixes)
if (formatted_links.length > 1) {
return combineLinks(formatted_links)
}
// Default case
return formatted_links[0]
}
The function, difference
, is fast-diff from npm. Which is defined as such:
let result = difference('Good dog', 'Bad dog');
// [[-1, "Goo"], [1, "Ba"], [0, "d dog"]]
Here are the remaining helper functions (or you may view the snippet for the rest):
function combineLinks(links) {
links.join('').replace(/(?<=\)).*?(?=\[)/g, '')
}
function formatAsSimpleLink(diff) {
let link = diff[0][1]
let text = _.startCase(link)
return `[${text}](${link})`
}
function formatAsPrefixedLink(diff) {
let link = diff[1][1]
let text = _.startCase(link)
let prefix = _.startCase(diff[0][1])
return `${prefix} [${text}](${link})`
}
function formatAsSuffixedLink(diff) {
let link = diff[0][1]
let text = _.startCase(link)
let suffix = diff[1][1]
// don't capitalize plurals
if (suffixIsPlural(suffix) == false) {
suffix = _.startCase(diff[1][1])
return `[${text}](${link}) ${suffix}`
}
return `[${text}](${link})${suffix}`
}
function isSimpleLink(diff) {
return diff.length == 1
}
function hasPrefix(diff) {
return diff[0][0] == 1 && diff[1][0] == 0
}
function hasSuffix(diff) {
return diff[0][0] == 0 && diff[1][0] == 1
}
function suffixIsPlural(suffix) {
return suffix.slice(-1) == 's'
}
My main concerns are:
- The looping in
formatLinks
, which is really only useful if the word has a suffix which is also a link - The magic numbers used to check the
diff
, e.g.,diff[0][1]
- If there is a better way to tackle the problem.