kramdown-latexish 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 06fa0ad97174ba629adeb406d91151b6b4aba7fc47d0b3b8e33d2b9aa147e722
4
+ data.tar.gz: d9af99b898053cd8dc701fac591520eba772855ad2e479197c1b0b90f048098b
5
+ SHA512:
6
+ metadata.gz: 54597cc241e9985853017b5f3e56140917d0b898ad7d8451c9701b77db625f59060a110867a37acbf35b6750f88fdbe465797c97cd1e6f2b1d031d2495d4860c
7
+ data.tar.gz: ebaacce34386a0ea7fce3c848891e7f4e9e22f018f026bd53d4b2d60814c7b901ba33f12f9b59fe6adcbb881f9d9bde929e093f99a81b5dc982edf681965dce9
data/.gitignore ADDED
@@ -0,0 +1,11 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /_yardoc/
4
+ /coverage/
5
+ /doc/
6
+ /pkg/
7
+ /spec/reports/
8
+ /tmp/
9
+
10
+ # rspec failure tracking
11
+ .rspec_status
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --format documentation
2
+ --color
3
+ --require spec_helper
data/.ruby-version ADDED
@@ -0,0 +1 @@
1
+ 3.0.6
data/.travis.yml ADDED
@@ -0,0 +1,6 @@
1
+ ---
2
+ sudo: false
3
+ language: ruby
4
+ cache: bundler
5
+ # Ruby version specified by .ruby-version
6
+ before_install: gem install bundler -v 2.2.33
data/Gemfile ADDED
@@ -0,0 +1,6 @@
1
+ source "https://rubygems.org"
2
+
3
+ git_source(:github) {|repo_name| "https://github.com/#{repo_name}" }
4
+
5
+ # Specify your gem's dependencies in kramdown-latexish.gemspec
6
+ gemspec
data/Gemfile.lock ADDED
@@ -0,0 +1,82 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ kramdown-latexish (1.0.0)
5
+ bibtex-ruby (~> 6.0)
6
+ citeproc-ruby (~> 2.0)
7
+ csl-styles (~> 2.0)
8
+ kramdown (~> 2.4)
9
+
10
+ GEM
11
+ remote: https://rubygems.org/
12
+ specs:
13
+ ast (2.4.2)
14
+ bibtex-ruby (6.0.0)
15
+ latex-decode (~> 0.0)
16
+ binding_of_caller (1.0.0)
17
+ debug_inspector (>= 0.0.1)
18
+ citeproc (1.0.10)
19
+ namae (~> 1.0)
20
+ citeproc-ruby (2.0.0)
21
+ citeproc (~> 1.0, >= 1.0.9)
22
+ csl (~> 2.0)
23
+ coderay (1.1.3)
24
+ csl (2.0.0)
25
+ namae (~> 1.0)
26
+ rexml
27
+ csl-styles (2.0.1)
28
+ csl (~> 2.0)
29
+ debug_inspector (1.1.0)
30
+ diff-lcs (1.5.0)
31
+ kramdown (2.4.0)
32
+ rexml
33
+ latex-decode (0.4.0)
34
+ namae (1.1.1)
35
+ parser (3.2.2.1)
36
+ ast (~> 2.4.1)
37
+ proc_to_ast (0.1.0)
38
+ coderay
39
+ parser
40
+ unparser
41
+ rake (10.5.0)
42
+ rexml (3.2.5)
43
+ rspec (3.12.0)
44
+ rspec-core (~> 3.12.0)
45
+ rspec-expectations (~> 3.12.0)
46
+ rspec-mocks (~> 3.12.0)
47
+ rspec-core (3.12.2)
48
+ rspec-support (~> 3.12.0)
49
+ rspec-expectations (3.12.3)
50
+ diff-lcs (>= 1.2.0, < 2.0)
51
+ rspec-support (~> 3.12.0)
52
+ rspec-mocks (3.12.5)
53
+ diff-lcs (>= 1.2.0, < 2.0)
54
+ rspec-support (~> 3.12.0)
55
+ rspec-parameterized (1.0.0)
56
+ rspec-parameterized-core (< 2)
57
+ rspec-parameterized-table_syntax (< 2)
58
+ rspec-parameterized-core (1.0.0)
59
+ parser
60
+ proc_to_ast
61
+ rspec (>= 2.13, < 4)
62
+ unparser
63
+ rspec-parameterized-table_syntax (1.0.0)
64
+ binding_of_caller
65
+ rspec-parameterized-core (< 2)
66
+ rspec-support (3.12.0)
67
+ unparser (0.6.7)
68
+ diff-lcs (~> 1.3)
69
+ parser (>= 3.2.0)
70
+
71
+ PLATFORMS
72
+ x86_64-darwin-20
73
+
74
+ DEPENDENCIES
75
+ bundler (~> 2.2)
76
+ kramdown-latexish!
77
+ rake (~> 10.0)
78
+ rspec (~> 3.0)
79
+ rspec-parameterized (~> 1.0)
80
+
81
+ BUNDLED WITH
82
+ 2.2.33
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2023 Luc J. Bourhis
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,283 @@
1
+ # Kramdown::Latexish
2
+
3
+ It is an extension of the Kramdown syntax taylored for mathematical articles. Its general philosophy is to imitate LaTeX as much as possible without being too verbose. This document describes the new syntactical elements added to Kramdown. We refer the reader to the documentation of the API for guidance to use it.
4
+
5
+ ## New syntax
6
+
7
+ An important point is that each document has a language associated to it, and several concepts are then accordingly localised. We currently support English and French only but the code could easily be extended to support many more. We will provide HTML conversion as illustrations as it will be the main target but there is no conceptual reason the other converters should not work.
8
+
9
+ ### Equations
10
+
11
+ The only difference with vanilla Kramdown is that span math can be marked with single dollars, as it is customary in LaTeX, in addition to the double dollars used in vanilla Kramdown.
12
+
13
+ ```
14
+ The identity $e^{i\pi} + 1 = 0$ is attributed to Euler.
15
+ ```
16
+
17
+ will eventually produce the HTML
18
+
19
+ ```
20
+ <p>The identity \(e^{i\pi} + 1 = 0\) is attributed to Euler.</p>
21
+ ```
22
+
23
+ and so will
24
+
25
+ ```
26
+ The identity is $$e^{i\pi} + 1 = 0$$ it attributed to Euler.
27
+ ```
28
+
29
+ As in vanilla Kramdown, one shall write block equations as
30
+
31
+ ```
32
+ The identity
33
+
34
+ $$e^{i\pi} + 1 = 0$$
35
+
36
+ is attributed to Euler.
37
+ ```
38
+
39
+ exactly as in vanilla Kramdown. This produces
40
+
41
+ ```
42
+ <p>The identity</p>
43
+
44
+ \[ e^{i\pi} + 1 = 0 \]
45
+
46
+ <p>is attributed to Euler.</p>
47
+ ```
48
+
49
+ Typically, one shall then rely on MathJax to render `\(…\)` and `\[…\]`.
50
+
51
+ ### Theorem-like environments
52
+
53
+ Theorem-like environments look as follow.
54
+
55
+ ```
56
+ We shall first prove the following.
57
+
58
+ Lemma (Eigenspace orthogonality)
59
+
60
+ For any symmetric matrix $M$, and any two eigenvalues $\lambda \ne \lambda'$, the eigenvectors for $\lambda$ are orthogonal to the eigenvectors for $\lambda'$.
61
+
62
+ \Lemma
63
+
64
+ It can then be used to prove the following.
65
+
66
+ Theorem (Diagonalisation)
67
+
68
+ Any symmetric matrix can be diagonalised in an orthogonal basis.
69
+
70
+ \Theorem
71
+ ```
72
+ We have defined two such environments in this example, of two different types. We support the following types: :definition, :property, :lemma, :theorem, and :corollary, where we use a colon prefix to distinguish them from the English words. Each environment type is introduced by a capitalised name. In English, the types without the colon. In French: définition, propriété, lemme, théorème, et corollaire.
73
+
74
+ Such an environment starts with a new paragraph, whose first word is one of those environment names. There cannot be any space at the beginning of that paragraph. A title for the environment may then appear between parentheses. Then, after perhaps some spaces, the paragraph must end: the next paragraph will start the body of the theorem.
75
+
76
+ That body then extends until the environment name prefixed by a backlash. That end tag must be alone in its own paragraph, without any leading spaces but trailing spaces are allowed.
77
+
78
+ The body of the environment is parsed as any other part of the document whereas the title line is encased in a header, and the whole environment in a section with class "theorem-like". Thus the example above renders as
79
+
80
+ ```
81
+ <p>We shall first prove the following.</p>
82
+
83
+ <section class="theorem-like">
84
+ <h5><strong>Lemma 1</strong> (Eigenspace orthogonality)</h5>
85
+
86
+ <p>For any symmetric matrix $M$, and any two eigenvalues $\lambda \ne \lambda'$, the eigenvectors for $\lambda$ are orthogonal to the eigenvectors for $\lambda'$.</p>
87
+
88
+ </section>
89
+
90
+ <p>It can then be used to prove the following.</p>
91
+
92
+ <section class="theorem-like">
93
+ <h5><strong>Theorem 1</strong> (Diagonalisation)</h5>
94
+
95
+ <p>Any symmetric matrix can be diagonalised in an orthogonal basis.</p>
96
+
97
+ </section>
98
+ ```
99
+ A few remarks are in order:
100
+ - the level of the header is user-customisable (h5 is the default)
101
+ - as shown, each environment is numbered, with a different numbering for each type
102
+
103
+ The first line of the environment can receives Kramdown IAL's in the usual manner
104
+ ```
105
+ {: #Euler}
106
+ Theorem
107
+
108
+ \Theorem
109
+ ```
110
+ or
111
+ ```
112
+ Theorem
113
+ {: #Euler}
114
+
115
+ \Theorem
116
+ ```
117
+
118
+ Either of those would result in the `<section>` tag to be be given the identifier `Euler`.
119
+
120
+ ### Automatically numbered section headers
121
+
122
+ Sections as well as all theorem-like environment are automatically numbered.
123
+
124
+ Section numbers follow the pattern x.y.z, for example
125
+
126
+ ```
127
+ ## One
128
+
129
+ ### One
130
+
131
+ ### Two
132
+
133
+ ## Two
134
+ ```
135
+
136
+ would result in
137
+
138
+ ```
139
+ <h2>1 One</h2>
140
+
141
+ <h3>1.1 One</h3>
142
+
143
+ <h3>1.2 Two</h3>
144
+
145
+ <h2>2 Two<h2>
146
+ ```
147
+
148
+ A single number is used for theorem-like environment, each type being numbered separately. For example,
149
+
150
+ ```
151
+ Theorem (Taylor-Young)
152
+
153
+ \Theorem
154
+
155
+ Lemma (Rolle)
156
+
157
+ \Lemma
158
+
159
+ Theorem (Taylor-Cauchy)
160
+
161
+ \Theorem
162
+ ```
163
+
164
+ would result in `Theorem 1 (Taylor-Young)`, `Theorem 2 (Taylor-Cauchy)`, and `Lemma 1 (Rolle)`.
165
+
166
+ ### Referencing sections or theorem-like environments
167
+
168
+ If a section or a theorem-like environment was given an identifier `xxx`, either with an IAL `{: ... #xxx ...}` or for a section the special syntax `{#xxx}`, then the syntax
169
+ `[cref:xxx]` will produce the like of
170
+
171
+ ```
172
+ section <a href="#xxx" title="Section 5">5</a>
173
+ ```
174
+
175
+ whereas `[Cref:xxx]` (note the capital letter) will then produce
176
+
177
+ ```
178
+ Section <a href="#xxx" title="Section 5">5</a>
179
+ ```
180
+
181
+ i.e. a link to that identifier, with the number as content, and with the type of the element referred to.
182
+
183
+ LaTeX users will recognise the cleveref package, from which we also borrow multiple references: `[cref:one,two,three,four,five,six]` will produce
184
+
185
+ ```
186
+ sections&nbsp;<a href="#two" title="Section 1.1">1.1</a>, <a href="#four" title="Section 3.2">3.2</a>, and&nbsp;<a href="#six" title="Section 1.8">1.8</a>, theorems&nbsp;<a href="#one" title="Theorem 1">1</a> and&nbsp;<a href="#five" title="Theorem 3">3</a>, and corollary&nbsp;<a href="#three" title="Corollary 5">5</a>
187
+ ```
188
+
189
+ if those id's had been assigned to the corresponding sections and environments. As can be seen, the spaces between "sections", "theorems", "corollary" and the following anchor are actually non-breakable (`&nbsp;`), and so are the spaces following the word "and".
190
+
191
+ The words used to introduce the anchors are of course localised in the document language. As for equations, they are typeset as `eqn \eqref{key}` and `eqns \eqref{key} and \eqref{other_key}`, with non-breakable spaces before the `\eqref`. This way, Mathjax will be able to put the numbers for the equations which were marked with `\label{key}`.
192
+
193
+ ### Bibliography and citations
194
+
195
+ Bibliographic entries come from a file or a string in BibTeX format, in which each entry must have a key. A reference section will be added at the end of the document, introduced by a level-2 header titled "References" in English and "Références" in French. It will contain only those entries that are cited in the document, thus skipping the entries in the BibTeX input which do not appear in the main body of the document.
196
+
197
+ The user can choose the style used to format it, among those supported by CSL. A list can be found [here](https://github.com/citation-style-language/styles). Each entry will be wrapped in a paragraph with a class "bibliography-item" to make it easy to customize styling. With the APA style, it would for example looks like this
198
+ ```
199
+ <p class="bibliography-item" id="Einstein1905"> Einstein, A. (1905). Zur Elektrodynamik bewegter Körper. <i>Annalen Der Physik</i>, <i>17</i>, 891.</p>
200
+ ```
201
+
202
+ Two types of citations can be made, a parenthical one,
203
+ ```
204
+ [citep: Einstein1905]
205
+ ```
206
+ will give
207
+ ```
208
+ <a href="#Einstein1905">(Einstein, 1905)</a>
209
+ ```
210
+ and a textual one,
211
+ ```
212
+ [citet: Einstein1905]
213
+ ```
214
+ will give
215
+ ```
216
+ <a href="#Einstein:SR">Einstein (1905)</a>
217
+ ```
218
+ Thus the citation is always typeset with the surname and the year of publication, using the notation from the natbib LaTeX package
219
+
220
+ When there are several authors, they all appear, for example
221
+ ```
222
+ <p><a href="#Lammerzahl_etal">(Lämmerzahl, Braxmaier, Dittus, Müller, Peters, and Schiller, 2002)</a></p>
223
+ ```
224
+ except if the BibTeX key is preceded by a star, i.e.
225
+ ```
226
+ [citet: *Lammerzahl_etal]
227
+ ```
228
+ will give
229
+ ```
230
+ <a href="#Lammerzahl_etal">Lämmerzahl et al (1975)</a>
231
+ ```
232
+ instead.
233
+
234
+ Finaly, several citations can be made in one instruction
235
+ ```
236
+ [citep: citeX, citeY, citeZ]
237
+ ```
238
+ resulting in those citations being combined in a conjunction with commans and a final word "and", in the same manner as for the references to sections, theorem-like environments and equations described in the previous section.
239
+
240
+
241
+ ## Installation
242
+
243
+ Add this line to your application's Gemfile:
244
+
245
+ ```ruby
246
+ gem 'kramdown-latexish'
247
+ ```
248
+
249
+ And then execute:
250
+
251
+ $ bundle
252
+
253
+ Or install it yourself as:
254
+
255
+ $ gem install kramdown-latexish
256
+
257
+ ## Usage
258
+
259
+ Given a string `source` and a hash `options` (c.f. [Kramdown documentation](https://kramdown.gettalong.org/rdoc/Kramdown/Options.html)), the following snippet will convert the extended Kramdown in that string into HTML
260
+
261
+ ```ruby
262
+ require 'kramdown/latexish'
263
+
264
+ options = Kramdown::Latexish::taylor_options(options)
265
+ doc = Kramdown::Document.initialize(source, options)
266
+ converted = doc.html
267
+ ```
268
+
269
+ The rationales for this design is explained in the documentation for method `Kramdown::Latexish::taylor_options`.
270
+
271
+ ## Development
272
+
273
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
274
+
275
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
276
+
277
+ ## Contributing
278
+
279
+ Bug reports and pull requests are welcome on GitHub at https://github.com/luc-j-bourhis/kramdown-latexish.
280
+
281
+ ## License
282
+
283
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
data/Rakefile ADDED
@@ -0,0 +1,6 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task :default => :spec
data/bin/console ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "kramdown/latexish"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require "irb"
14
+ IRB.start(__FILE__)
data/bin/setup ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,41 @@
1
+ lib = File.expand_path("../lib", __FILE__)
2
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
3
+ require "kramdown/latexish/version"
4
+
5
+ Gem::Specification.new do |spec|
6
+ spec.name = "kramdown-latexish"
7
+ spec.version = Kramdown::Latexish::VERSION
8
+ spec.authors = ["Luc J. Bourhis"]
9
+ spec.email = ["luc_j_bourhis@mac.com"]
10
+
11
+ spec.summary = %q{An extension of Kramdown taylored for math-heavy documents.}
12
+ spec.description = %q{It provides theorem environments, and easy references to those environments as well as to equations and section headers. Moreover, a bibliography section can be generated from a BibTeX file, and an flexible and easy mean of citing bibliographical entries is provided.}
13
+ spec.homepage = "https://github.com/luc-j-bourhis/kramdown-latexish"
14
+ spec.license = "MIT"
15
+
16
+ # Specify which files should be added to the gem when it is released.
17
+ # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
18
+ spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
19
+ `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
20
+ end
21
+ spec.bindir = "exe"
22
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
23
+ spec.require_paths = ["lib"]
24
+
25
+ spec.add_development_dependency "bundler", "~> 2.2"
26
+ spec.add_development_dependency "rake", "~> 10.0"
27
+ spec.add_development_dependency "rspec", "~> 3.0"
28
+ spec.add_development_dependency "rspec-parameterized", "~> 1.0"
29
+
30
+ # We extend this
31
+ spec.add_runtime_dependency "kramdown", "~> 2.4"
32
+
33
+ # BibTeX bibliography tools
34
+ spec.add_runtime_dependency 'bibtex-ruby', "~> 6.0"
35
+
36
+ # Render bibliography to HTML
37
+ spec.add_runtime_dependency 'citeproc-ruby', "~> 2.0"
38
+
39
+ # Bibliography styles
40
+ spec.add_runtime_dependency 'csl-styles', "~> 2.0"
41
+ end
@@ -0,0 +1,75 @@
1
+ require 'latex/decode'
2
+
3
+ module Kramdown::Latexish
4
+
5
+ # An extension dealing with BibTeX
6
+ #
7
+ # Mostly so that we can test those methods independently of our Kramdown
8
+ # parser and converter
9
+ #
10
+ # The class this is included into shall provide the following methods:
11
+ #
12
+ # bibliography:
13
+ # An instance of BibTeX::Bibliography holding the references
14
+ #
15
+ # lexical_and:
16
+ # The conjonction of a sequence of words with commas and the word "and"
17
+ # C.f. module Lexical for the requirements
18
+ module Bibliographical
19
+ # Clean BibTeX field (typically the title)
20
+ #
21
+ # 1. It converts accents, diacritics, etc to unicode.
22
+ # This is implemented withu bits and pieces of the latex-decode library.
23
+ # We cannot use its main function LaTeX::decode because it removes
24
+ # the dollars around equations, and all braces including in equations.
25
+ # 2. It strips the braces outside formulae.
26
+ # Example: "{A} proof of $G_{\mu\nu} = 8\pi T_{\mu\nu}$ by {E}instein"
27
+ # must become "A proof of $G_{\mu\nu} = 8\pi T_{\mu\nu}$ by Einstein"
28
+ # 3. It puts `\ce{...}` between dollars so that MathJax can eventually
29
+ # display it
30
+ def clean_bibtex(txt)
31
+ # Let latex-decode do the bulk of the work
32
+ LaTeX::Decode::Base.normalize(txt)
33
+ LaTeX::Decode::Accents.decode!(txt)
34
+ LaTeX::Decode::Diacritics.decode!(txt)
35
+ LaTeX::Decode::Punctuation.decode!(txt)
36
+ LaTeX::Decode::Symbols.decode!(txt)
37
+ LaTeX::Decode::Greek.decode!(txt)
38
+
39
+ # Protect \ce
40
+ txt.gsub!(/(\\ce\{.*?\})/, '$\1$')
41
+
42
+ # Remove braces outside equations
43
+ txt.chars.map do |c|
44
+ if c == '$' ... c == '$'
45
+ c
46
+ elsif c != '{' and c != '}'
47
+ c
48
+ else
49
+ next
50
+ end
51
+ end.compact.join
52
+ end
53
+
54
+ # Text of the citation for the given bibtex key
55
+ def citation_for(key, style, et_al, loc)
56
+ unless (e = bibliography[key]).nil?
57
+ authors = e.authors.map(&:last)
58
+ authors_s = authors.size == 1 ? authors[0]
59
+ : et_al ? "#{authors[0]} et al"
60
+ : @lex.and(authors)
61
+ case style
62
+ when :parenthetical
63
+ "(#{authors_s}, #{e.year})"
64
+ when :textual
65
+ "#{authors_s} (#{e.year})"
66
+ else
67
+ raise "Unknown citation style: #{style.to_s}"
68
+ end
69
+ else
70
+ warning("Unknown bibliographic citation at line #{loc}")
71
+ "??#{key}??"
72
+ end
73
+ end
74
+ end
75
+ end