require 'ostruct' require 'pp' require 'date' require 'runeblog' require 'pathmagic' require 'xlate' # errfile = File.new("/tmp/liveblog.out", "w") # STDERR.reopen(errfile) def init_liveblog # FIXME - a lot of this logic sucks here = Dir.pwd dir = here loop { dir = Dir.pwd; break if File.exist?("config"); Dir.chdir("..") } Dir.chdir(here) # here??? or dir?? @blog = RuneBlog.new(dir) @root = @blog.root @view = @blog.view @view_name = @blog.view.name unless @view.nil? @vdir = @blog.view.dir @version = RuneBlog::VERSION @theme = @vdir/:themes/:standard end ################## # "dot" commands ################## def dropcap # Bad form: adds another HEAD text = _data _out " " letter = text[0] remain = text[1..-1] _out %[
#{letter}
] _out %[
#{remain}] end def post @meta = OpenStruct.new @meta.num = _args[0] _out " \n " end def post_trailer perma = _var("publish.proto") + "://" + _var("publish.server") + "/" + _var("publish.path") + "/permalink/" + _var("post.aslug") + ".html" tags = _var("post.tags") if tags.empty? taglist = "" else taglist = "Tags: #{tags}" end _out <<~HTML
[Back] [permalink] #{taglist}
HTML # damned syntax highlighting end def backlink _out %[
[Back]] end def quote _passthru "
" _passthru _body.join(" ") _passthru "
" _optional_blank_line end def categories # does nothing right now end def style fname = _args[0] _passthru %[] end # Move elsewhere later! def h1; _passthru "

#{@_data}

"; end def h2; _passthru "

#{@_data}

"; end def h3; _passthru "

#{@_data}

"; end def h4; _passthru "

#{@_data}

"; end def h5; _passthru "
#{@_data}
"; end def h6; _passthru "
#{@_data}
"; end def hr; _passthru "
"; end def list _out "" _optional_blank_line end def list! _out "" _optional_blank_line end def make_main_links log!(enter: __method__, level: 1) # FIXME remember strings may not be safe line = _data.chomp tag, card_title = *line.split(" ", 2) cardfile, mainfile = "#{tag}-card", "#{tag}-main" input = "list.data" log!(str: "Reading #{input}", pwd: true, level: 3) pairs = File.readlines(input).map {|line| line.chomp.split(/, */, 2) } _write_main(mainfile, pairs, card_title, tag) _write_card(cardfile, mainfile, pairs, card_title, tag) log!(str: "...returning from method", pwd: true, level: 3) end ### inset def inset lines = _body box = "" output = [] lines.each do |line| line = line case line[0] when "/" # Only into inset line[0] = ' ' box << line line.replace(" ") when "|" # Into inset and body line[0] = ' ' box << line output << line else # Only into body output << line end # _passthru(line) end lr = _args.first wide = _args[1] || "25" stuff = "
" stuff << '' + box + '
' _out "

" # kludge!! nopara 0.upto(2) {|i| _passthru output[i] } _passthru stuff # _passthru "
" # ; font-family:verdana'>" # _passthru '' # _passthru box # _passthru_noline '
' 3.upto(output.length-1) {|i| _passthru output[i] } _out "

" # kludge!! para _optional_blank_line end def title raise "'post' was not called" unless @meta title = @_data.chomp @meta.title = title setvar :title, title # FIXME refactor -- just output variables for a template # _out %[

#{title}


] _optional_blank_line end def pubdate raise "'post' was not called" unless @meta _debug "data = #@_data" # Check for discrepancy? match = /(\d{4}).(\d{2}).(\d{2})/.match @_data junk, y, m, d = match.to_a y, m, d = y.to_i, m.to_i, d.to_i @meta.date = ::Date.new(y, m, d) @meta.pubdate = "%04d-%02d-%02d" % [y, m, d] _optional_blank_line end def image # primitive so far _debug "img: huh? " fname = _args.first path = :assets/fname _out "" _optional_blank_line end def tags raise "'post' was not called" unless @meta _debug "args = #{_args}" @meta.tags = _args.dup || [] _optional_blank_line end def views raise "'post' was not called" unless @meta _debug "data = #{_args}" @meta.views = _args.dup _optional_blank_line end def pin raise "'post' was not called" unless @meta _debug "data = #{_args}" # verify only already-specified views? @meta.pinned = _args.dup _optional_blank_line end def write_post raise "'post' was not called" unless @meta @meta.views = @meta.views.join(" ") if @meta.views.is_a? Array @meta.tags = @meta.tags.join(" ") if @meta.tags.is_a? Array _write_metadata rescue => err puts "err = #{err}" puts err.backtrace.join("\n") end def teaser raise "'post' was not called" unless @meta text = _body_text @meta.teaser = text setvar :teaser, @meta.teaser if _args[0] == "dropcap" # FIXME doesn't work yet! letter, remain = text[0], text[1..-1] _out %[
#{letter}
] _out %[
#{remain}] + "\n" else _out @meta.teaser + "\n" end end def finalize # FIXME simplify this! unless @meta puts @live.body return end if @blog.nil? return @meta end @slug = @blog.make_slug(@meta) slug_dir = @slug @postdir = @blog.view.dir/:posts/slug_dir write_post @meta end def head # Does NOT output tags args = _args args.each do |inc| self.data = inc _include end # Depends on vars: title, desc, host defaults = {} defaults = { "charset" => %[], "http-equiv" => %[], "title" => %[\n #{_var(:blog)} | #{_var("blog.desc")}\n ], "generator" => %[], "og:title" => %[], "og:locale" => %[], "description" => %[], "og:description" => %[], "linkc" => %[], "og:url" => %[], "og:site_name" => %[], "style" => %[], "feed" => %[], "favicon" => %[\n ] } result = {} lines = _body lines.each do |line| line.chomp word, remain = line.split(" ", 2) case word when "viewport" result["viewport"] = %[] when "script" # FIXME this is broken file = remain text = File.read(file) result["script"] = Livetext.new.transform(text) when "style" result["style"] = %[] # Later: allow other overrides when ""; break else if defaults[word] result[word] = %[] else puts "Unknown tag '#{word}'" end end end hash = defaults.dup.update(result) # FIXME collisions? hash.each_value {|x| _out " " + x } end ########## newer stuff... def meta args = _args enum = args.each str = "" _out str end def recent_posts # side-effect _out <<-HTML
HTML end def _make_class_name(app) if app =~ /[-_]/ words = app.split(/[-_]/) name = words.map(&:capitalize).join else name = app.capitalize end return name end def _load_local(widget) Dir.chdir("widgets/#{widget}") do rclass = _make_class_name(widget) found = (require("./#{widget}") if File.exist?("#{widget}.rb")) code = found ? ::RuneBlog::Widget.class_eval(rclass) : nil code end rescue => err STDERR.puts err.to_s STDERR.puts err.backtrace.join("\n") exit end def sidebar if _args.include? "off" _body { } # iterate, do nothing return end _out %[
] _body do |token| tag = token.chomp.strip.downcase wtag = :widgets/tag raise "Can't find #{wtag}" unless Dir.exist?(wtag) tcard = "#{tag}-card.html" code = _load_local(tag) if code if ["pages", "links"].include? tag Dir.chdir(wtag) do widget = code.new(@blog) widget.build end end end if tag == "ad" num = rand(1..4) img = "widgets/ad/ad#{num}.png" src, dst = img, @root/:views/@view_name/"remote/widgets/ad/" system!("cp #{src} #{dst}") # , show: true) File.open(wtag/"vars.lt3", "w") do |f| f.puts ".set ad.image = #{img}" end end xlate cwd: wtag, src: tag, dst: tcard # , debug: (tag == "ad") _include_file wtag/tcard end _out %[
] rescue => err puts "err = #{err}" puts err.backtrace.join("\n") exit end def stylesheet lines = _body url = lines[0] integ = lines[1] cross = lines[2] || "anonymous" _out %[] end def script lines = _body url = lines[0] integ = lines[1] cross = lines[2] || "anonymous" _out %[] end def card_iframe title, lines = _data, _body lines.map!(&:chomp) url = lines[0].chomp stuff = lines[1..-1].join(" ") # FIXME later middle = <<-HTML HTML _card_generic(card_title: title, middle: middle, extra: "bg-dark text-white") end $Dot = self # Clunky! for dot commands called from Functions class # Find a better way to do this? class Livetext::Functions def br(n="1") # Thought: Maybe make a way for functions to "simply" call the # dot command of the same name?? Is this trivial?? n = n.empty? ? 1 : n.to_i "
"*n end def h1(param); "

#{param}

"; end def h2(param); "

#{param}

"; end def h3(param); "

#{param}

"; end def h4(param); "

#{param}

"; end def h5(param); "
#{param}
"; end def h6(param); "
#{param}
"; end def hr(param=nil) $Dot.hr end def image(param) "" end end ###### experimental... class Livetext::Functions def _var(name) ::Livetext::Vars[name] || "[:#{name} is undefined]" end # def link(param = nil) # puts "--- WTF?? param = #{param.inspect}"; gets # file, cdata = param.split("||", 2) # %[#{cdata}] # end # # def link(param = nil) # file, cdata = param.split("||", 2) # %[] # end end ### def card1 title, lines = _data, _body lines.map!(&:chomp) card_text = lines[0] url, classname, cdata = lines[1].split(",", 4) main = _main(url) middle = <<-HTML

#{card_text}

#{cdata} HTML _card_generic(card_title: title, middle: middle, extra: "bg-dark text-white") end def card2 str = _data file, card_title = str.chomp.split(" ", 2) card_title = %[#{card_title}] # FIXME is this wrong?? open = <<-HTML
#{card_title}
    HTML _out open _body do |line| url, cdata = line.chomp.split(",", 3) main = _main(url) _out %[
  • #{cdata}
  • ] end close = %[
\n
\n
] _out close end def tag_cloud title = _data title = "Tag Cloud" if title.empty? open = <<-HTML
#{title}
HTML _out open _body do |line| line.chomp! url, classname, cdata = line.split(",", 3) main = _main(url) _out %[#{cdata}] end close = %[
\n
\n
] _out close end def navbar vdir = @blog.view.dir title = _var(:blog) open = <<-HTML HTML first = true _out open lines = _body lines.each do |line| basename, cdata = line.chomp.strip.split(" ", 2) full = :navbar/basename+".html" href_main = _main(full) if first first = false # hardcode this part?? _out %[] else xlate cwd: "navbar", src: basename, dst: vdir/"remote/navbar"/basename+".html" # , debug: true _out %[] end end _out close end ################## # helper methods ################## def _html_body(file, css = nil) file.puts "" if css file.puts " " file.puts " " file.puts " " end file.puts " " yield file.puts " \n" end def _write_card(cardfile, mainfile, pairs, card_title, tag) log!(str: "Creating #{cardfile}.html", pwd: true, level: 2) url = mainfile url = :widgets/tag/mainfile + ".html" File.open("#{cardfile}.html", "w") do |f| f.puts <<-EOS
#{card_title}
EOS log!(str: "Writing data pairs to #{cardfile}.html", pwd: true, level: 2) local = _local_tag?(tag) pairs.each do |file, title| url = file type, title = page_type(tag, title) case type when :local; url_ref = _widget_card(file, tag) # local always frameable when :frame; url_ref = _main(file) # remote, frameable when :noframe; url_ref = _blank(file) # remote, not frameable end anchor = %[#{title}] wrapper = %[
  • #{anchor}
  • ] f.puts wrapper end _include_file cardfile+".html" f.puts <<-EOS
    EOS end end def _local_tag?(tag) case tag.to_sym when :pages true when :news, :links false else true # Hmmm... end end def page_type(tag, title) yesno = "yes" yesno, title = title.split(/, */) if title =~ /^[yes|no]/ local = _local_tag?(tag) frameable = (yesno == "yes") if local return [:local, title] elsif frameable return [:frame, title] else return [:noframe, title] end end def _write_main_pages(mainfile, pairs, card_title, tag) local = _local_tag?(tag) pieces = @blog.view.dir/"themes/standard/widgets"/tag/:pieces main_head = xlate! cwd: pieces, src: "main-head.lt3" main_tail = xlate! cwd: pieces, src: "main-tail.lt3" # ^ make into methods in pages.rb or whatever? File.open("#{mainfile}.html", "w") do |f| f.puts main_head pairs.each do |file, title| type, title = page_type(tag, title) title = title.gsub(/\\/, "") # kludge case type when :local; url_ref = _widget_main(file, tag) # local always frameable when :frame; url_ref = "href = '#{file}'" # local always frameable when :noframe; url_ref = _blank(file) # local always frameable end css = "color: #8888FF; text-decoration: none; font-size: 21px" # ; font-family: verdana" f.puts %[#{title}
    ] end f.puts main_tail end end def _write_main(mainfile, pairs, card_title, tag) log!(str: "Creating #{mainfile}.html", pwd: true, level: 2) if tag == "pages" # temporary experiment _write_main_pages(mainfile, pairs, card_title, tag) return end local = _local_tag?(tag) setvar "card.title", card_title css = "* { font-family: verdana }" File.open("#{mainfile}.html", "w") do |f| _html_body(f, css) do f.puts "

    #{card_title}



    " pairs.each do |file, title| type, title = page_type(tag, title) title = title.gsub(/\\/, "") # kludge case type when :local; url_ref = _widget_main(file, tag) # local always frameable when :frame; url_ref = "href = '#{file}'" # local always frameable when :noframe; url_ref = _blank(file) # local always frameable end css = "color: #8888FF; text-decoration: none; font-size: 21px" # ; font-family: verdana" f.puts %[#{title}
    ] end end end end def _errout(*args) ::STDERR.puts *args end def _passthru(line) return if line.nil? line = _format(line) _out line + "\n" _out "

    " if line.empty? && ! @_nopara end def _passthru_noline(line) return if line.nil? line = _format(line) _out line _out "

    " if line.empty? && ! @_nopara end def _write_metadata File.write("teaser.txt", @meta.teaser) fields = [:num, :title, :date, :pubdate, :views, :tags] fname2 = "metadata.txt" f2 = File.open(fname2, "w") do |f2| fields.each {|fld| f2.puts "#{fld}: #{@meta.send(fld)}" } end end def _post_lookup(postid) # side-effect # .. = templates, ../.. = views/thisview slug = title = date = teaser_text = nil dir_posts = @vdir/:posts posts = Dir.entries(dir_posts).grep(/^\d\d\d\d/).map {|x| dir_posts/x } posts.select! {|x| File.directory?(x) } post = posts.select {|x| File.basename(x).to_i == postid } raise "Error: More than one post #{postid}" if post.size > 1 postdir = post.first vp = RuneBlog::ViewPost.new(@blog.view, postdir) vp end def _interpolate(str, context) # FIXME move this later wrapped = "%[" + str.dup + "]" # could fail... eval(wrapped, context) end def _card_generic(card_title:, middle:, extra: "") front = <<-HTML

    #{card_title}
    HTML tail = <<-HTML
    HTML text = front + middle + tail _out text + "\n " end def _var(name) # FIXME scope issue! ::Livetext::Vars[name] || "[:#{name} is undefined]" end def _main(url) %[href="javascript: void(0)" onclick="javascript:open_main('#{url}')"] end def _blank(url) %[href='#{url}' target='blank'] end def _widget_main(url, tag) %[href="#{url}"] end def _widget_card(url, tag) url2 = :widgets/tag/url %[href="javascript: void(0)" onclick="javascript:open_main('#{url2}')"] end