asciidoctor-bibliography 0.0.1.dev
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +50 -0
- data/Gemfile +21 -0
- data/Gemfile.lock +41 -0
- data/LICENSE.txt +21 -0
- data/README.adoc +101 -0
- data/SYNTAX.adoc +117 -0
- data/asciidoctor-bibliography.gemspec +37 -0
- data/deprecated/asciidoctor-bibliography/asciidoctor/bibliographer_postprocessor.rb +23 -0
- data/deprecated/asciidoctor-bibliography/asciidoctor/bibliography_block_macro.rb +77 -0
- data/deprecated/asciidoctor-bibliography/asciidoctor/citation_processor.rb +144 -0
- data/deprecated/asciidoctor-bibliography/asciidoctor/cite_inline_macro.rb +30 -0
- data/deprecated/asciidoctor-bibliography/citationdata.rb +23 -0
- data/deprecated/asciidoctor-bibliography/citations.rb +45 -0
- data/deprecated/asciidoctor-bibliography/citationutils.rb +67 -0
- data/deprecated/asciidoctor-bibliography/extensions.rb +64 -0
- data/deprecated/asciidoctor-bibliography/filehandlers.rb +32 -0
- data/deprecated/asciidoctor-bibliography/index.rb +31 -0
- data/deprecated/asciidoctor-bibliography/processor.rb +208 -0
- data/deprecated/asciidoctor-bibliography/processorutils.rb +34 -0
- data/deprecated/asciidoctor-bibliography/styles.rb +27 -0
- data/lib/asciidoctor-bibliography.rb +3 -0
- data/lib/asciidoctor-bibliography/asciidoctor.rb +17 -0
- data/lib/asciidoctor-bibliography/asciidoctor/bibliographer_preprocessor.rb +68 -0
- data/lib/asciidoctor-bibliography/bibliographer.rb +31 -0
- data/lib/asciidoctor-bibliography/citation.rb +73 -0
- data/lib/asciidoctor-bibliography/database.rb +20 -0
- data/lib/asciidoctor-bibliography/databases/bibtex.rb +43 -0
- data/lib/asciidoctor-bibliography/formatters/csl.rb +12 -0
- data/lib/asciidoctor-bibliography/formatters/tex.rb +164 -0
- data/lib/asciidoctor-bibliography/helpers.rb +40 -0
- data/lib/asciidoctor-bibliography/index.rb +43 -0
- data/lib/asciidoctor-bibliography/version.rb +3 -0
- data/samples/.byebug_history +245 -0
- data/samples/biblio.bib +31 -0
- data/samples/latex_macros_in_bibtex/reference.bib +16 -0
- data/samples/latex_macros_in_bibtex/sample.adoc +13 -0
- data/samples/sample-authoryear.adoc +72 -0
- data/samples/sample-authoryear.html +550 -0
- data/samples/sample-numbers.adoc +72 -0
- data/samples/sample-numbers.html +550 -0
- metadata +187 -0
@@ -0,0 +1,144 @@
|
|
1
|
+
require 'asciidoctor'
|
2
|
+
require 'asciidoctor/extensions'
|
3
|
+
require 'asciidoctor/reader'
|
4
|
+
require 'asciidoctor/parser'
|
5
|
+
# require 'bibtex/filters'
|
6
|
+
# require 'latex/decode/base'
|
7
|
+
# require 'latex/decode/maths'
|
8
|
+
# require 'latex/decode/accents'
|
9
|
+
# require 'latex/decode/diacritics'
|
10
|
+
# require 'latex/decode/punctuation'
|
11
|
+
# require 'latex/decode/symbols'
|
12
|
+
# require 'latex/decode/greek'
|
13
|
+
# require_relative 'styles'
|
14
|
+
# require_relative 'filehandlers'
|
15
|
+
|
16
|
+
module AsciidoctorBibliography
|
17
|
+
module Asciidoctor
|
18
|
+
|
19
|
+
# This filter extends the original latex filter in bibtex-ruby to handle
|
20
|
+
# unknown latex macros more gracefully. We could have used latex-decode
|
21
|
+
# gem together with our custom replacement rules, but latex-decode eats up
|
22
|
+
# all braces after it finishes all decoding. So we hack over the
|
23
|
+
# LaTeX.decode function and insert our rules before `strip_braces`.
|
24
|
+
# class LatexFilter < ::BibTeX::Filter
|
25
|
+
# def apply(value)
|
26
|
+
# text = value.to_s
|
27
|
+
# LaTeX::Decode::Base.normalize(text)
|
28
|
+
# LaTeX::Decode::Maths.decode!(text)
|
29
|
+
# LaTeX::Decode::Accents.decode!(text)
|
30
|
+
# LaTeX::Decode::Diacritics.decode!(text)
|
31
|
+
# LaTeX::Decode::Punctuation.decode!(text)
|
32
|
+
# LaTeX::Decode::Symbols.decode!(text)
|
33
|
+
# LaTeX::Decode::Greek.decode!(text)
|
34
|
+
# text.gsub!(/\\url\{(.+?)\}/, " \\1 ")
|
35
|
+
# text.gsub!(/\\\w+(?=\s+\w)/, "")
|
36
|
+
# text.gsub!(/\\\w+(?:\[.+?\])?\s*\{(.+?)\}/, "\\1")
|
37
|
+
# LaTeX::Decode::Base.strip_braces(text)
|
38
|
+
# LaTeX.normalize_C(text)
|
39
|
+
# end
|
40
|
+
# end
|
41
|
+
|
42
|
+
# This processor scans the document, generates a list of citations,
|
43
|
+
# replace each citation with correct text and the reference block macro
|
44
|
+
# placeholder with the final reference list. It relys on the block macro
|
45
|
+
# processor to generate the place holder.
|
46
|
+
class CitationProcessor < ::Asciidoctor::Extensions::Treeprocessor
|
47
|
+
|
48
|
+
def process document
|
49
|
+
puts self
|
50
|
+
# byebug
|
51
|
+
# bibtex_file = (document.attr 'bibtex-file').to_s
|
52
|
+
# bibtex_style = ((document.attr 'bibtex-style') || 'ieee').to_s
|
53
|
+
# bibtex_order = ((document.attr 'bibtex-order') || 'appearance').to_sym
|
54
|
+
# bibtex_format = ((document.attr 'bibtex-format') || 'asciidoc').to_sym
|
55
|
+
|
56
|
+
# if bibtex_file.empty?
|
57
|
+
# bibtex_file = AsciidoctorBibliography::FileHandlers.find_bibliography "."
|
58
|
+
# end
|
59
|
+
# if bibtex_file.empty?
|
60
|
+
# bibtex_file = AsciidoctorBibliography::FileHandlers.find_bibliography "#{ENV['HOME']}/Documents"
|
61
|
+
# end
|
62
|
+
# if bibtex_file.empty?
|
63
|
+
# puts "Error: bibtex-file is not set and automatic search failed"
|
64
|
+
# exit
|
65
|
+
# end
|
66
|
+
|
67
|
+
# bibtex = BibTeX.open bibtex_file, :filter => [LatexFilter]
|
68
|
+
# processor = Processor.new bibtex, true, bibtex_style, bibtex_order == :appearance, bibtex_format
|
69
|
+
|
70
|
+
# prose_blocks = document.find_by {|b| b.content_model == :simple or b.context == :list_item}
|
71
|
+
# prose_blocks.each do |block|
|
72
|
+
# if block.context == :list_item
|
73
|
+
# line = block.instance_variable_get :@text
|
74
|
+
# processor.citations.add_from_line line
|
75
|
+
# else
|
76
|
+
# block.lines.each do |line|
|
77
|
+
# processor.citations.add_from_line line
|
78
|
+
# end
|
79
|
+
# end
|
80
|
+
# end
|
81
|
+
|
82
|
+
# prose_blocks.each do |block|
|
83
|
+
# if block.context == :list_item
|
84
|
+
# line = block.instance_variable_get :@text
|
85
|
+
# processor.citations.retrieve_citations(line).each do |citation|
|
86
|
+
# line.gsub!(citation.original, processor.complete_citation(citation))
|
87
|
+
# end
|
88
|
+
# block.instance_variable_set :@text, line
|
89
|
+
# else
|
90
|
+
# block.lines.each do |line|
|
91
|
+
# processor.citations.retrieve_citations(line).each do |citation|
|
92
|
+
# line.gsub!(citation.original, processor.complete_citation(citation))
|
93
|
+
# end
|
94
|
+
# end
|
95
|
+
# end
|
96
|
+
# end
|
97
|
+
|
98
|
+
# references_asciidoc = []
|
99
|
+
# if bibtex_format == :latex
|
100
|
+
# references_asciidoc << %(+++\\bibliography{#{bibtex_file}}{}+++)
|
101
|
+
# references_asciidoc << %(+++\\bibliographystyle{#{bibtex_style}}+++)
|
102
|
+
# else
|
103
|
+
# processor.cites.each do |ref|
|
104
|
+
# references_asciidoc << processor.get_reference(ref)
|
105
|
+
# references_asciidoc << ''
|
106
|
+
# end
|
107
|
+
# end
|
108
|
+
|
109
|
+
# biblio_blocks = document.find_by do |b|
|
110
|
+
# # for fast search (since most searches shall fail)
|
111
|
+
# b.content_model == :simple and b.lines.size == 1 \
|
112
|
+
# and b.lines[0] == BibliographyBlockMacroPlaceholder
|
113
|
+
# end
|
114
|
+
# biblio_blocks.each do |block|
|
115
|
+
# block_index = block.parent.blocks.index do |b|
|
116
|
+
# b == block
|
117
|
+
# end
|
118
|
+
# reference_blocks = parse_asciidoc block.parent, references_asciidoc
|
119
|
+
# reference_blocks.reverse.each do |b|
|
120
|
+
# block.parent.blocks.insert block_index, b
|
121
|
+
# end
|
122
|
+
# block.parent.blocks.delete_at block_index + reference_blocks.size
|
123
|
+
# end
|
124
|
+
|
125
|
+
# nil
|
126
|
+
end
|
127
|
+
|
128
|
+
# This is an adapted version of Asciidoctor::Extension::parse_content,
|
129
|
+
# where resultant blocks are returned as a list instead of attached to
|
130
|
+
# the parent.
|
131
|
+
def parse_asciidoc parent, content, attributes = {}
|
132
|
+
result = []
|
133
|
+
reader = ::Asciidoctor::Reader.new content
|
134
|
+
while reader.has_more_lines?
|
135
|
+
block = ::Asciidoctor::Parser.next_block reader, parent, attributes
|
136
|
+
result << block if block
|
137
|
+
end
|
138
|
+
result
|
139
|
+
end
|
140
|
+
|
141
|
+
end
|
142
|
+
|
143
|
+
end
|
144
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require 'asciidoctor'
|
2
|
+
require 'asciidoctor/extensions'
|
3
|
+
|
4
|
+
require 'securerandom'
|
5
|
+
|
6
|
+
module AsciidoctorBibliography
|
7
|
+
module Asciidoctor
|
8
|
+
|
9
|
+
class CiteInlineMacro < ::Asciidoctor::Extensions::InlineMacroProcessor
|
10
|
+
use_dsl
|
11
|
+
|
12
|
+
named :cite
|
13
|
+
# name_positional_attributes 'volnum'
|
14
|
+
|
15
|
+
def process parent, target, attrs
|
16
|
+
puts self
|
17
|
+
|
18
|
+
citation = AsciidoctorBibliography::Citation.new parent, target, attrs, SecureRandom.uuid
|
19
|
+
parent.document.bibliographer.citations << citation
|
20
|
+
|
21
|
+
# text = target # TODO: typeset
|
22
|
+
# target = "#bibliography-#{target}"
|
23
|
+
# parent.document.register :links, target
|
24
|
+
# (create_anchor parent, text, type: :link, target: target).render
|
25
|
+
|
26
|
+
citation.placeholder
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# citationdata class
|
2
|
+
#
|
3
|
+
# Copyright (c) Peter Lane, 2013.
|
4
|
+
# Released under Open Works License, 0.9.2
|
5
|
+
|
6
|
+
module AsciidoctorBibliography
|
7
|
+
# Class to hold information about a citation in text:
|
8
|
+
# the text forming the citation, its type, pretext, and enclosed cites
|
9
|
+
class CitationData
|
10
|
+
attr_reader :original, :type, :pretext, :cites
|
11
|
+
|
12
|
+
def initialize original, type, pretext, cites
|
13
|
+
@original = original
|
14
|
+
@type = type
|
15
|
+
@pretext = if pretext.nil?
|
16
|
+
''
|
17
|
+
else
|
18
|
+
pretext
|
19
|
+
end
|
20
|
+
@cites = cites
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
#
|
2
|
+
# Class to hold and manage citations
|
3
|
+
#
|
4
|
+
# Copyright (c) Peter Lane, 2013.
|
5
|
+
# Released under Open Works License, 0.9.2
|
6
|
+
|
7
|
+
module AsciidoctorBibliography
|
8
|
+
# Class to store list of citations used in document
|
9
|
+
class Citations
|
10
|
+
include CitationUtils
|
11
|
+
|
12
|
+
attr_reader :cites_used
|
13
|
+
|
14
|
+
def initialize
|
15
|
+
@cites_used = []
|
16
|
+
end
|
17
|
+
|
18
|
+
# Given a line of text, extract any citations and include new citation references in current list
|
19
|
+
def add_from_line line
|
20
|
+
retrieve_citations(line).each do |citation|
|
21
|
+
@cites_used += citation.cites.collect {|cite| cite.ref}
|
22
|
+
end
|
23
|
+
@cites_used.uniq! {|item| item.to_s} # only keep each reference once
|
24
|
+
end
|
25
|
+
|
26
|
+
# Return a list of citation references in document, sorted into order
|
27
|
+
def sorted_cites biblio
|
28
|
+
@cites_used.sort_by do |ref|
|
29
|
+
bibitem = biblio[ref]
|
30
|
+
|
31
|
+
unless bibitem.nil?
|
32
|
+
# extract the reference, and uppercase.
|
33
|
+
# Remove { } from grouped names for sorting.
|
34
|
+
author = bibitem.author
|
35
|
+
if author.nil?
|
36
|
+
author = bibitem.editor
|
37
|
+
end
|
38
|
+
author_chicago(author).collect {|s| s.upcase.gsub("{","").gsub("}","")} + [bibitem.year]
|
39
|
+
else
|
40
|
+
[ref]
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
# Utility functions for citations class
|
2
|
+
#
|
3
|
+
# Copyright (c) Peter Lane, 2013.
|
4
|
+
# Released under Open Works License, 0.9.2
|
5
|
+
|
6
|
+
module AsciidoctorBibliography
|
7
|
+
# Some utility functions used in Citations class
|
8
|
+
module CitationUtils
|
9
|
+
|
10
|
+
# Given a line, return a list of CitationData instances
|
11
|
+
# containing information on each set of citation information
|
12
|
+
def retrieve_citations line
|
13
|
+
result = []
|
14
|
+
md = CITATION_FULL.match line
|
15
|
+
while md
|
16
|
+
data = CitationData.new md[0], md[1], nil, []
|
17
|
+
cm = CITATION_KEY.match md[2]
|
18
|
+
while cm
|
19
|
+
pages = nil
|
20
|
+
if cm[2]
|
21
|
+
pages = cm[2][1...-1]
|
22
|
+
end
|
23
|
+
data.cites << Citation.new(cm[1], pages)
|
24
|
+
# look for next ref within citation
|
25
|
+
cm = CITATION_KEY.match cm.post_match
|
26
|
+
end
|
27
|
+
result << data
|
28
|
+
# look for next citation on line
|
29
|
+
md = CITATION_FULL.match md.post_match
|
30
|
+
end
|
31
|
+
|
32
|
+
return result
|
33
|
+
end
|
34
|
+
|
35
|
+
# arrange author string, flag for order of surname/initials
|
36
|
+
def arrange_authors authors, surname_first
|
37
|
+
return [] if authors.nil?
|
38
|
+
authors.split(/\band\b/).collect do |name|
|
39
|
+
if name.include?(", ")
|
40
|
+
parts = name.strip.rpartition(", ")
|
41
|
+
if surname_first
|
42
|
+
"#{parts.first}, #{parts.third}"
|
43
|
+
else
|
44
|
+
"#{parts.third} #{parts.first}"
|
45
|
+
end
|
46
|
+
else
|
47
|
+
name
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
# Arrange given author string into Chicago format
|
53
|
+
def author_chicago authors
|
54
|
+
arrange_authors authors, true
|
55
|
+
end
|
56
|
+
|
57
|
+
# matches a citation key, such as 'Dan2012(99-100)'
|
58
|
+
CITATION_KEY = /([^\s,()\[\]]+)(\(\d+(-\d+)*\))?/
|
59
|
+
# matches a citation type
|
60
|
+
CITATION_TYPE = /cite|citenp|fullcite/
|
61
|
+
# matches a citation list
|
62
|
+
CITATION_LIST_TAIL = /(\s*,\s*#{CITATION_KEY})*/
|
63
|
+
CITATION_LIST = /(?:#{CITATION_KEY}#{CITATION_LIST_TAIL})/
|
64
|
+
# matches the whole citation
|
65
|
+
CITATION_FULL = /(#{CITATION_TYPE}):\[(#{CITATION_LIST})\]/
|
66
|
+
end
|
67
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
# Some extension and helper methods.
|
2
|
+
#
|
3
|
+
# Copyright (c) Peter Lane, 2012-13.
|
4
|
+
# Released under Open Works License, 0.9.2
|
5
|
+
|
6
|
+
module AsciidoctorBibliographyArrayExtensions
|
7
|
+
|
8
|
+
# Retrieve the third item of an array
|
9
|
+
# Note: no checks for validity
|
10
|
+
def third
|
11
|
+
self[2]
|
12
|
+
end
|
13
|
+
|
14
|
+
# Join items in array using commas and 'and' on last item
|
15
|
+
def comma_and_join
|
16
|
+
if size < 2
|
17
|
+
return self.join("")
|
18
|
+
end
|
19
|
+
result = ""
|
20
|
+
self.each_with_index do |item, index|
|
21
|
+
if index.zero?
|
22
|
+
result << item
|
23
|
+
elsif index == size-1
|
24
|
+
result << " and #{item}"
|
25
|
+
else
|
26
|
+
result << ", #{item}"
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
return result
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
# monkey patch the extension methods to Array
|
35
|
+
class Array
|
36
|
+
include AsciidoctorBibliographyArrayExtensions
|
37
|
+
end
|
38
|
+
|
39
|
+
# Converts html output produced by citeproc to asciidoc markup
|
40
|
+
module StringHtmlToAsciiDoc
|
41
|
+
def html_to_asciidoc
|
42
|
+
r = self.gsub(/<\/?i>/, '_')
|
43
|
+
r = r.gsub(/<\/?b>/, '*')
|
44
|
+
r = r.gsub(/<\/?span.*?>/, '')
|
45
|
+
r = r.gsub(/\{|\}/, '')
|
46
|
+
r
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
# Provides a check that a string is in integer
|
51
|
+
# Taken from:
|
52
|
+
# http://stackoverflow.com/questions/1235863/test-if-a-string-is-basically-an-integer-in-quotes-using-ruby
|
53
|
+
module IntegerCheck
|
54
|
+
def is_i?
|
55
|
+
!!(self =~ /^[-+]?[0-9]+$/)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
# monkey patch the extension methods into String
|
60
|
+
class String
|
61
|
+
include StringHtmlToAsciiDoc
|
62
|
+
include IntegerCheck
|
63
|
+
end
|
64
|
+
|
@@ -0,0 +1,32 @@
|
|
1
|
+
#
|
2
|
+
# filehandlers.rb
|
3
|
+
# Contains top-level file utility methods
|
4
|
+
#
|
5
|
+
|
6
|
+
module AsciidoctorBibliography
|
7
|
+
|
8
|
+
module FileHandlers
|
9
|
+
# Locate a bibliography file to read in given dir
|
10
|
+
def FileHandlers.find_bibliography dir
|
11
|
+
begin
|
12
|
+
candidates = Dir.glob("#{dir}/*.bib")
|
13
|
+
if candidates.empty?
|
14
|
+
return ""
|
15
|
+
else
|
16
|
+
return candidates.first
|
17
|
+
end
|
18
|
+
rescue # catch all errors, and return empty string
|
19
|
+
return ""
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
# Add '-ref' before the extension of a filename
|
24
|
+
def FileHandlers.add_ref filename
|
25
|
+
file_dir = File.dirname(File.expand_path(filename))
|
26
|
+
file_base = File.basename(filename, ".*")
|
27
|
+
file_ext = File.extname(filename)
|
28
|
+
return "#{file_dir}#{File::SEPARATOR}#{file_base}-ref#{file_ext}"
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module AsciidoctorBibliography
|
2
|
+
class Index
|
3
|
+
attr_reader :parent, :target, :attrs, :uuid
|
4
|
+
|
5
|
+
def initialize(parent, target, attrs, uuid)
|
6
|
+
@parent = parent
|
7
|
+
@target = target
|
8
|
+
@attrs = attrs
|
9
|
+
@uuid = uuid
|
10
|
+
end
|
11
|
+
|
12
|
+
def placeholder
|
13
|
+
"{#{uuid}}"
|
14
|
+
end
|
15
|
+
|
16
|
+
# attr_reader :ref, :pages
|
17
|
+
|
18
|
+
# def initialize ref, pages
|
19
|
+
# @ref = ref
|
20
|
+
# @pages = pages
|
21
|
+
# # clean up pages
|
22
|
+
# @pages = '' unless @pages
|
23
|
+
# @pages.gsub!("--","-")
|
24
|
+
# end
|
25
|
+
|
26
|
+
# def to_s
|
27
|
+
# "#{@ref}:#{@pages}"
|
28
|
+
# end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|