clearing the number line
This commit is contained in:
parent
e3ff2331ad
commit
60821677af
181
markdown.rb
181
markdown.rb
|
@ -1,92 +1,187 @@
|
||||||
## Filter-based Markdown translator.
|
## Filter-based Markdown translator.
|
||||||
|
#
|
||||||
module Markdown
|
module Markdown
|
||||||
## Translator for linear tags in Markdown.
|
## Superclass that defines behaviour of all translators
|
||||||
# A linear tag is any tag that starts anywhere on the line, and closes on the same exact line.
|
# @abstract Don't use directly - it only defins the ability to chain translators
|
||||||
class LinearTagTranslator
|
class AbstractTranslator
|
||||||
def initialize(text)
|
attr_accessor :input
|
||||||
@input = text
|
attr_accessor :output
|
||||||
|
def initialize()
|
||||||
|
@chain = []
|
||||||
end
|
end
|
||||||
def escape(text)
|
def +(nextTranslator)
|
||||||
text.sub /([*`~_!\[])/,"\\\1"
|
@chain.append nextTranslator
|
||||||
|
return self
|
||||||
end
|
end
|
||||||
def to_html
|
def to_html
|
||||||
@input
|
output = @output
|
||||||
|
@chain.each { |x|
|
||||||
|
x = x.new(output) if x.class == Class
|
||||||
|
x.to_html
|
||||||
|
output = x.output
|
||||||
|
}
|
||||||
|
return output
|
||||||
|
end
|
||||||
|
end
|
||||||
|
module_function
|
||||||
|
def html_highlighter; @html_highlighter end
|
||||||
|
def html_highlighter= v; @html_highlighter = v end
|
||||||
|
## Translator for linear tags in Markdown.
|
||||||
|
# A linear tag is any tag that starts anywhere on the line, and closes on the same exact line.
|
||||||
|
class LinearTagTranslator < AbstractTranslator
|
||||||
|
def initialize(text)
|
||||||
|
@input = text
|
||||||
|
@output = text
|
||||||
|
super()
|
||||||
|
end
|
||||||
|
def to_html
|
||||||
|
@output = @input
|
||||||
# Newline
|
# Newline
|
||||||
.sub /\s{2}[\n\r]/,"<br/>"
|
.sub(/\s{2}[\n\r]/,"<br/>")
|
||||||
# Inline code (discord style)
|
# Inline code (discord style)
|
||||||
.sub /(?<!\\)``(.*?[^\\])``/, { |code|
|
.gsub(/(?<!\\)``(.*?[^\\])``/) {
|
||||||
"<code>#{self.escape code}</code>"
|
code = Regexp.last_match[1]
|
||||||
|
"<code>#{code.gsub /[*`~_!\[]/,"\\\\\\0"}</code>"
|
||||||
}
|
}
|
||||||
# Inline code (Markdown style)
|
# Inline code (Markdown style)
|
||||||
.sub /(?<!\\)`(.*?[^\\])`/, { |code|
|
.gsub(/(?<!\\)`(.*?[^\\])`/) {
|
||||||
"<code>#{self.escape code}</code>"
|
code = Regexp.last_match[1]
|
||||||
|
"<code>#{code.gsub /[*`~_!\[]/,"\\\\\\0"}</code>"
|
||||||
}
|
}
|
||||||
# Bold-italics
|
# Bold-italics
|
||||||
.sub /(?<!\\)\*\*\*(.*?[^\\])\*\*\*/,"<i><b>\1</b></i>"
|
.gsub(/(?<!\\)\*\*\*(.*?[^\\])\*\*\*/,"<i><b>\\1</b></i>")
|
||||||
# Bold
|
# Bold
|
||||||
.sub /(?<!\\)\*\*(.*?[^\\])\*\*/,"<b>\1</b>"
|
.gsub(/(?<!\\)\*\*(.*?[^\\])\*\*/,"<b>\\1</b>")
|
||||||
# Italics
|
# Italics
|
||||||
.sub /(?<!\\)\*(.*?[^\\])\*/,"<i>\1</i>"
|
.gsub(/(?<!\\)\*(.*?[^\\])\*/,"<i>\\1</i>")
|
||||||
# Strikethrough
|
# Strikethrough
|
||||||
.sub /(?<!\\)~~(.*?[^\\])~~/,"<s>\1</s>"
|
.gsub(/(?<!\\)~~(.*?[^\\])~~/,"<s>\\1</s>")
|
||||||
# Underline
|
# Underline
|
||||||
.sub /(?<!\\)__(.*?[^\\])__/,"<span style=\"text-decoration: underline\">\1</span>"
|
.gsub(/(?<!\\)__(.*?[^\\])__/,"<span style=\"text-decoration: underline\">\\1</span>")
|
||||||
# Image
|
# Image
|
||||||
.sub /(?<!\\)!\[(.*)\]\((.*)\)/,"<img src=\"\2\" alt=\"\1\" />"
|
.gsub(/(?<!\\)!\[(.*)\]\((.*)\)/,"<img src=\"\\2\" alt=\"\\1\" />")
|
||||||
# Link
|
# Link
|
||||||
.sub /(?<!\\)\[(.*)\]\((.*)\)/,"<a href=\"\2\">\1</a>"
|
.gsub(/(?<!\\)\[(.*)\]\((.*)\)/,"<a href=\"\\2\">\\1</a>")
|
||||||
|
super
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
## Translator for linear leftmost tags.
|
## Translator for linear leftmost tags.
|
||||||
# Leftmost linear tags open on the leftmost end of the string, and close once the line ends. These tags do not need to be explicitly closed.
|
# Leftmost linear tags open on the leftmost end of the string, and close once the line ends. These tags do not need to be explicitly closed.
|
||||||
class LeftmostTagTranslator
|
class LeftmostTagTranslator < AbstractTranslator
|
||||||
def initalize(text)
|
def initialize(text)
|
||||||
@input = text
|
@input = text
|
||||||
|
@output = text
|
||||||
|
super()
|
||||||
end
|
end
|
||||||
def to_html
|
def to_html
|
||||||
# Headers
|
# Headers
|
||||||
@input.sub(/(?<!\\)(\#{1,4})([^\n\r]*)/) { |level,content|
|
@output = @input.split("\n").map do |x|
|
||||||
|
x.gsub(/^(?<!\\)(\#{1,4})([^\n\r]*)/) {
|
||||||
|
level,content = Regexp.last_match[1..2]
|
||||||
"<h#{level.length}>"+content+"</h#{level.length}>"
|
"<h#{level.length}>"+content+"</h#{level.length}>"
|
||||||
}
|
}
|
||||||
|
end.join("\n")
|
||||||
|
super
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
## Translator for code blocks in Markdown.
|
## Translator for code blocks in markdown
|
||||||
# First in terms of precedence.
|
# Code blocks can have syntax highlighting. This class implements an attribute for providing a syntax highlighter, one handler per requested output.
|
||||||
class CodeBlocksTranslator
|
class CodeBlockTranslator < AbstractTranslator
|
||||||
def initialize(text
|
def initialize(text)
|
||||||
|
@input = text
|
||||||
|
@output = text
|
||||||
|
super()
|
||||||
|
end
|
||||||
|
def to_html
|
||||||
|
@output = @input.gsub(/(?<=\n)(?<!\\)```([\w_-]*)(.*?)```/) {
|
||||||
|
language,code = Regexp.last_match[1..2]
|
||||||
|
code = Markdown::html_highlighter.call(language,code)
|
||||||
|
"<code>#{code}</code>"
|
||||||
|
}
|
||||||
|
super()
|
||||||
|
end
|
||||||
end
|
end
|
||||||
## Translator for quotes in Markdown.
|
## Translator for quotes in Markdown.
|
||||||
# These deserve their own place in hell.
|
# These deserve their own place in hell. As if the "yaml with triangle brackets instead of spaces" syntax wasn't horrible enough, each quote is its own markdown context.
|
||||||
class QuoteTranslator
|
class QuoteTranslator < AbstractTranslator
|
||||||
def initialize(text, level: 0)
|
def initialize(text)
|
||||||
if text.is_a? Array then
|
if text.is_a? Array then
|
||||||
@lines = text
|
@lines = text
|
||||||
elsif text.is_a? String then
|
elsif text.is_a? String then
|
||||||
@lines = text.split("\n\n")
|
@lines = text.split("\n")
|
||||||
end
|
end
|
||||||
|
@output = text
|
||||||
|
super()
|
||||||
|
end
|
||||||
|
def input= (v)
|
||||||
|
@lines = v.split("\n")
|
||||||
|
@output = v
|
||||||
|
end
|
||||||
|
def input
|
||||||
|
@lines.join("\n")
|
||||||
end
|
end
|
||||||
def to_html
|
def to_html
|
||||||
stack = []
|
stack = []
|
||||||
range = []
|
range = []
|
||||||
state = false
|
|
||||||
@lines.each_with_index { |x,index|
|
@lines.each_with_index { |x,index|
|
||||||
if x.match(/^\s{0,1}>/) and state == false then
|
if x.match /^\s*> ?/ then
|
||||||
range.append index
|
range[0] = index if not range[0]
|
||||||
state = true
|
range[1] = index
|
||||||
end
|
else
|
||||||
if (not x.match /^\s{0,1}>/) and state == true then
|
stack.append(range[0]..range[1]) if range[0] and range[1]
|
||||||
range.append index-1
|
|
||||||
state = false
|
|
||||||
stack.append(range[0]..range[1])
|
|
||||||
range = []
|
range = []
|
||||||
end
|
end
|
||||||
}
|
}
|
||||||
range.each { |r|
|
stack.append(range[0]..range[1]) if range[0] and range[1]
|
||||||
|
stack.reverse.each { |r|
|
||||||
|
@lines[r.begin] = "<blockquote>\n"+@lines[r.begin]
|
||||||
|
@lines[r.end] = @lines[r.end]+"\n</blockquote>"
|
||||||
|
@lines[r] = @lines[r].map { |line|
|
||||||
|
line.sub /^(\s*)> ?/,"\\1 "
|
||||||
|
}
|
||||||
@lines[r] = QuoteTranslator.new(@lines[r]).to_html
|
@lines[r] = QuoteTranslator.new(@lines[r]).to_html
|
||||||
}
|
}
|
||||||
@lines = @lines.map { |x|
|
@output = @lines.join("\n")
|
||||||
(x.sub /^\s{0,1}>/,"")
|
super
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
## Table parser
|
||||||
|
# translates tables from a format in markdown to an html table
|
||||||
|
class TableTranslator < AbstractTranslator
|
||||||
|
def initialize(text)
|
||||||
|
@input = text
|
||||||
|
@output = text
|
||||||
|
super()
|
||||||
|
end
|
||||||
|
def to_html
|
||||||
|
lines = @output.split("\n")
|
||||||
|
table_testline = -1
|
||||||
|
table_start = -1
|
||||||
|
table_column_count = 0
|
||||||
|
tables = []
|
||||||
|
cur_table = []
|
||||||
|
lines.each_with_index { |line,index|
|
||||||
|
if (line.start_with? / *\|/) and (line.match /^ *\|.*\|/) then
|
||||||
|
table_start = index
|
||||||
|
table_column_count = line.count "|"
|
||||||
|
cur_table.push (line.split "|")
|
||||||
|
end
|
||||||
|
if (table_start != -1) and (line.match /^ *\|([^\|]*\|){#{table_column_count-1}}$/) then
|
||||||
|
if (table_testline == -1) then
|
||||||
|
if (line.match /^ *\|(\-*\|){#{table_column_count-1}}$/) then
|
||||||
|
table_testline = 1
|
||||||
|
else
|
||||||
|
table_start = -1
|
||||||
|
cur_table = []
|
||||||
|
end
|
||||||
|
else
|
||||||
|
cur_table.push (line.split "|")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
puts cur_table
|
||||||
}
|
}
|
||||||
|
super()
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
95
test.rb
95
test.rb
|
@ -1,7 +1,92 @@
|
||||||
require "minitest"
|
require_relative "markdown"
|
||||||
require "markdown"
|
puts Markdown::LinearTagTranslator.new(<<CODE
|
||||||
class LinearParsingTest << Minitest::Test
|
*Italics*
|
||||||
def setup
|
**Bold**
|
||||||
@lparser =
|
***Bolitalics***
|
||||||
|
__underline__
|
||||||
|
__underline plus ***bolitalics***__
|
||||||
|
___invalid underline___
|
||||||
|
~~strikethrough ~~
|
||||||
|
`code that ignores ***all*** __Markdown__ [tags](https://nevergonnagiveyouup)`
|
||||||
|
me: google en passant
|
||||||
|
them: [holy hell!](https://google.com/q?=en+passant)
|
||||||
|
CODE
|
||||||
|
).to_html
|
||||||
|
puts Markdown::LeftmostTagTranslator.new(<<CODE
|
||||||
|
# Header v1
|
||||||
|
## Header v2
|
||||||
|
### Header v3
|
||||||
|
#### Header v4
|
||||||
|
##### Invalid header
|
||||||
|
#### Not a header
|
||||||
|
*** Also #### Not a header ***
|
||||||
|
CODE
|
||||||
|
).to_html
|
||||||
|
puts Markdown::QuoteTranslator.new(<<CODE
|
||||||
|
> Quote begins
|
||||||
|
>
|
||||||
|
> yea
|
||||||
|
> # header btw
|
||||||
|
> > nextlevel quote
|
||||||
|
> > more quote
|
||||||
|
> > those are quotes
|
||||||
|
> > yes
|
||||||
|
> > > third level quote
|
||||||
|
> > > yes
|
||||||
|
> > second level again
|
||||||
|
> > > third level again
|
||||||
|
> > second level oioioi
|
||||||
|
> >
|
||||||
|
> > > third
|
||||||
|
> > >
|
||||||
|
> > >
|
||||||
|
> > >
|
||||||
|
>
|
||||||
|
>
|
||||||
|
>
|
||||||
|
> fin
|
||||||
|
CODE
|
||||||
|
).to_html
|
||||||
|
|
||||||
|
puts Markdown::CodeBlockTranslator.new(<<CODE
|
||||||
|
```markdown
|
||||||
|
shmarkshmark
|
||||||
|
# pee pee
|
||||||
|
# piss
|
||||||
|
**ass**
|
||||||
|
__cock__
|
||||||
|
cock__
|
||||||
|
piss__
|
||||||
|
`shmark shmark`
|
||||||
|
```
|
||||||
|
CODE
|
||||||
|
).to_html
|
||||||
|
|
||||||
|
puts (Markdown::QuoteTranslator.new(<<TEXT
|
||||||
|
> Here's a bunch of shit i guess lmao idk
|
||||||
|
```markdown
|
||||||
|
test
|
||||||
|
test
|
||||||
|
test
|
||||||
|
*** test ***
|
||||||
|
piss
|
||||||
|
cock
|
||||||
|
__cock__
|
||||||
|
# hi
|
||||||
|
```
|
||||||
|
> ok
|
||||||
|
> here i go pissing
|
||||||
|
> ***time to take a piss***
|
||||||
|
> > pissing
|
||||||
|
> > "what the hell are you doing"
|
||||||
|
> > i'm taking a pieeees
|
||||||
|
> > "why areyou not jomping at me thats what yourshupposed to do
|
||||||
|
> > I might do it focking later
|
||||||
|
> > ok
|
||||||
|
> # bug
|
||||||
|
> __cum__
|
||||||
|
__mashup__
|
||||||
|
|
||||||
|
TEXT
|
||||||
|
)+Markdown::QuoteTranslator+Markdown::LeftmostTagTranslator+Markdown::LinearTagTranslator)
|
||||||
|
.to_html
|
||||||
|
|
Loading…
Reference in New Issue