Skip to content

Commit 5b1a4e8

Browse files
Individual cite links (#363)
* initial draft of separate citation links * make separating links optional, add single test * fix tests that were broken by csl style changes
1 parent 459f94d commit 5b1a4e8

5 files changed

Lines changed: 94 additions & 6 deletions

File tree

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ description of all options and their defaults, see
7373
| `group_order` | `ascending` | Ordering for groups is specified in the same way as the sort order. Publication types -- specified with group key `type`, can be ordered by adding `type_order` to the configuration. For example, `type_order: [article,techreport]` lists journal articles before technical reports. Types not mentioned in `type_order` are considered smaller than types that are mentioned. Types can be merge in one group using the `type_aliases` setting. By default `phdthesis` and `mastersthesis` are grouped as `thesis`. By using, for example, `type_aliases: { inproceedings: article}`, journal and conference articles appear in a single group. The display names for entry types are specified with `type_names`. Names for common types are provided, but they can be extended or overridden. For example, the default name for `article` is *Journal Articles*, but it can be changed to *Papers* using `type_names: { article: Papers }`. |
7474
| `bibtex_filters` | `latex,smallcaps,superscript` | Configures which [BibTeX-Ruby](https://github.com/inukshuk/bibtex-ruby) formatting filters values of entries should be passed through. The default `latex` filter converts LaTeX character escapes into unicode, `smallcaps` converts the `\textsc` command into a HTML `<font style=\"font-variant: small-caps\">` tag, and `superscript` which converts the `\textsuperscript` command into a HTML `<sup>` tag. |
7575
| `raw_bibtex_filters` | ` ` | Configures which [BibTeX-Ruby](https://github.com/inukshuk/bibtex-ruby) formatting filters the raw BiBTeX entry (i.e. that available through `{{ entry.bibtex }}`) should be passed through. This can be used to e.g. strip excess newlines by using the `linebreaks` filter. |
76+
| `separate_links` | `false` | Experimental: If `true`, render each in-text citation in a citation group as a separate link (e.g. `[1, 2, 3]` would have 3 links, one to each citation). Otherwise, only render a single link to the first citation (default). May not work with citation styles that abbreviate ranges of citations, e.g. `[1-3]`. |
7677

7778

7879
### Bibliographies

features/bibtex.feature

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -524,7 +524,7 @@ Feature: BibTeX
524524
| source | ./_bibliography |
525525
| bibliography | my_references |
526526
| allow_locale_overrides | true |
527-
| style | chicago-fullnote-bibliography |
527+
| style | chicago-notes-bibliography |
528528
And I have a "_bibliography" directory
529529
And I have a file "_bibliography/my_references.bib":
530530
"""

features/citation.feature

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -352,7 +352,7 @@ Feature: Citations
352352
When I run jekyll
353353
Then the _site directory should exist
354354
And the "_site/scholar.html" file should exist
355-
And I should see "Matsumoto, 2008, Chapters 2-3; Shaughnessy, 2013, figs. 4,5" in "_site/scholar.html"
355+
And I should see "Matsumoto, 2008, Chapters 2-3; Shaughnessy, 2013, Figures 4,5" in "_site/scholar.html"
356356

357357
@tags @cite @locator @label
358358
Scenario: Citations with multiple locator labels
@@ -554,3 +554,38 @@ Feature: Citations
554554
And I should see "Flanagan" in "_site/scholar.html"
555555
And I should see "Gamma" in "_site/scholar.html"
556556

557+
@tags @cite
558+
Scenario: Multiple Citations with separate links
559+
Given I have a scholar configuration with:
560+
| key | value |
561+
| source | ./_bibliography |
562+
| bibliography | my_references |
563+
| separate_links | true |
564+
And I have a "_bibliography" directory
565+
And I have a file "_bibliography/my_references.bib":
566+
"""
567+
@book{ruby,
568+
title = {The Ruby Programming Language},
569+
author = {Flanagan, David and Matsumoto, Yukihiro},
570+
year = {2008},
571+
publisher = {O'Reilly Media}
572+
}
573+
574+
@book{microscope,
575+
title = {Ruby Under a Microscope},
576+
author = {Pat Shaughnessy},
577+
year = {2013},
578+
publisher = {No Starch Press}
579+
}
580+
"""
581+
And I have a page "scholar.html":
582+
"""
583+
---
584+
---
585+
{% cite ruby microscope %}
586+
"""
587+
When I run jekyll
588+
Then the _site directory should exist
589+
And the "_site/scholar.html" file should exist
590+
And I should see "\(<a.*href=\"#ruby\".*</a>; <a.*href=\"#microscope\".*</a>\)" in "_site/scholar.html"
591+

lib/jekyll/scholar/defaults.rb

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,11 +60,11 @@ class Scholar
6060
# Valid template parameters:
6161
# ":details_dir" The value of the details_dir field in the scholar config
6262
# ":key" The bibtex citation key.
63-
# ":doi" The DOI. If the DOI is missing or blank, this returns the citation key.
63+
# ":doi" The DOI. If the DOI is missing or blank, this returns the citation key.
6464
# ":extension" Either of ".html" or "/index.html" depending upon the global permalink setting.
6565
# Template parameters can also include any key defined in the bibtex file, e.g. ":year", ":title", etc.
6666
# Bibtex keys such as 'title' are slugified in the same way as Jekyll treats blog post titles.
67-
'details_permalink' => '/:details_dir/:key:extension',
67+
'details_permalink' => '/:details_dir/:key:extension',
6868

6969
'bibliography_class' => 'bibliography',
7070
'bibliography_template' => '{{reference}}',
@@ -78,6 +78,12 @@ class Scholar
7878

7979
'cite_class' => 'citation',
8080

81+
# If true, render in-page links from in-text citations to references as separate links (one link per citation).
82+
# If false, render as only one link to the first citation.
83+
# Note: This feature may not work with citation styles that group in-text citations
84+
# like `[1-3]` rather than `[1, 2, 3]`
85+
'separate_links' => false,
86+
8187
'type_names' => {
8288
'article' => 'Journal Articles',
8389
'book' => 'Books',

lib/jekyll/scholar/utilities.rb

Lines changed: 48 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -501,6 +501,30 @@ def style
501501
interpolate(@style)|| config['style']
502502
end
503503

504+
# The citation layout object for the currently selected style
505+
# @return [CSL::Style::Layout]
506+
def layout
507+
styles(style).citation.layout
508+
end
509+
510+
# Prefix string before citations. If style has no prefix, return empty string
511+
# @return [String]
512+
def csl_prefix
513+
layout.attributes.prefix.nil? ? '' : layout.attributes.prefix
514+
end
515+
516+
# Suffix string after citations. If style has no suffix, return empty string
517+
# @return [String]
518+
def csl_suffix
519+
layout.attributes.suffix.nil? ? '' : layout.attributes.suffix
520+
end
521+
522+
# Delimiter between citations in a citation group
523+
# @return [String]
524+
def delimiter
525+
layout.delimiter
526+
end
527+
504528
def missing_reference
505529
config['missing_reference']
506530
end
@@ -742,14 +766,33 @@ def cite(keys)
742766
if bibliography.key?(key)
743767
entry = bibliography[key]
744768
cite_cache.getset(key) do
745-
entry.convert(*bibtex_filters) unless bibtex_filters.empty?
769+
entry = entry.convert(*bibtex_filters) unless bibtex_filters.empty?
770+
771+
if config['separate_links']
772+
## Render each citation in the group as a separate link
773+
# Render the single citation, stripping delimiting characters
774+
rendered = render_citation([entry])
775+
.sub(/^#{Regexp.escape(csl_prefix)}/, '')
776+
.sub(/#{Regexp.escape(csl_suffix)}$/, '')
777+
778+
# Then render to HTML with the link to this specific citation
779+
link_to link_target_for(key), rendered, {class: config['cite_class']}
780+
else
781+
entry
782+
end
746783
end
747784
else
748785
return missing_reference
749786
end
750787
end
751788

752-
link_to link_target_for(keys[0]), render_citation(items), {class: config['cite_class']}
789+
if config['separate_links']
790+
# Combine individual linkified items
791+
csl_prefix + items.join(delimiter) + csl_suffix
792+
else
793+
# Render as a single link
794+
link_to link_target_for(keys[0]), render_citation(items), {class: config['cite_class']}
795+
end
753796
end
754797

755798
def nocite(keys)
@@ -828,6 +871,7 @@ def set_context_to(context)
828871
self
829872
end
830873

874+
# @return [CSL::Style]
831875
def load_style(uri)
832876
begin
833877
style = CSL::Style.load uri
@@ -847,6 +891,8 @@ def load_style(uri)
847891
end
848892
end
849893

894+
# Access or load style by style URI or relative path
895+
# @return [CSL::Style]
850896
def styles(style)
851897
STYLES[style] ||= load_style(style)
852898
end

0 commit comments

Comments
 (0)