Skip to content

Commit

Permalink
Merge pull request #5 from ricardoricho/fix-footnotes
Browse files Browse the repository at this point in the history
Fix footnotes
  • Loading branch information
ricardoricho authored Jul 23, 2024
2 parents 83d8cef + 3981cc1 commit 2a40784
Show file tree
Hide file tree
Showing 22 changed files with 314 additions and 494 deletions.
3 changes: 1 addition & 2 deletions .github/workflows/rspec.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,7 @@
# This workflow will download a prebuilt Ruby version, install dependencies and run tests with Rake
# For more information see: https://github.com/marketplace/actions/setup-ruby-jruby-and-truffleruby

name: Ruby

name: RSpec
on:
push:
branches: [ "master" ]
Expand Down
2 changes: 1 addition & 1 deletion README.org
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ An [[http://orgmode.org][Org-mode]] parser written in Ruby.
** Demo

See the README file in [[https://ricardo-richo.gitlab.io/org-ruby][Gitlab]] ([[https://ricardo-richo.gitlab.io/org-ruby/]]) or in
[[https://ricardoricho.github.io/org-ruby/][GitHub]] (https://ricardoricho.github.io/org-ruby/)
[[https://ricardoricho.github.io/org-ruby/][GitHub]] ([[https://ricardoricho.github.io/org-ruby/]])

** Installation

Expand Down
1 change: 1 addition & 0 deletions lib/org-ruby.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
# internal requires
require 'org-ruby/version'
require 'orgmode/elements/document'
require 'org-ruby/parser'
require 'org-ruby/regexp_helper'
require 'org-ruby/line'
Expand Down
46 changes: 26 additions & 20 deletions lib/org-ruby/html_output_buffer.rb
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,10 @@ class HtmlOutputBuffer < OutputBuffer

attr_reader :options

def initialize(output, opts = {})
super(output)
def initialize(output, document = nil, opts = {})
super(output, document)
@options = opts
@new_paragraph = :start
@footnotes = {}
@unclosed_tags = []

# move from output_buffer
Expand Down Expand Up @@ -218,7 +217,7 @@ def add_headline_id(line)
end

def html_buffer_code_block_indent(line)
if mode_is_code?(current_mode) && !(line.block_type)
if mode_is_code?(current_mode) && !line.block_type
# Determines the amount of whitespaces to be stripped at the
# beginning of each line in code block.
if line.paragraph_type != :blank
Expand All @@ -238,20 +237,19 @@ def html_buffer_code_block_indent(line)
# defined separately from their references will be rendered where they appear in the original
# Org document.
def output_footnotes!
return false if !options[:export_footnotes] || @footnotes.empty?
return if !options[:export_footnotes] || document.footnotes.empty?

@output.concat footnotes_header
@footnotes.each do |name, (defi, content)|
@buffer = defi
@output << "<div class=\"footdef\"><sup><a id=\"fn.#{name}\" href=\"#fnr.#{name}\">#{name}</a></sup>" \
<< "<p class=\"footpara\">" \
document.footnotes.each do |footnote|
@buffer = footnote[:content].empty? && footnote[:label] || footnote[:content]
a_href = footnote[:index]
@output << "<div class=\"footdef\"><sup><a id=\"fn.#{a_href}\" class=\"footnum\" href=\"#fnr.#{a_href}\" role=\"doc-backlink\">#{a_href}</a></sup>" \
<< "<div class=\"footpara\" role=\"doc-footnote\"><p class=\"footpara\">" \
<< inline_formatting(@buffer) \
<< "</p></div>\n"
<< "</p></div></div>\n"
end

@output.concat "</div>\n</div>"

true
end

def footnotes_header
Expand Down Expand Up @@ -390,16 +388,24 @@ def inline_formatting(str)
str.gsub!(/\s*\|\s*/, quote_tags("</th><th>"))
end

if @options[:export_footnotes] then
@re_help.rewrite_footnote_definition str do |name, content|
quote_tags("<sup><a id=\"fn.#{name}\" class=\"footnum\" href=\"#fnr.#{name}\">") +
name + quote_tags("</a></sup> ") + content
if @options[:export_footnotes]
@re_help.capture_footnote_definition(str) do |label, content|
# Capture definition and replace it with nil
nil
end

@re_help.rewrite_footnote str do |name, defi|
@footnotes[name] = defi if defi
quote_tags("<sup><a id=\"fnr.#{name}\" class=\"footref\" href=\"#fn.#{name}\">") +
name + quote_tags("</a></sup>")
# Reference footnote
@re_help.rewrite_footnote str do |label, content|
footnote = document.footnotes.find do |footnote|
footnote[:label] == label || footnote[:content] == content
end

a_id = (footnote[:label].nil? || footnote[:label].empty?) ? footnote[:index] : footnote[:label]
a_text = footnote[:index]
a_href = (footnote[:label].nil? || footnote[:label].empty?) ? footnote[:index] : footnote[:label]

footnote_tag = "<sup><a id=\"fnr.#{a_id}\" class=\"footref\" href=\"#fn.#{a_href}\" role=\"doc-backlink\">#{a_text}</a></sup>"
quote_tags(footnote_tag)
end
end

Expand Down
7 changes: 6 additions & 1 deletion lib/org-ruby/line.rb
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,12 @@ def comment?
# Determines if a line is an orgmode "headline":
# A headline begins with one or more asterisks.
def headline?
RegexpHelper.headline.match(to_s)
RegexpHelper.headline.match(@line)
end

def footnote?
RegexpHelper.footnote_definition.match(@line) ||
RegexpHelper.footnote_reference.match(@line)
end

def property_drawer_begin_block?
Expand Down
8 changes: 8 additions & 0 deletions lib/org-ruby/line_regexp.rb
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,14 @@ def drawer
/^\s*:(?<name>[\w\-]+):$/
end

def footnote_definition
/^\[fn:(?<label>[\w-]+)\](?<contents>.*)/
end

def footnote_reference
/\[fn:(?<label>[\w-]*)(:?)(?<contents>.*)\]/
end

def headline
/^\*+\s+/
end
Expand Down
5 changes: 0 additions & 5 deletions lib/org-ruby/markdown_output_buffer.rb
Original file line number Diff line number Diff line change
Expand Up @@ -69,11 +69,6 @@ def inline_formatting(input)
input
end

# TODO: Implement this
def output_footnotes!
return false
end

# Flushes the current buffer
def flush!
return false if @buffer.empty? and @output_type != :blank
Expand Down
13 changes: 7 additions & 6 deletions lib/org-ruby/output_buffer.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,14 @@ module Orgmode
# add a newline character prior emitting the output.
class OutputBuffer
# This is the overall output buffer
attr_reader :output, :mode_stack, :list_indent_stack
attr_reader :output, :mode_stack, :list_indent_stack, :document

# This is the current type of output being accumulated.
attr_accessor :output_type, :headline_number_stack, :custom_blocktags

# Creates a new OutputBuffer object that is bound to an output object.
# The output will get flushed to =output=.
def initialize(output)
def initialize(output, document = nil)
# This is the accumulation buffer. It's a holding pen so
# consecutive lines of the right type can get stuck together
# without intervening newlines.
Expand All @@ -29,6 +29,7 @@ def initialize(output)
@list_indent_stack = []
@mode_stack = []
@custom_blocktags = []
@document = document

# regexp module
@re_help = RegexpHelper.new
Expand Down Expand Up @@ -169,6 +170,10 @@ def no_custom_markup_file_exist
nil
end

def output_footnotes!
# Implement in output buffers
end

protected

attr_reader :block_lang
Expand Down Expand Up @@ -257,10 +262,6 @@ def add_headline_id(line)
# Implement this in output buffers
end

def output_footnotes!
false
end

# Tests if the current line should be accumulated in the current
# output buffer.
def should_accumulate_output?(line)
Expand Down
29 changes: 18 additions & 11 deletions lib/org-ruby/parser.rb
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ def export_todo?

# Returns true if we are to export footnotes
def export_footnotes?
"t" == @options["f"]
"nil" != @options["f"]
end

# Returns true if we are to export heading numbers.
Expand Down Expand Up @@ -97,14 +97,15 @@ def initialize_lines(lines)
# I can construct a parser object either with an array of lines
# or with a single string that I will split along \n boundaries.
def initialize(lines, parser_options = {})
@lines = initialize_lines lines
@lines = initialize_lines(lines)
@custom_keywords = []
@headlines = []
@current_headline = nil
@header_lines = []
@document = Orgmode::Elements::Document.new
@in_buffer_settings = {}
@options = {}
@headlines = []
@header_lines = []
@link_abbrevs = {}
@options = {}
@parser_options = parser_options

#
Expand Down Expand Up @@ -170,6 +171,9 @@ def parse_lines(lines)
@link_abbrevs[link_abbrev_data[0]] = link_abbrev_data[1]
end

# Store footnotes
document.store_footnote(line)

if (line.end_block? && [line.paragraph_type, :comment].include?(mode)) ||
(line.property_drawer_end_block? && (mode == :property_drawer))
mode = :normal
Expand Down Expand Up @@ -309,12 +313,13 @@ def self.load(fname, _opts = {})
# Saves the loaded orgmode file as a textile file.
def to_textile
output = ''
output_buffer = TextileOutputBuffer.new(output)
output_buffer = TextileOutputBuffer.new(output, document)

translate(@header_lines, output_buffer)
@headlines.each do |headline|
translate(headline.body_lines, output_buffer)
end
output_buffer.output_footnotes!
output
end

Expand All @@ -339,8 +344,8 @@ def to_html
decorate_title: in_buffer_settings['TITLE'],
export_heading_number: export_heading_number?,
export_todo: export_todo?,
use_sub_superscripts: use_sub_superscripts?,
export_footnotes: export_footnotes?,
use_sub_superscripts: use_sub_superscripts?,
link_abbrevs: @link_abbrevs,
skip_syntax_highlight: @parser_options[:skip_syntax_highlight],
markup_file: @parser_options[:markup_file],
Expand All @@ -350,8 +355,7 @@ def to_html
}
export_options[:skip_tables] = true unless export_tables?
output = ''
output_buffer = HtmlOutputBuffer.new(output, export_options)

output_buffer = HtmlOutputBuffer.new(output, document, export_options)
if title?
# If we're given a new title, then just create a new line
# for that title.
Expand Down Expand Up @@ -379,7 +383,10 @@ def title
in_buffer_settings['TITLE']
end

######################################################################
protected

attr_reader :document

private

def translate_headlines(headlines, output_buffer)
Expand All @@ -391,6 +398,7 @@ def translate_headlines(headlines, output_buffer)
translate(headline.body_lines, output_buffer)
end
end
output_buffer.output_footnotes!
end

# Converts an array of lines to the appropriate format.
Expand All @@ -400,7 +408,6 @@ def translate(lines, output_buffer)
lines.each { |line| output_buffer.insert(line) }
output_buffer.flush!
output_buffer.pop_mode while output_buffer.current_mode
output_buffer.output_footnotes!
output_buffer.output
end

Expand Down
12 changes: 7 additions & 5 deletions lib/org-ruby/regexp_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -108,14 +108,16 @@ def rewrite_subp(str)

# rewrite footnotes
def rewrite_footnote(str)
str.gsub!(org_footnote_regexp) do |_match|
yield Regexp.last_match(1), Regexp.last_match(3)
str.gsub!(RegexpHelper.footnote_reference) do |_match|
match = Regexp.last_match
yield match[:label], match[:contents]
end
end

def rewrite_footnote_definition(str)
str.gsub!(org_footnote_def_regexp) do |_match|
yield Regexp.last_match(1), Regexp.last_match(5)
def capture_footnote_definition(str)
str.gsub!(RegexpHelper.footnote_definition) do |_match|
match = Regexp.last_match
yield match[:label], match[:contents]
end
end

Expand Down
Loading

0 comments on commit 2a40784

Please sign in to comment.