/*
* Copyright (c) Huawei Technologies Co., Ltd. 2025-2025. All rights resvered.
*/
package commonmark4cj.commonmark
class InlineParserContextCalc {
var specialCharacters: BitSet
var delimiterProcessors: HashMap<Rune, DelimiterProcessor>
let inlineContentParserFactories: ArrayList<InlineContentParserFactory>
let linkProcessors: ArrayList<LinkProcessor>
let linkMarkers: BitSet
init(context: InlineParserContext) {
this.inlineContentParserFactories = calculateInlineContentParserFactories(
context.getCustomInlineContentParserFactories())
this.delimiterProcessors = calculateDelimiterProcessors(context.getCustomDelimiterProcessors())
this.linkProcessors = calculateLinkProcessors(context.getCustomLinkProcessors())
this.linkMarkers = calculateLinkMarkers(context.getCustomLinkMarkers())
this.specialCharacters = calculateSpecialCharacters(linkMarkers, this.delimiterProcessors.keys(),
this.inlineContentParserFactories)
}
@Frozen
private static func calculateInlineContentParserFactories(customFactories: ArrayList<InlineContentParserFactory>): ArrayList<InlineContentParserFactory> {
// Custom parsers can override built-in parsers if they want, so make sure they are tried first
var list = ArrayList(customFactories)
list.add(BackslashInlineParserFactory())
list.add(BackticksInlineParserFactory())
list.add(EntityInlineParserFactory())
list.add(AutolinkInlineParserFactory())
list.add(HtmlInlineParserFactory())
return list
}
@Frozen
private static func calculateLinkProcessors(linkProcessors: ArrayList<LinkProcessor>): ArrayList<LinkProcessor> {
// Custom link processors can override the built-in behavior, so make sure they are tried first
var list = ArrayList(linkProcessors)
list.add(CoreLinkProcessor())
return list
}
@Frozen
private static func calculateDelimiterProcessors(delimiterProcessors: ArrayList<DelimiterProcessor>): HashMap<Rune,
DelimiterProcessor> {
var map: HashMap<Rune, DelimiterProcessor> = HashMap<Rune, DelimiterProcessor>()
addDelimiterProcessors([AsteriskDelimiterProcessor(), UnderscoreDelimiterProcessor()], map)
addDelimiterProcessors(delimiterProcessors, map)
return map
}
@Frozen
private static func addDelimiterProcessors(
delimiterProcessors: Collection<DelimiterProcessor>,
hashMap: HashMap<Rune, DelimiterProcessor>
): Unit {
for (delimiterProcessor in delimiterProcessors) {
let opening: Rune = delimiterProcessor.getOpeningCharacter()
let closing: Rune = delimiterProcessor.getClosingCharacter()
if (opening == closing) {
let old: Option<DelimiterProcessor> = hashMap.get(opening)
if (old.isSome() && old().getOpeningCharacter() == old().getClosingCharacter()) {
var s: StaggeredDelimiterProcessor
if (let Some(v: StaggeredDelimiterProcessor) <- old) {
s = v
} else {
s = StaggeredDelimiterProcessor(opening)
s.add(old())
}
s.add(delimiterProcessor)
hashMap.add(opening, s)
} else {
addDelimiterProcessorForChar(opening, delimiterProcessor, hashMap)
}
} else {
addDelimiterProcessorForChar(opening, delimiterProcessor, hashMap)
addDelimiterProcessorForChar(closing, delimiterProcessor, hashMap)
}
}
}
@Frozen
private static func addDelimiterProcessorForChar(
delimiterChar: Rune,
toAdd: DelimiterProcessor,
delimiterProcessors: HashMap<Rune, DelimiterProcessor>
): Unit {
let existing: ?DelimiterProcessor = delimiterProcessors.add(delimiterChar, toAdd)
if (existing.isSome()) {
throw IllegalArgumentException("Delimiter processor conflict with delimiter char '${delimiterChar}'")
}
}
@Frozen
private static func calculateLinkMarkers(linkMarkers: Set<Rune>): BitSet {
var bitSet = BitSet()
for (c in linkMarkers) {
bitSet.set(c)
}
bitSet.set(r'!')
return bitSet
}
@Frozen
private static func calculateSpecialCharacters(
linkMarkers: BitSet,
delimiterCharacters: Collection<Rune>,
inlineContentParserFactories: ArrayList<InlineContentParserFactory>
): BitSet {
var bitSet: BitSet = linkMarkers.clone()
for (c in delimiterCharacters) {
bitSet.set(c)
}
for (factory in inlineContentParserFactories) {
for (c in factory.getTriggerCharacters()) {
bitSet.set(c)
}
}
bitSet.set(r'[')
bitSet.set(r']')
bitSet.set(r'!')
bitSet.set(r'\n')
return bitSet
}
}