Last active
March 25, 2020 03:24
-
-
Save jeremyredhead/534c2f1502b6b95294959d3f72f41342 to your computer and use it in GitHub Desktop.
WIP Ruby Code for Eventual Use in a Markdown Parser
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
=begin title | |
EXCESSIVELY ANNOTATED WORK IN PROGRESS RUBY CODE FOR EVENTUAL USE IN A HOMEMADE MARKDOWN PARSER | |
=end # title | |
# half-baked WIP for a markdown generator i am fixin' to write | |
# (for personal use, this thing will make orignal markdown.pl look clean :P) | |
class Element | |
# attr_* methods are library helpers, | |
# they create setters & getters which correspond to a @ClassVar of the same name | |
attr_accessor :tagname | |
attr_accessor :contents # i should rename this :children | |
# the method is initialize, but you don't call it directly :P | |
# you call :new (which is defined on Object) which creates & allocates an object, | |
# and then calls initialize with the right self/args | |
def initialize(tag, node = nil) # default tagname ? | |
# in this case I am using explicit (instead of implicit) self, | |
# to invoke the setter (otherwise ruby thinks its a normal variable) | |
self.tagname = tag | |
@contents = [] | |
# << is basically push | |
# notice the elegant but slightly confusing reverse if/unless | |
self << node unless node.nil? | |
end | |
# ruby's version of setters basically | |
def tagname=(tag) | |
# sidenote: ruby has some *really* nice regex syntax imho | |
unless tag.match /^[-_a-z:0-9]+$/ | |
# reminder that ruby uses implicit self, inspect == self.inspect | |
raise ArgumentError, "bad tagname: '#{tag}' for #{inspect}" | |
end | |
@tagname = tag | |
# do SOMETHING if tag is e.g. 'img' or other weird stuff | |
end | |
# yes, that's ruby's name for toString... | |
def to_s | |
# that's really ugly looking, isn't it? | |
# but not as ugly as "<#@tagname>" :D | |
html = "<#{@tagname}>" | |
# oh yea also ruby has mutable strings. yea | |
@contents.each { |node| html << node.to_s } | |
html << "</#{@tagname}>" | |
end | |
# inspect is called by IRB | |
def inspect | |
# TODO: better inspect | |
"<#{@tagname}> #{@contents[0]} ..." | |
end | |
# i wish JS had operator overloading.... | |
def <<(node) | |
@contents << node | |
self | |
end | |
# this is a little confusing (even *if* you know ruby)... | |
# this is "static" class method b/c of the `self.` | |
# "but wait?", i hear myself say to no one, | |
# "i thought ruby was implicit self? why is this different from above" | |
# well, uh, normally methods are defined on the class (Element) | |
# ...but not the object Element(?) | |
# but with self, you're defining it on Element, aka Element's class | |
# no, not Class, the Element object's *metaclass*... | |
# look, just read this, okay? | |
# i can barely keep it all straight in my own head... | |
# https://yehudakatz.com/2009/11/15/metaprogramming-in-ruby-its-all-about-the-self/ | |
def self.method_missing(name, *args) | |
# TODO: use an element tagname white-list | |
# this is very lazy. super to catch errors | |
super unless name.match(/^[a-z][a-z0-9]*$/) | |
new(name, *args) | |
end | |
# after some reading & research i realized in this case, | |
# probably i would want to use define_method, | |
# since the list of html elements doesn't change too often :P | |
end | |
# stuff from Kernel can be called anywhere un-namespaced | |
# it holds stuff like print, puts, gets, etc | |
module Kernel | |
def h(tag, node = nil) | |
Element.new(tag, node) | |
end | |
end | |
class Document | |
def initialize; end | |
end | |
__END__ | |
Note: __END__ marks the beginning of the "data section" in a ruby file | |
(which can be read by the program!) | |
IIRC this is one of the features copied from Perl :P | |
# NOTES | |
/ html | body | title # etc | |
| h[1-6] | |
| [abipqsu] | |
| a | abbr | b | br | em | strong | |
| blockquote | ins | del | figure | figcaption | /x | |
# is this a bad idea? | |
# thinking bout whether to alias these method names to elements | |
# just to make the code prettier, y'know | |
strike = s | |
bold = b | |
italic = i | |
under(line) = u | |
quote = q | |
super = sup | |
? link = a | |
image = img | |
para = p | |
%w[ html head body title | |
h1 h2 h3 h4 h5 h6 | |
dl ol ul dd dt li | |
a abbr b br cite code em i mark s sub sup time u | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment