diff --git a/Go/WMarkDown.go b/Go/WMarkDown.go
new file mode 100644
index 0000000..92653ea
--- /dev/null
+++ b/Go/WMarkDown.go
@@ -0,0 +1,1684 @@
+package Modules
+
+import (
+ "bytes"
+ "encoding/base64"
+ "encoding/json"
+ "maps"
+ "os"
+ "path/filepath"
+ "regexp"
+ "runtime/debug"
+ "slices"
+ "strconv"
+ "strings"
+)
+
+type ItemMark struct {
+ from string
+ to string
+ pattern *regexp.Regexp
+}
+
+type WMDConstants struct {
+
+ // Languages
+ HTML int
+
+ // Analyse modes
+ RAW int
+ SUBITEM int
+ LINKED int
+
+ html_special_characters map[string]string
+ quote_special map[string]string
+
+ item_mark ItemMark
+}
+
+type PatternMatch struct {
+ String string
+ Groups []string
+ Span []int
+ Ok bool
+}
+
+type WMDModule struct {
+ mode int
+ patterns []*regexp.Regexp
+ pattern_method func(data string, patterns []*regexp.Regexp) *PatternMatch
+ method func(matches *PatternMatch, language int, path string) string
+}
+
+type WMDModulePattern struct {
+ patterns []string
+ method func(data string, patterns []*regexp.Regexp) *PatternMatch
+}
+
+type WMarkDown struct {
+ keys []string
+ modules map[string]*WMDModule
+ ids_cache []string
+}
+
+type WMDAnalyseItem struct {
+ exists bool
+ from int
+ to int
+ matches *PatternMatch
+}
+
+type PatternsModel struct {
+ RE_BLOCK_HTML *regexp.Regexp
+ RE_BLOCK_MARK *regexp.Regexp
+ RE_NEW_LINES *regexp.Regexp
+ RE_NEW_LINE *regexp.Regexp
+ RE_STARTED_WHITE_SPACES *regexp.Regexp
+ RE_LINES *regexp.Regexp
+ RE_LIST_LINE *regexp.Regexp
+ RE_TABLE_LINE *regexp.Regexp
+ RE_TABLE_ITEM *regexp.Regexp
+ RE_OPTIONS *regexp.Regexp
+ RE_OPTION *regexp.Regexp
+ RE_EXTENSION *regexp.Regexp
+ RE_CHARACTERS_NO_ID *regexp.Regexp
+ RE_PHONE_NUMBER *regexp.Regexp
+ RE_EMAIL_ADDRESS *regexp.Regexp
+ RE_CLASS_ATTRIBUTE *regexp.Regexp
+ RE_WHITE_SPACES *regexp.Regexp
+ RE_LINE_MARKS *regexp.Regexp
+ RE_INTEGER *regexp.Regexp
+ RE_CODE_DOC *regexp.Regexp
+ RE_CODE_DOC_ARGUMENTS *regexp.Regexp
+ RE_CODE_DOC_SUBARGUMENTS *regexp.Regexp
+ RE_START_WITH_WHITE_SPACES *regexp.Regexp
+ RE_DOMAIN *regexp.Regexp
+ RE_PROTOCOL *regexp.Regexp
+ RE_TRACE_STACK *regexp.Regexp
+}
+
+type WMDListLevel struct {
+ separator int
+ _type byte
+ subtype string
+}
+
+type ModulePresentationLinkItem struct {
+ title string
+ avatars []string
+ links []string
+}
+
+var RE_BLOCK_HTML_PATTERN string = `^[ \t]*<\!\-{2}[ \t]*\[{2}[ \t]*(wmd|markdown)[ \t]*\]{2}[ \t]*\-{2}>`
+
+var WMD WMDConstants = WMDConstants{
+
+ // Languages
+ HTML: 1 << 0,
+
+ // Analyse modes
+ RAW: 0,
+ SUBITEM: 1 << 0,
+ LINKED: 1 << 1,
+
+ html_special_characters: map[string]string{
+ "<": "lt",
+ ">": "gt",
+ "&": "amp",
+ },
+ quote_special: map[string]string{
+ "?": "ask",
+ "!": "warning",
+ ">": "answer",
+ "Q": "comment",
+ "#": "note",
+ },
+
+ item_mark: ItemMark{
+ from: "###@&&_",
+ to: "_&&@###",
+ pattern: regexp.MustCompile(`\#{3}\@\&{2}_([0-9]+)_\&{2}\@\#{3}`),
+ },
+}
+
+var Patterns PatternsModel = PatternsModel{
+ RE_BLOCK_HTML: regexp.MustCompile(`(?mi)` + RE_BLOCK_HTML_PATTERN),
+ RE_BLOCK_MARK: regexp.MustCompile(`(?mi)^[ \t]*((" ?){3}|(\' ?){3}|(` + "`" + ` ?){3})[ \t]*(wmd|wmarkdown)|` + RE_BLOCK_HTML_PATTERN),
+ RE_NEW_LINES: regexp.MustCompile(`[\r\n]+`),
+ RE_NEW_LINE: regexp.MustCompile(`\n|\r\n|\r`),
+ RE_STARTED_WHITE_SPACES: regexp.MustCompile(`^[ \t]*`),
+ RE_LINES: regexp.MustCompile(`(?m)^[^\r\n]+`),
+ RE_LIST_LINE: regexp.MustCompile(`(?mi)^([ \t]*)(([\-\*#\+]+)|([0-9]+|[a-z]+)\.)?(.*)$`),
+ RE_TABLE_LINE: regexp.MustCompile(`(?m)^\|([^\r\n"\']+|"([^"\\\\]+|\\\\(.|[\r\n])|[\r\n]+)*"|\'([^\'\\\\]+|\\\\(.|[\r\n])|[\r\n]+)*\')*[\r\n]*`),
+ RE_TABLE_ITEM: regexp.MustCompile(`(\|+)(([^\|\'\"]+|"([^"\\\\]+|\\\\(.|[\r\n])|[\r\n]+)*"|\'([^\'\\\\]+|\\\\(.|[\r\n])|[\r\n]+)*\')*)`),
+ RE_OPTIONS: regexp.MustCompile("(?im)^`" + `{3}[ \t]*w(?:md|markdown)-options[ \t]*(?:\n|\r\n|\r)((?:[^\r\n` + "`" + `]+|[\r\n]+|` + "`{1,2}[^`])*)`{3}"),
+ RE_OPTION: regexp.MustCompile(`(?m)^([^=\r\n]+)=([^\r\n]*)$`),
+ RE_EXTENSION: regexp.MustCompile(`(?:([^\.\/\\\\]+)\.)?([^\.\/\\\\]+)$`),
+ RE_CHARACTERS_NO_ID: regexp.MustCompile(`(?i)[^a-z0-9]+`),
+ RE_PHONE_NUMBER: regexp.MustCompile(`^\+?[0-9 ]{5,22}$`),
+ RE_EMAIL_ADDRESS: regexp.MustCompile(`^[a-z\.0-9_\-]+@[a-z\.0-9_\-]+\.[a-z0-9]+$`),
+ RE_CLASS_ATTRIBUTE: regexp.MustCompile(`(?i)([^a-z0-9_\-]|^)(class=")([^"]+)(")`),
+ RE_WHITE_SPACES: regexp.MustCompile(`[ \t]+`),
+ RE_LINE_MARKS: regexp.MustCompile(`(?i)[\*#~\-_]+|\[[ \-x]\]|\([ \-x]\)`),
+ RE_INTEGER: regexp.MustCompile(`^[0-9]+$`),
+ RE_CODE_DOC: regexp.MustCompile(`^(\[([^\]]+)\][ \t]+)?([\!\?=\&\*]{0,3})(([^\(\[\]\?\!]+)([\:\.]))([^\(\.\:\[\]\=]+)(\(((.+|[\r\n]+)*)\)|[ \t]*=[ \t]*((.+|[\r\n]+)*))?`),
+ RE_CODE_DOC_ARGUMENTS: regexp.MustCompile(`([\!\?\&\*]{0,2})([^=]+)[ \t]+([^=]+)(=(.+))?`),
+ RE_CODE_DOC_SUBARGUMENTS: regexp.MustCompile(`<([^<>]+)>|("[^"]*"|\'[^\']*\')`),
+ RE_START_WITH_WHITE_SPACES: regexp.MustCompile(`(?m)^[ \t]`),
+ RE_DOMAIN: regexp.MustCompile(`^[^\:]+\:\/{2}[^\/]+`),
+ RE_PROTOCOL: regexp.MustCompile(`(?i)^([a-z0-9_\-]+)\:`),
+ RE_TRACE_STACK: regexp.MustCompile(`[\n\r](([^\.\(\s]+|\..)+)\([^\n\r]+[\r\n]+\s+([^\:\s]+)\:([0-9]+)`),
+}
+
+var MAXIMUM_INTEGER int = 2<<31 - 1
+var LIST_MARKS []byte = []byte{'-', '*', '+'}
+var LIST_LATIN_MARKS []byte = []byte{'a', 'A', 'i', 'I'}
+var TABLE_MARKS []byte = []byte{'^', '_', '='}
+
+func (_self *PatternMatch) GetByGroup(is []int, _default string) string {
+
+ var l int = len(_self.Groups)
+
+ for _, i := range is {
+ if i < l && _self.Groups[i] != "" {
+ return _self.Groups[i]
+ }
+ }
+ return _default
+}
+
+func (_self *PatternsModel) GetMatches(_string string, groups [][]byte) *PatternMatch {
+
+ var binary []byte = []byte(_string)
+ var matches PatternMatch
+
+ if groups != nil {
+
+ var index int = bytes.Index(binary, groups[0])
+
+ matches.String = _string
+ matches.Groups = []string{}
+ matches.Span = []int{index, index + len(groups[0])}
+ matches.Ok = true
+
+ for _, group := range groups {
+ matches.Groups = append(matches.Groups, string(group))
+ }
+
+ }
+
+ return &matches
+}
+
+func NewDebugStackLineModel(line int, file string, method string) DebugStackLineModel {
+ return DebugStackLineModel{
+ Line: line,
+ File: file,
+ Method: method,
+ }
+}
+
+func NewDebugStackLineFromMatch(match *PatternMatch) DebugStackLineModel {
+
+ line, _ := strconv.ParseInt(match.Groups[4], 10, 32)
+
+ return NewDebugStackLineModel(int(line), match.Groups[3], match.Groups[1])
+}
+
+func GetTraceStack(i int) []DebugStackLineModel {
+
+ var stack_map []DebugStackLineModel = []DebugStackLineModel{}
+
+ Patterns.Replace(string(debug.Stack()), Patterns.RE_TRACE_STACK, func(matches *PatternMatch) string {
+
+ stack_map = append(stack_map, NewDebugStackLineFromMatch(matches))
+
+ return ""
+ })
+
+ return stack_map[i+2:]
+}
+
+func DebugPrint(items ...any) {
+
+ var stack DebugStackLineModel = GetTraceStack(1)[0]
+ var json_data []byte
+
+ json_data, _ = json.Marshal(items)
+
+ println(">[DEV]>[" + strconv.FormatInt(int64(stack.Line), 10) + "]" + stack.File + "(" + stack.Method + "): " + string(json_data))
+
+}
+
+func (_self *PatternsModel) Match(_string string, pattern *regexp.Regexp) *PatternMatch {
+ return _self.GetMatches(_string, pattern.FindSubmatch([]byte(_string)))
+}
+
+func (_self *PatternsModel) Replace(_string string, pattern *regexp.Regexp, new_value any) string {
+
+ var callback func(matches *PatternMatch) string
+ var processed string = ""
+ var binary []byte = []byte(_string)
+
+ switch value := new_value.(type) {
+ case func(matches *PatternMatch) string:
+ callback = value
+ case string:
+ callback = func(matches *PatternMatch) string {
+ return value
+ }
+ }
+
+ for {
+
+ var matches *PatternMatch = _self.Match(string(binary), pattern)
+
+ if !matches.Ok {
+ break
+ }
+
+ processed += string(binary[:matches.Span[0]]) + callback(matches)
+ binary = binary[matches.Span[1]:]
+
+ }
+
+ return processed + string(binary)
+}
+
+func NewWMDModule(method func(matches *PatternMatch, language int, path string) string, mode int, pattern any) *WMDModule {
+
+ var wmdmodule WMDModule = WMDModule{
+ mode: mode,
+ method: method,
+ }
+
+ switch value := pattern.(type) {
+ case string:
+ wmdmodule.patterns = []*regexp.Regexp{regexp.MustCompile(value)}
+ wmdmodule.pattern_method = func(data string, patterns []*regexp.Regexp) *PatternMatch {
+ return Patterns.Match(data, patterns[0])
+ }
+ case WMDModulePattern:
+ wmdmodule.patterns = []*regexp.Regexp{}
+ for _, pattern := range value.patterns {
+ wmdmodule.patterns = append(wmdmodule.patterns, regexp.MustCompile(pattern))
+ }
+ wmdmodule.pattern_method = value.method
+ }
+
+ return &wmdmodule
+}
+
+func NewWMDModulePattern(patterns []string, method func(data string, patterns []*regexp.Regexp) *PatternMatch) WMDModulePattern {
+ return WMDModulePattern{
+ patterns: patterns,
+ method: method,
+ }
+}
+
+func BoldOrItalicModelMethod(data string, patterns []*regexp.Regexp) *PatternMatch {
+
+ var matches *PatternMatch = Patterns.Match(data, patterns[0])
+
+ if matches.Ok {
+ if matches.Groups[1] != "" {
+ matches.String = matches.String[1:]
+ matches.Groups[0] = matches.Groups[0][1:]
+ matches.Span[0]++
+ }
+ matches.Groups = []string{matches.Groups[0], matches.Groups[2]}
+ }
+
+ return matches
+}
+
+func check_html_module(_type string, matches *PatternMatch) string {
+
+ var class_type string = _type
+ var icon_name string = _type
+ var input_type string = _type
+ var disabled string = ""
+ var checked string = ""
+
+ switch _type {
+ case "radio":
+ class_type = "radio-button"
+ icon_name = "radio_button"
+ case "tick":
+ input_type = "checkbox"
+ }
+
+ if matches.Groups[1] != "" {
+ disabled = " disabled"
+ }
+ if matches.Groups[2] != "" {
+ checked = " checked"
+ }
+
+ return ``
+}
+
+func ModuleCheckbox(matches *PatternMatch, language int, path string) string {
+ if language&WMD.HTML != 0 {
+ return check_html_module("checkbox", matches)
+ }
+ return ""
+}
+
+func ModuleRadio(matches *PatternMatch, language int, path string) string {
+ if language&WMD.HTML != 0 {
+ return check_html_module("radio", matches)
+ }
+ return ""
+}
+
+func ModuleTick(matches *PatternMatch, language int, path string) string {
+ if language&WMD.HTML != 0 {
+ return check_html_module("tick", matches)
+ }
+ return ""
+}
+
+func ModuleExclude(matches *PatternMatch, language int, path string) string {
+ if language&WMD.HTML != 0 {
+ return `` + matches.Groups[1] + ``
+ }
+ return ""
+}
+
+func ModuleSpecialCharacters(matches *PatternMatch, language int, path string) string {
+ if language&WMD.HTML != 0 {
+ return matches.Groups[1]
+ }
+ return ""
+}
+
+func GetDirectory(path string) string {
+
+ stat, _ := os.Stat(path)
+
+ if stat.IsDir() {
+ return path
+ }
+ return filepath.Dir(path)
+}
+
+func PathExists(path string) bool {
+
+ _, error := os.Stat(path)
+
+ return error == nil
+}
+
+func LoadFile(path string) string {
+
+ var data string = ""
+
+ if stat, error := os.Stat(path); error == nil && !stat.IsDir() {
+ bytes, _ := os.ReadFile(path)
+ data = string(bytes)
+ }
+
+ return string(data)
+}
+
+func Base64Encode(_string string) string {
+ return base64.StdEncoding.EncodeToString([]byte(_string))
+}
+
+func JSONEncode(data any) string {
+
+ json, _ := json.Marshal(data)
+
+ return string(json)
+}
+
+func ModuleColorSample(matches *PatternMatch, language int, path string) string {
+ if language&WMD.HTML != 0 {
+
+ var color = matches.GetByGroup([]int{2, 3}, "")
+
+ return `` +
+ `` +
+ `` + color + `` +
+ ``
+ }
+ return ""
+}
+
+func BuildHTMLImage(links []string, _type string, title string) string {
+
+ var attributes string = ``
+
+ if title != "" {
+ attributes = ` title="` + title + `" alt="` + title + `"`
+ }
+
+ var html string = `` +
+ `` +
+ `` +
+ ``
+ if title != "" {
+ html += `` + title + ``
+ }
+
+ return html +
+ ``
+}
+
+func ModulePresentationLinks(matches *PatternMatch, language int, path string) string {
+ if language&WMD.HTML != 0 {
+
+ var items []ModulePresentationLinkItem = []ModulePresentationLinkItem{}
+ var i int = -1
+ var html_avatars string = ``
+ var html_list string = ``
+
+ for _, line := range Patterns.RE_NEW_LINES.Split(matches.Groups[1], -1) {
+
+ var data string = Trim(line)
+
+ if data == "" {
+ continue
+ }
+
+ var has_spaces bool = Patterns.Match(line, Patterns.RE_STARTED_WHITE_SPACES).Ok
+
+ if has_spaces {
+ if i == -1 {
+ continue
+ }
+ if data[0] == '*' {
+ items[i].avatars = append(items[i].avatars, data[1:])
+ if strings.Contains(data, ".k3y.pw/") {
+ items[i].avatars = append(items[i].avatars, strings.ReplaceAll(data[1:], ".k3y.pw/", ".local/"))
+ }
+ } else {
+ items[i].links = append(items[i].links, data)
+ }
+ } else {
+ i += 1
+ items = append(items, ModulePresentationLinkItem{
+ title: Trim(line),
+ avatars: []string{},
+ links: []string{},
+ })
+ }
+
+ }
+
+ for i, item := range items {
+
+ html_avatars += `
]*)>`,
+ `(?i)<\/code\-sample\-block>`,
+ }, func(data string, patterns []*regexp.Regexp) *PatternMatch {
+
+ var pattern *PatternMatch = &PatternMatch{}
+ var matches *PatternMatch = Patterns.Match(data, patterns[0])
+
+ if matches.Ok {
+
+ var from int = matches.Span[0]
+ var internal_string string = data[matches.Span[0]:matches.Span[1]]
+ var attributes string = matches.Groups[1]
+ var fill int = matches.Span[1]
+
+ data = data[fill:]
+ matches = Patterns.Match(data, patterns[1])
+
+ if matches.Ok {
+
+ internal_string += data[:matches.Span[1]]
+
+ pattern.Ok = true
+ pattern.Groups = []string{internal_string, attributes, data[:matches.Span[0]]}
+ pattern.Span = []int{from, fill + matches.Span[1]}
+ pattern.String = internal_string
+
+ }
+
+ }
+
+ return pattern
+ })
+
+ wmarkdown.modules = map[string]*WMDModule{
+ "special_characters": NewWMDModule(ModuleSpecialCharacters, WMD.SUBITEM, `\\([\(\{\[\*\\])`),
+ "title": NewWMDModule(wmarkdown.ModuleTitle, WMD.RAW, `(?m)^(?:(#{1,6})[\t ]*([^\r\n]+)|(={1,6})[\t ]*([^\r\n=]+)={1,6})(?:\n|\r\n|\r){2,}`),
+ "list": NewWMDModule(wmarkdown.ModuleList, WMD.RAW, `(?mi)^([\-\*#\+]+|([0-9]+|[a-z]+)\.)[^\r\n]*(\n|\r\n|\r)([\t ]*(([\-\*#\+]+|([0-9]+|[a-z]+)\.)[^\r\n]*)(\n|\r\n|\r)?)*`),
+ "code_block": NewWMDModule(wmarkdown.ModuleCodeBlock, WMD.RAW, `(?m)^(?:"{3}([^\r\n]*)((?:[^"]+|[\r\n]+|"{1,2}[^"])*)"{3}|" " "([^\r\n]*)((?:[^"]+|[\r\n]|"[^ ]|(" ){1,2}[^"])*)" " "|'{3}([^\r\n]*)((?:[^']+|[\r\n]+|'{1,2}[^'])*)'{3}|' ' '([^\r\n]*)((?:[^']+|[\r\n]|'[^ ]|(' ){1,2}[^'])*)' ' '|`+"`{3}([^\\r\\n]*)((?:[^`]+|[\\r\\n]+|`{1,2}[^`])*)`{3}|` ` `([^\\r\\n]*)((?:[^`]+|[\\r\\n]|`[^ ]|(` ){1,2}[^`])*)` ` `)"),
+ "table": NewWMDModule(wmarkdown.ModuleTable, WMD.RAW, `(?m)^\[\|([^\r\n]*)[\r\n]+((^\|([^\]]([^\r\n"\']|"([^"\\\\]+|\\\\(.|[\r\n])|[\r\n]+)*"|\'([^\'\\\\]+|\\\\(.|[\r\n])|[\r\n]+)*\')*)?[\r\n]+)*)^\|\]`),
+ "quote": NewWMDModule(wmarkdown.ModuleQuote, WMD.RAW, `(?m)^>[ \t]*(\[\![\t ]*([^\] \t]+)([ \t]+([^\]]+))?\])?(([^\r\n]+(\r\n|[\r\n])?)*)`),
+ "include": NewWMDModule(wmarkdown.ModuleInclude, WMD.RAW, `(?m)^\[{2}include[ \t]+([^\]]+)\]{2}`),
+ "media": NewWMDModule(wmarkdown.ModuleMedia, WMD.SUBITEM|WMD.LINKED, `(?i)\({2}\!(image|icon|video|audio|sound|picture)[ \t]+("(([^"]+|[\r\n]+))"|\'(([^\']+|[\r\n]+))\'|([^ \t\)]+))([ \t]*|[ \t]+("(([^\\\\"]+|\\\\.|[\r\n]+)*)"|\'(([^\\\\\']+|\\\\.|[\r\n]+)*)\'|([^\)]+)))\){2}`),
+ "code_doc": NewWMDModule(wmarkdown.ModuleCodeDoc, WMD.RAW, `(?m)^\[{2}@(([^\]]+|\][^\]])+)\]{2}`),
+ "presentation_links": NewWMDModule(ModulePresentationLinks, WMD.RAW, `(?m)^\[{2}"{3}(([^"]+|[\r\n]+|"{1,2}[^"])*)"{3}\]{2}`),
+ "code_sample_block": NewWMDModule(wmarkdown.ModuleCodeSampleBlock, WMD.RAW, code_sample_block_module_pattern),
+ "paragraph": NewWMDModule(wmarkdown.ModuleParagraph, WMD.RAW, `(?m)^(([^\r\n]+(\n|\r\n|\r)?)+)`),
+ "bold": NewWMDModule(wmarkdown.ModuleBold, WMD.SUBITEM|WMD.LINKED, NewWMDModulePattern([]string{`(^|[^\\])\*{2}((?:[^\*]+|[\n\r]+|\*[^\*])+\*?)\*{2}`}, BoldOrItalicModelMethod)),
+ "italic": NewWMDModule(wmarkdown.ModuleItalic, WMD.SUBITEM|WMD.LINKED, NewWMDModulePattern([]string{`(^|[^\\])\*((?:[^\*]+|[\r\n]+|\*{2})+(?:\*{2})?)\*`}, BoldOrItalicModelMethod)),
+ "underline": NewWMDModule(wmarkdown.ModuleUnderline, WMD.SUBITEM|WMD.LINKED, `__(([^_]+|_[^_])+)__`),
+ "strike": NewWMDModule(wmarkdown.ModuleStrike, WMD.SUBITEM|WMD.LINKED, `~~(([^~]+|~[^~])+)~~`),
+ "code_item": NewWMDModule(wmarkdown.ModuleCodeItem, WMD.SUBITEM|WMD.LINKED, "``(([^`]+|`[^`])+)``"),
+ "checkbox": NewWMDModule(ModuleCheckbox, WMD.SUBITEM|WMD.LINKED, `(?i)\[(?:(\-)|(x)|( ))\]`),
+ "radio": NewWMDModule(ModuleRadio, WMD.SUBITEM|WMD.LINKED, `(?i)\((?:(\-)|(x)|( ))\)`),
+ "tick": NewWMDModule(ModuleTick, WMD.SUBITEM|WMD.LINKED, `(?i)\{(?:(w)|(v)|(x))\}`),
+ "color_sample": NewWMDModule(ModuleColorSample, WMD.SUBITEM|WMD.LINKED, `(?i)\[{2}((\#[a-f0-9]{3,8})|color[ \t]+([^\[\]\t\r\n]+))\]{2}`),
+ "exclude": NewWMDModule(ModuleExclude, WMD.SUBITEM, `\[{2}\!(([^\]]+|\][^\]]|[\r\n])*)\]{2}`),
+ "link": NewWMDModule(wmarkdown.ModuleLink, WMD.SUBITEM, `(?i)(\[([^\[\]]+)\])?\((([^\(\) \t]+)[ \t]+("(([^\\\\"]+|\\\\.|[\r\n]+)*)"|\'(([^\\\\\']+|\\\\.|[\r\n]+)*)\'|([^\(\)]+)?))[ \t]*\)|\[(\+?[0-9 ]{5,22}|[^ \]]+)([\t ]+([^\]]*))?\]|([a-z0-9]{3,8}\:\/{2}[^ \(\[\)\]>]+|[a-z\.0-9_\-]+@[a-z\.0-9_\-]+\.[a-z0-9]+)`),
+ }
+
+ return wmarkdown
+}
+
+func (_self *WMarkDown) ModuleDefault(matches *PatternMatch, language int, path string) string {
+ return matches.Groups[0]
+}
+
+func (_self *WMarkDown) Id(_string string) string {
+
+ var id string = Patterns.Replace(_string, Patterns.RE_CHARACTERS_NO_ID, "-")
+
+ if id[0] == '-' {
+ id = id[1:]
+ } else if id[len(id)-1] == '-' {
+ id = id[:len(id)-1]
+ }
+
+ if slices.Contains(_self.ids_cache, id) {
+
+ var i int = 2
+
+ for ; slices.Contains(_self.ids_cache, id+"-"+strconv.FormatInt(int64(i), 10)); i++ {
+ }
+
+ id += "-" + strconv.FormatInt(int64(i), 10)
+
+ }
+ _self.ids_cache = append(_self.ids_cache, id)
+
+ return id
+}
+
+func (_self *WMarkDown) ResetIds() {
+ _self.ids_cache = []string{}
+}
+
+func (_self *WMarkDown) ModuleTitle(matches *PatternMatch, language int, path string) string {
+ if language&WMD.HTML != 0 {
+
+ var level string
+ var content string
+
+ if matches.Groups[1] != "" {
+ level = matches.Groups[1]
+ } else {
+ level = matches.Groups[3]
+ }
+ level = strconv.FormatInt(int64(len(level)), 10)
+
+ if matches.Groups[2] != "" {
+ content = strings.ToLower(matches.Groups[2])
+ } else {
+ content = strings.ToLower(matches.Groups[4])
+ }
+
+ return `` +
+ `` + _self.Analyse(content, language, WMD.SUBITEM, path) + `` +
+ ` `
+ }
+ return ""
+}
+
+func Trim(_string string) string {
+ return strings.Trim(_string, " \r\t\n")
+}
+
+func (_self *WMarkDown) ModuleParagraph(matches *PatternMatch, language int, path string) string {
+ if language&WMD.HTML != 0 {
+ return `` + _self.Analyse(Trim(matches.Groups[0]), language, WMD.SUBITEM, path) + `
`
+ }
+ return ""
+}
+
+func (_self *WMarkDown) ModuleBold(matches *PatternMatch, language int, path string) string {
+ if language&WMD.HTML != 0 {
+ return `` + _self.Analyse(matches.Groups[1], language, WMD.SUBITEM, path) + ``
+ }
+ return ""
+}
+
+func (_self *WMarkDown) ModuleItalic(matches *PatternMatch, language int, path string) string {
+ if language&WMD.HTML != 0 {
+ return `` + _self.Analyse(matches.Groups[1], language, WMD.SUBITEM, path) + ``
+ }
+ return ""
+}
+
+func (_self *WMarkDown) ModuleStrike(matches *PatternMatch, language int, path string) string {
+ if language&WMD.HTML != 0 {
+ return `` + _self.Analyse(matches.Groups[1], language, WMD.SUBITEM, path) + ``
+ }
+ return ""
+}
+
+func (_self *WMarkDown) ModuleUnderline(matches *PatternMatch, language int, path string) string {
+ if language&WMD.HTML != 0 {
+ return `` + _self.Analyse(matches.Groups[1], language, WMD.SUBITEM, path) + ``
+ }
+ return ""
+}
+
+func (_self *WMarkDown) ModuleCodeItem(matches *PatternMatch, language int, path string) string {
+ if language&WMD.HTML != 0 {
+ return `` + _self.Analyse(matches.Groups[1], language, WMD.SUBITEM, path) + `
`
+ }
+ return ""
+}
+
+func NewWMDListLevel(separator int, _type byte, subtype string) *WMDListLevel {
+ return &WMDListLevel{
+ separator: separator,
+ _type: _type,
+ subtype: subtype,
+ }
+}
+
+func list_deployed(level *WMDListLevel, last_mark string, l int) string {
+
+ var _type string = level.subtype
+ var deployable bool = l != 0 && strings.Contains("+-", _type)
+ var deployed string = "true"
+ var processed string = ""
+
+ if l != 0 && last_mark != "" {
+ _type = last_mark
+ }
+
+ if !deployable {
+ deployed = "null"
+ } else {
+ processed = ` data-list-unprocessed="true"`
+ if _type == "-" {
+ deployed = "false"
+ }
+ }
+
+ return ` data-deployed="` + deployed + `"` + processed
+}
+
+func list_start(unordered bool, _type string) string {
+ if !unordered {
+ _type = _type[:len(_type)-1]
+ if Patterns.Match(_type, Patterns.RE_INTEGER).Ok {
+ return ` start="` + _type + `"`
+ }
+ }
+ return ``
+}
+
+func (_self *WMarkDown) ModuleList(matches *PatternMatch, language int, path string) string {
+ if language&WMD.HTML != 0 {
+
+ var html string = ``
+ var levels []*WMDListLevel = []*WMDListLevel{NewWMDListLevel(0, 'u', "")}
+ var l int = 0
+ var last_mark string = ""
+ var subtype string = ""
+
+ for _, line := range Patterns.RE_NEW_LINE.Split(matches.Groups[0], -1) {
+
+ var matches *PatternMatch = Patterns.Match(line, Patterns.RE_LIST_LINE)
+
+ if !matches.Ok || matches.String == "" {
+ continue
+ }
+
+ var separator_by_marks int = len(matches.Groups[3])
+ var separator int = separator_by_marks
+ var _type string = matches.Groups[2]
+ var key string = matches.Groups[4]
+ var _string string = Trim(_self.Analyse(matches.Groups[5], language, WMD.SUBITEM, path))
+ var type_character byte = _type[len(_type)-1]
+ var unordered bool = _type != "" && slices.Contains(LIST_MARKS, type_character)
+
+ if separator_by_marks <= 1 {
+ separator = len(matches.Groups[1])
+ }
+
+ if !unordered {
+ levels[0]._type = 'o'
+ }
+
+ subtype = _type
+
+ if _type != "" {
+ if levels[l].separator == separator {
+ levels[l].subtype = subtype
+ if html != "" {
+ html += ``
+ } else {
+ html += `<` + string(levels[l]._type) + `l class="wmd-list"` + list_start(unordered, _type) + list_deployed(levels[l], last_mark, l)
+ if key != "" && !unordered && slices.Contains(LIST_LATIN_MARKS, key[0]) {
+ html += ` type="` + string(key[0]) + `"`
+ }
+ html += `>`
+ }
+ html += `` + _string
+ } else if levels[l].separator < separator {
+
+ var child_type byte = 'u'
+
+ if unordered {
+ child_type = 'o'
+ }
+
+ l++
+ levels = append(levels, NewWMDListLevel(separator, child_type, subtype))
+ html += `<` + string(levels[l]._type) + `l class="wmd-list"` + list_start(unordered, _type) + list_deployed(levels[l-1], last_mark, l)
+ if key != "" && !unordered && slices.Contains(LIST_LATIN_MARKS, key[0]) {
+ html += ` type="` + string(key[0]) + `"`
+ }
+ html += `> ` + _string
+
+ } else {
+ for levels[l].separator > separator {
+ html += ` ` + string(levels[l]._type) + `l>`
+ levels = levels[:l]
+ l--
+ if l == 0 {
+ break
+ }
+ }
+ html += `` + _string
+ }
+ } else {
+ html += ` ` + _string
+ }
+
+ last_mark = subtype
+
+ }
+
+ for l >= 0 {
+ html += ` ` + string(levels[l]._type) + `l>`
+ levels = levels[:l]
+ l--
+ }
+
+ return html
+ }
+ return ""
+}
+
+func (_self *WMarkDown) ModuleTable(matches *PatternMatch, language int, path string) string {
+ if language&WMD.HTML != 0 {
+
+ var html map[string]string = map[string]string{
+ "thead": ``,
+ "tbody": ``,
+ "tfoot": ``,
+ }
+ var attributes string = Trim(matches.Groups[1])
+ var data string = Trim(matches.Groups[2])
+
+ for {
+
+ var line_matches *PatternMatch = Patterns.Match(data, Patterns.RE_TABLE_LINE)
+
+ if !line_matches.Ok || line_matches.Groups[0] == "" {
+ break
+ }
+
+ var line string = line_matches.Groups[0]
+ var cell_type string = "d"
+ var tags []string
+ var row string = ``
+
+ if slices.Contains(TABLE_MARKS, line[1]) {
+ cell_type = "h"
+ switch line[1] {
+ case '^':
+ tags = []string{"thead"}
+ case '_':
+ tags = []string{"tfoot"}
+ case '=':
+ tags = []string{"thead", "tfoot"}
+ }
+ } else {
+ tags = []string{"tbody"}
+ }
+
+ if cell_type == "h" {
+ line = line[:1] + line[2:]
+ }
+
+ for {
+
+ var cell_matches *PatternMatch = Patterns.Match(line, Patterns.RE_TABLE_ITEM)
+
+ if !cell_matches.Ok || cell_matches.Groups[0] == "" {
+ break
+ }
+
+ var column_span_i int = len(cell_matches.Groups[1])
+ var column_span string = ``
+ var content string = Trim(cell_matches.Groups[2])
+
+ if column_span_i > 1 {
+ column_span = ` colspan="` + strconv.FormatInt(int64(column_span_i), 10) + `"`
+ }
+
+ if len(content) > 1 && slices.Contains([]string{`''`, `""`}, content[:1]+content[len(content)-1:]) {
+ content = content[1 : len(content)-1]
+ }
+
+ row += `` + _self.Analyse(content, WMD.HTML, WMD.SUBITEM, path) + ` `
+ line = line[cell_matches.Span[1]:]
+
+ }
+
+ row += ` `
+
+ for i, tag := range tags {
+ if i == 0 {
+ html[tag] = row + html[tag]
+ } else {
+ html[tag] += row
+ }
+ }
+
+ data = data[line_matches.Span[1]:]
+
+ }
+
+ return `` +
+ `` +
+ `` + html["thead"] + `` +
+ `` + html["tbody"] + `` +
+ `` + html["tfoot"] + `` +
+ `
` +
+ ``
+ }
+ return ""
+}
+
+func (_self *WMarkDown) ModuleLink(matches *PatternMatch, language int, path string) string {
+ if language&WMD.HTML != 0 {
+
+ var raw_url string = Trim(matches.GetByGroup([]int{4, 11, 14}, ""))
+ var url string = raw_url
+ var text string = Trim(matches.GetByGroup([]int{2, 13}, raw_url))
+ var protocol_matches *PatternMatch = Patterns.Match(url, Patterns.RE_PROTOCOL)
+ var html string
+
+ if Patterns.Match(raw_url, Patterns.RE_PHONE_NUMBER).Ok {
+ url = "tel:" + strings.ReplaceAll(raw_url, " ", "")
+ } else if Patterns.Match(raw_url, Patterns.RE_EMAIL_ADDRESS).Ok {
+ url = "mailto:" + raw_url
+ }
+
+ html += `` + _self.Analyse(text, language, WMD.SUBITEM|WMD.LINKED, path) + ``
+ }
+ return ""
+}
+
+func (_self *WMarkDown) ModuleQuote(matches *PatternMatch, language int, path string) string {
+ if language&WMD.HTML != 0 {
+
+ var _type string = matches.Groups[2]
+ var type_text string = matches.Groups[4]
+ var html string
+
+ if value, ok := WMD.quote_special[_type]; ok {
+ _type = value
+ }
+
+ html = `` +
+ ``
+ if _type[0] == '@' {
+ html += `` +
+ `` + strings.ToLower(_type[1:]) + ``
+ } else {
+ html += ``
+ if type_text != "" {
+ html += `` + type_text + ``
+ }
+ }
+ html += ``
+ } else {
+ html += `>`
+ }
+
+ return html + `` + _self.Analyse(matches.Groups[5], language, WMD.SUBITEM, path) + `` +
+ `
`
+ }
+ return ""
+}
+
+func code_block_data(key string, value string, language int) string {
+ if language&WMD.HTML != 0 {
+ return `` +
+ `` +
+ `` + key + `` +
+ `` + value + `` +
+ ` `
+ }
+ return ""
+}
+
+func FilterHTMLSpecialCharacters(_string string) string {
+
+ var l int = len(WMD.html_special_characters)
+ var z int = -(1 << 28)
+ var index []int = []int{}
+ var response string = ``
+ var characters []string = slices.Collect(maps.Keys(WMD.html_special_characters))
+
+ for j := 0; j < l; j++ {
+ index = append(index, -1)
+ }
+
+ for {
+
+ var i int = -1
+
+ for j, character := range characters {
+ if index[j] < z {
+ continue
+ }
+
+ if index[j] < 0 {
+ index[j] = strings.Index(_string, character)
+ if index[j] == -1 {
+ index[j] = z
+ continue
+ }
+ }
+
+ if i == -1 || index[i] > index[j] {
+ i = j
+ }
+
+ }
+
+ if i == -1 {
+ response += _string
+ break
+ }
+
+ var length int = index[i]
+
+ response += _string[:length] + "&" + WMD.html_special_characters[characters[i]] + ";"
+ _string = _string[length+1:]
+
+ for j := 0; j < l; j++ {
+ if index[j] != z {
+ index[j] -= length + 1
+ }
+ }
+
+ }
+
+ return response
+}
+
+func GetCodeBlockData(matches *PatternMatch) (string, string) {
+
+ var _type string
+ var content string
+
+ for i := 0; i < 6; i++ {
+
+ var j int = 1 + i*2
+
+ _type = matches.Groups[j]
+ content = matches.Groups[j+1]
+ if _type != "" || content != "" {
+ if _type != "" {
+ _type = strings.ToLower(_type)
+ } else {
+ _type = "unamed"
+ }
+ break
+ }
+ }
+
+ return _type, content
+}
+
+func (_self *WMarkDown) ModuleCodeBlock(matches *PatternMatch, language int, path string) string {
+ if language&WMD.HTML != 0 {
+
+ _type, content := GetCodeBlockData(matches)
+
+ if _type != "" {
+
+ var lines []string = Patterns.RE_NEW_LINE.Split(content, -1)[2:]
+ var html string = `` +
+ `` +
+ ` ` +
+ code_block_data("type", _type, language) +
+ code_block_data("characters", strconv.FormatInt(int64(len(content)), 10), language) +
+ code_block_data("lines", strconv.FormatInt(int64(len(lines)), 10), language) +
+ `
` +
+ `` +
+ ``
+
+ for range lines {
+ html += ``
+ }
+ html += `` + FilterHTMLSpecialCharacters(content) + `
` +
+ `
` +
+ ``
+
+ return html
+ }
+ return "UNKNOWN_BLOCK"
+ }
+ return ""
+}
+
+func (_self *WMarkDown) ModuleInclude(matches *PatternMatch, language int, path string) string {
+ if language&WMD.HTML != 0 {
+
+ var relative_path string = matches.Groups[1]
+ var directory_origin string = GetDirectory(path)
+ var new_path string = directory_origin + "/" + relative_path
+ var extension []string = Patterns.Match(new_path, Patterns.RE_EXTENSION).Groups[1:]
+ var directory string = GetDirectory(new_path)
+ var content string = LoadFile(new_path)
+ var results string = content
+ var included string = "false"
+
+ if content != "" {
+ if strings.Join(extension, ".") == "w.md" {
+ results, _ = _self.Process(content, language, directory)
+ } else if extension[len(extension)-1] == "md" {
+ results = _self.Analyse(content, language, WMD.RAW, directory)
+ }
+ }
+
+ if PathExists(new_path) {
+ included = "true"
+ }
+
+ return `` +
+ `` +
+ results +
+ ` `
+ }
+ return ""
+}
+
+func (_self *WMarkDown) ModuleMedia(matches *PatternMatch, language int, path string) string {
+ if language&WMD.HTML != 0 {
+
+ var _type string = strings.ToLower(matches.Groups[1])
+ var links []string = Patterns.RE_WHITE_SPACES.Split(matches.GetByGroup([]int{3, 5, 7}, ""), -1)
+ var text string = Trim(matches.GetByGroup([]int{10, 12, 14}, ""))
+
+ if slices.Contains([]string{"image", "picture", "icon"}, _type) {
+ return BuildHTMLImage(links, _type, text)
+ }
+
+ if slices.Contains([]string{"video"}, _type) {
+
+ var html string
+
+ if strings.Contains(links[0], "youtube.com") || strings.Contains(links[0], "youtu.be") {
+ _type = "youtube"
+ } else if strings.Contains(links[0], "vimeo.com") {
+ _type = "vimeo"
+ }
+
+ html = `` +
+ ``
+
+ switch _type {
+ case "youtube":
+ html += `YOUTUBE`
+ case "vimeo":
+ html += `VIMEO`
+ default:
+
+ var poster string = ""
+
+ if len(links) > 1 {
+ poster = ` poster="` + links[1] + `"`
+ }
+
+ html += ``
+ }
+
+ return html + ``
+ }
+
+ if slices.Contains([]string{"sound", "audio"}, _type) {
+
+ var html string
+
+ if strings.Contains(links[0], "soundcloud.com") {
+ _type = "soundcloud"
+ }
+
+ html = `` +
+ ``
+
+ switch _type {
+ case "soundcloud":
+ html += `SOUNDCLOUD`
+ default:
+ html += ``
+ }
+
+ return html + ``
+ }
+ return ""
+ }
+ return ""
+}
+
+func MarkReplace(_string string, matches *PatternMatch, fragments *[]string) string {
+
+ if matches.Ok {
+
+ _string = _string[:matches.Span[0]] + WMD.item_mark.from + strconv.FormatInt(int64(len(*fragments)), 10) + WMD.item_mark.to + _string[matches.Span[1]:]
+ *fragments = append(*fragments, matches.Groups[0])
+ }
+
+ return _string
+}
+
+func RestoreMarks(_string string, fragments *[]string) string {
+
+ var l int = len(*fragments)
+
+ for {
+
+ var matches *PatternMatch = Patterns.Match(_string, WMD.item_mark.pattern)
+
+ if !matches.Ok {
+ break
+ }
+
+ power_i, _ := strconv.ParseInt(matches.Groups[1], 10, 32)
+ var i int = int(power_i)
+ var subdata string = ""
+
+ if i < l {
+ subdata = (*fragments)[i]
+ }
+
+ _string = _string[:matches.Span[0]] + subdata + _string[matches.Span[1]:]
+
+ }
+
+ return _string
+}
+
+func doc_type_format(typed string) string {
+ return FilterHTMLSpecialCharacters(strings.ReplaceAll(strings.ReplaceAll(typed, " ", ""), ",", ", "))
+}
+
+func IsReference(scope string) string {
+ if strings.Contains(scope, "&") {
+ return "reference"
+ }
+ if strings.Contains(scope, "*") {
+ return "pointer"
+ }
+ return ""
+}
+
+func (_self *WMarkDown) ModuleCodeDoc(matches *PatternMatch, language int, path string) string {
+ if language&WMD.HTML != 0 {
+
+ var data string = Trim(matches.Groups[1])
+ var base PatternMatch = *Patterns.Match(data, Patterns.RE_CODE_DOC)
+ var return_type string = doc_type_format(base.GetByGroup([]int{2}, "void"))
+ var access string = base.GetByGroup([]int{3}, "public")
+ var constant string = ""
+ var reference string = IsReference(access)
+ var name_space string = base.Groups[5]
+ var environment string = base.GetByGroup([]int{6}, "global")
+ var parameters string = base.Groups[9]
+ var has_parameters bool = parameters != ""
+ var default_value string = base.Groups[11]
+ var full_method string = ""
+ var arguments string = ""
+ var arguments_definition string = ""
+ var header string = `` +
+ `Name ` +
+ `Required ` +
+ `Nullable ` +
+ `Typed ` +
+ `Default value ` +
+ ` `
+ var fragments *[]string = &[]string{}
+ var arguments_l int = 0
+
+ if name_space != "" {
+ full_method = name_space + "."
+ }
+ full_method += Trim(base.Groups[7])
+
+ if strings.Contains(access, "=") {
+ constant = "constant"
+ }
+ if strings.Contains(access, "?") {
+ access = "protected"
+ } else if strings.Contains(access, "!") {
+ access = "private"
+ } else {
+ access = "global"
+ }
+
+ switch environment {
+ case ":":
+ environment = "static"
+ case ".":
+ environment = "object"
+ }
+
+ if has_parameters {
+ for {
+
+ var matches *PatternMatch = Patterns.Match(parameters, Patterns.RE_CODE_DOC_SUBARGUMENTS)
+
+ if !matches.Ok {
+ break
+ }
+ parameters = MarkReplace(parameters, matches, fragments)
+
+ }
+ }
+
+ for parameter := range strings.SplitSeq(parameters, ",") {
+
+ var matches *PatternMatch = Patterns.Match(Trim(parameter), Patterns.RE_CODE_DOC_ARGUMENTS)
+
+ if matches.Ok {
+
+ var scopes string = matches.Groups[1]
+ var required bool = strings.Contains(scopes, "!")
+ var nullish bool = strings.Contains(scopes, "?")
+ var subreference string = IsReference(access)
+ var typed string = doc_type_format(RestoreMarks(matches.Groups[2], fragments))
+ var name string = Trim(matches.Groups[3])
+ var default_value string = FilterHTMLSpecialCharacters(RestoreMarks(Trim(matches.Groups[5]), fragments))
+
+ arguments += ``
+ if required {
+ arguments += `Required`
+ }
+ if nullish {
+ arguments += `Nullish`
+ }
+ if subreference != "" {
+ arguments += `` + subreference + ``
+ }
+ arguments += `` + typed + `` +
+ `` + name + ``
+ if default_value != "" {
+ arguments += `` + default_value + ``
+ }
+ arguments += ``
+
+ arguments_definition += `` +
+ `` + name + ` ` +
+ ``
+ if required {
+ arguments_definition += `True`
+ } else {
+ arguments_definition += `False`
+ }
+ arguments_definition += ` ` +
+ ``
+ if nullish {
+ arguments_definition += `True`
+ } else {
+ arguments_definition += `False`
+ }
+ arguments_definition += ` ` +
+ `` + typed + ` ` +
+ `` + default_value + ` ` +
+ ` `
+
+ arguments_l++
+
+ }
+
+ }
+
+ var html string = ``
+ }
+ return ""
+}
+
+func (_self *WMarkDown) ModuleCodeSampleBlock(matches *PatternMatch, language int, path string) string {
+ if language&WMD.HTML != 0 {
+
+ var attributes string = matches.Groups[1]
+ var submatches *PatternMatch = Patterns.Match(attributes, Patterns.RE_CLASS_ATTRIBUTE)
+ var classes []string = []string{}
+ var content string = matches.Groups[2]
+ var languages string = ``
+ var html string = ``
+ var i int = 0
+
+ if submatches.Ok {
+ classes = Patterns.RE_WHITE_SPACES.Split(Trim(submatches.Groups[1]), -1)
+ }
+
+ for {
+
+ var submatches *PatternMatch = Patterns.Match(content, _self.modules["code_block"].patterns[0])
+
+ if !submatches.Ok {
+ break
+ }
+
+ _type, _ := GetCodeBlockData(submatches)
+
+ languages += `` + _type + ` `
+ html += _self.ModuleCodeBlock(submatches, language, path)
+
+ content = content[submatches.Span[1]:]
+
+ }
+
+ if len(classes) == 0 {
+ classes = append(classes, "wmd-code-sample-block")
+ }
+
+ return `` +
+ `` +
+ `` + html + `` +
+ ``
+ }
+ return ""
+}
+
+func WMDRemoveDefaultTabulations(data string) string {
+
+ var spaces int = len(data)
+
+ for _, line := range Patterns.RE_NEW_LINES.Split(data, -1) {
+ if line == "" {
+ continue
+ }
+
+ var white_spaces int = len(Patterns.Match(line, Patterns.RE_STARTED_WHITE_SPACES).Groups[0])
+
+ if white_spaces < spaces {
+ spaces = white_spaces
+ }
+
+ }
+
+ return Patterns.Replace(data, Patterns.RE_LINES, func(matches *PatternMatch) string {
+ return matches.Groups[0][spaces:]
+ })
+}
+
+func (_self WMarkDown) build(data string, language int, path string) string {
+ if language&WMD.HTML != 0 {
+ return `` +
+ _self.Analyse(WMDRemoveDefaultTabulations(data), language, WMD.RAW, path) +
+ `` +
+ ``
+ }
+ return ""
+}
+
+func (_self *WMarkDown) Process(data string, language int, path string) (string, map[string]string) {
+
+ var results string = ""
+ var variables map[string]string = map[string]string{}
+ var options *PatternMatch = Patterns.Match(data, Patterns.RE_OPTIONS)
+
+ if options.Ok {
+
+ var options_data string = options.Groups[1]
+
+ for {
+
+ var option *PatternMatch = Patterns.Match(options_data, Patterns.RE_OPTION)
+
+ if !option.Ok {
+ break
+ }
+
+ variables[Trim(option.Groups[1])] = Trim(option.Groups[2])
+ options_data = options_data[option.Span[1]:]
+
+ }
+
+ data = data[:options.Span[0]] + data[options.Span[1]:]
+
+ }
+
+ for {
+
+ var matches *PatternMatch = Patterns.Match(data, Patterns.RE_BLOCK_MARK)
+
+ if !matches.Ok {
+ results += data
+ break
+ }
+
+ var mark string = matches.Groups[1]
+ var RE_CLOSE *regexp.Regexp = Patterns.RE_BLOCK_MARK
+
+ if mark != "" {
+ RE_CLOSE = regexp.MustCompile(`(?m)^\s*` + mark)
+ }
+
+ results += data[:matches.Span[0]]
+ data = data[matches.Span[1]:]
+
+ var close_matches *PatternMatch = Patterns.Match(data, RE_CLOSE)
+
+ if close_matches.Ok {
+ results += _self.build(data[:close_matches.Span[0]], language, path)
+ data = data[close_matches.Span[1]:]
+ } else {
+ results += _self.build(data, language, path)
+ break
+ }
+
+ }
+
+ return results, variables
+}
+
+func (_self *WMarkDown) Analyse(data string, language int, mode int, path string) string {
+
+ var response string = ""
+ var items map[string]*WMDAnalyseItem = map[string]*WMDAnalyseItem{}
+ var current_keys []string = []string{}
+
+ for _, key := range _self.keys {
+ if mode == WMD.RAW || mode|_self.modules[key].mode == _self.modules[key].mode {
+ items[key] = &WMDAnalyseItem{
+ exists: true,
+ from: -1,
+ to: -1,
+ matches: &PatternMatch{
+ Ok: false,
+ String: "",
+ Groups: []string{},
+ Span: []int{-1, -1},
+ },
+ }
+ current_keys = append(current_keys, key)
+ }
+ }
+
+ for {
+
+ var l int = len(data)
+ var selected string = ""
+
+ for _, key := range current_keys {
+ if !items[key].exists {
+ continue
+ }
+
+ var module WMDModule = *_self.modules[key]
+
+ if items[key].from < 0 {
+ items[key].matches = module.pattern_method(data, module.patterns)
+ if items[key].matches.Ok {
+ items[key].from = items[key].matches.Span[0]
+ items[key].to = items[key].matches.Span[1]
+ } else {
+ items[key].exists = false
+ continue
+ }
+ }
+
+ if items[key].from < l {
+ l = items[key].from
+ selected = key
+ }
+
+ }
+
+ if selected == "" {
+ response += data
+ break
+ }
+
+ var to int = items[selected].to
+
+ response += data[:items[selected].from] + _self.modules[selected].method(items[selected].matches, language, path)
+ data = data[to:]
+
+ for _, item := range items {
+ if item.matches.Ok {
+ item.from -= to
+ item.to -= to
+ }
+ }
+
+ }
+
+ return response
+}
+
+type DebugStackLineModel struct {
+ Line int
+ Method string
+ File string
+}
+
+func (_self *WMarkDown) ToHTML(data string, path string) string {
+ return _self.Analyse(data, WMD.HTML, WMD.RAW, path)
+}
diff --git a/version b/version
index 9676eb0..30ac009 100644
--- a/version
+++ b/version
@@ -1 +1 @@
-0.0.3.7
\ No newline at end of file
+0.0.3.8
\ No newline at end of file