├── spec ├── fixtures │ ├── database.unk │ ├── database.bibtex │ ├── database-issue84.bib │ ├── database.bib │ └── database.rfc.xml ├── throwaway_spec.rb ├── index_spec.rb ├── integration_spec.rb ├── csl │ └── styles │ │ ├── tex_citealp_numeric_spec.rb │ │ ├── tex_citep_numeric_spec.rb │ │ ├── tex_citeps_numeric_spec.rb │ │ ├── tex_citealps_numeric_spec.rb │ │ ├── tex_citeyear_numeric_spec.rb │ │ ├── tex_citeyear_authoryear_spec.rb │ │ ├── tex_citeyearpar_numeric_spec.rb │ │ ├── tex_citeyearpar_authoryear_spec.rb │ │ ├── rfc_v2_spec.rb │ │ ├── rfc_v3_spec.rb │ │ ├── tex_citealt_numeric_spec.rb │ │ ├── tex_citeauthor_numeric_spec.rb │ │ ├── tex_citeauthor_authoryear_spec.rb │ │ ├── tex_citealt_authoryear_spec.rb │ │ ├── tex_citet_authoryear_spec.rb │ │ ├── tex_citep_authoryear_spec.rb │ │ ├── tex_citealp_authoryear_spec.rb │ │ ├── tex_citet_numeric_spec.rb │ │ ├── tex_citealts_numeric_spec.rb │ │ ├── tex_citeauthors_numeric_spec.rb │ │ ├── tex_citeauthors_authoryear_spec.rb │ │ ├── tex_citealts_authoryear_spec.rb │ │ ├── tex_citets_authoryear_spec.rb │ │ ├── tex_citeps_authoryear_spec.rb │ │ ├── tex_citealps_authoryear_spec.rb │ │ └── tex_citets_numeric_spec.rb ├── citation_helper.rb ├── citeproc │ └── ruby │ │ └── formats │ │ └── adoc_spec.rb ├── nocite_spec.rb ├── end_to_end_spec.rb ├── database_spec.rb ├── macros_spec.rb └── citation_item_spec.rb ├── .rspec ├── Gemfile ├── .hound.yml ├── .codeclimate.yml ├── lib ├── asciidoctor-bibliography │ ├── version.rb │ ├── asciidoctor │ │ ├── document_ext.rb │ │ └── bibliographer_preprocessor.rb │ ├── asciidoctor.rb │ ├── errors.rb │ ├── formatter.rb │ ├── bibliographer.rb │ ├── citation_item.rb │ ├── database.rb │ ├── databases │ │ ├── rfc.rb │ │ └── bibtex.rb │ └── index.rb ├── asciidoctor-bibliography.rb ├── csl │ └── styles │ │ ├── rfc-v2.csl │ │ ├── rfc-v3.csl │ │ ├── tex-citealp-numeric.csl │ │ ├── tex-citealps-numeric.csl │ │ ├── tex-citeauthor-numeric.csl │ │ ├── tex-citeauthors-numeric.csl │ │ ├── tex-citeauthor-authoryear.csl │ │ ├── tex-citeauthors-authoryear.csl │ │ ├── tex-citep-numeric.csl │ │ ├── tex-citeps-numeric.csl │ │ ├── tex-citeyear-numeric.csl │ │ ├── tex-citeyear-authoryear.csl │ │ ├── tex-citeyearpar-numeric.csl │ │ ├── tex-citeyearpar-authoryear.csl │ │ ├── tex-citealp-authoryear.csl │ │ ├── tex-citealps-authoryear.csl │ │ ├── tex-citep-authoryear.csl │ │ ├── tex-citeps-authoryear.csl │ │ ├── tex-citealt-numeric.csl │ │ ├── tex-citealts-numeric.csl │ │ ├── tex-citet-numeric.csl │ │ ├── tex-citets-numeric.csl │ │ ├── tex-citealt-authoryear.csl │ │ ├── tex-citealts-authoryear.csl │ │ ├── tex-citet-authoryear.csl │ │ └── tex-citets-authoryear.csl └── citeproc │ └── ruby │ └── formats │ └── adoc.rb ├── Rakefile ├── bin ├── setup └── rspec ├── .rubocop.yml ├── samples ├── latex_macros_in_bibtex │ ├── sample.adoc │ └── reference.bib ├── tex │ ├── sample-sort.adoc │ ├── biblio.bib │ ├── sample-authoryear.adoc │ └── sample-numbers.adoc └── standard │ ├── sample-targets.adoc │ ├── sample-ieee.adoc │ ├── sample-default.adoc │ ├── sample-din.adoc │ └── biblio.bib ├── LICENSE.txt ├── .github └── workflows │ └── test-and-release.yml ├── .gitignore ├── asciidoctor-bibliography.gemspec └── SYNTAX.adoc /spec/fixtures/database.unk: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.rspec: -------------------------------------------------------------------------------- 1 | --require spec_helper 2 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | source "https://rubygems.org" 2 | 3 | gemspec 4 | -------------------------------------------------------------------------------- /.hound.yml: -------------------------------------------------------------------------------- 1 | ruby: 2 | enabled: true 3 | config_file: .rubocop.yml 4 | -------------------------------------------------------------------------------- /.codeclimate.yml: -------------------------------------------------------------------------------- 1 | engines: 2 | rubocop: 3 | enabled: true 4 | config: 5 | file: .rubocop.yml 6 | -------------------------------------------------------------------------------- /lib/asciidoctor-bibliography/version.rb: -------------------------------------------------------------------------------- 1 | module AsciidoctorBibliography 2 | VERSION = "0.11.0".freeze 3 | end 4 | -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | require "bundler/gem_tasks" 2 | require "rspec/core/rake_task" 3 | 4 | RSpec::Core::RakeTask.new(:spec) 5 | 6 | task :default => :spec 7 | -------------------------------------------------------------------------------- /spec/fixtures/database.bibtex: -------------------------------------------------------------------------------- 1 | @article{Bar10, 2 | author = {F. Bar}, 3 | title = {Article title}, 4 | publisher = {Publisher}, 5 | year = {2010} 6 | } -------------------------------------------------------------------------------- /bin/setup: -------------------------------------------------------------------------------- 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 9 | -------------------------------------------------------------------------------- /spec/throwaway_spec.rb: -------------------------------------------------------------------------------- 1 | describe :throwaway do 2 | # This just covers a couple of trivial lines to better track coverage. 3 | # To be deleted when coverage is satisfactory. 4 | document = Asciidoctor::Document.new 5 | document.bibliographer 6 | end 7 | -------------------------------------------------------------------------------- /.rubocop.yml: -------------------------------------------------------------------------------- 1 | inherit_from: .oss-guides.rubocop.yml 2 | 3 | AllCops: 4 | TargetRubyVersion: 2.3 5 | 6 | # TODO: shorten all lines to 80, as per oss-guides. 7 | Metrics/LineLength: 8 | Max: 120 9 | Exclude: 10 | - 'spec/**/*_spec.rb' 11 | 12 | Rails: 13 | Enabled: false 14 | -------------------------------------------------------------------------------- /samples/latex_macros_in_bibtex/sample.adoc: -------------------------------------------------------------------------------- 1 | = Latex Macros In Bibtex Items 2 | :bibliography-database: reference.bib 3 | :bibliography-style: ieee 4 | 5 | == Contents 6 | 7 | This is a paper "Validation and Verificaton of Computer Forensic Software 8 | tools -- Searching Function" (see cite:guo2009[]). 9 | 10 | == Bibliography 11 | 12 | bibliography::[] 13 | 14 | -------------------------------------------------------------------------------- /lib/asciidoctor-bibliography.rb: -------------------------------------------------------------------------------- 1 | begin 2 | require "byebug" 3 | rescue LoadError 4 | end 5 | 6 | require_relative "asciidoctor-bibliography/asciidoctor" 7 | 8 | module AsciidoctorBibliography 9 | def self.root 10 | File.dirname __dir__ 11 | end 12 | 13 | def self.csl_styles_root 14 | File.join AsciidoctorBibliography.root, 15 | "lib/csl/styles" 16 | end 17 | end 18 | -------------------------------------------------------------------------------- /lib/asciidoctor-bibliography/asciidoctor/document_ext.rb: -------------------------------------------------------------------------------- 1 | # Extends Document to support additional method 2 | module AsciidoctorBibliography 3 | module Asciidoctor 4 | module DocumentExt 5 | # All our document-level permanence passes through this accessor. 6 | def bibliographer 7 | @bibliographer ||= AsciidoctorBibliography::Bibliographer.new 8 | end 9 | end 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /samples/tex/sample-sort.adoc: -------------------------------------------------------------------------------- 1 | = Sample usage of asciidoctor-bibliography 2 | :bibliography-database: biblio.bib 3 | :bibliography-tex-style: numeric 4 | :bibliography-style: ieee 5 | :bibliography-sort: { macro: author, sort: descending } 6 | 7 | 8 | ## Citations 9 | 10 | 11 | cite:[Lane12a] 12 | 13 | cite:[Lane12b] 14 | 15 | cite:[Anderson04] 16 | 17 | 18 | ## Bibliography 19 | 20 | 21 | bibliography::[] 22 | 23 | -------------------------------------------------------------------------------- /lib/asciidoctor-bibliography/asciidoctor.rb: -------------------------------------------------------------------------------- 1 | require "asciidoctor/extensions" 2 | 3 | require_relative "asciidoctor/bibliographer_preprocessor" 4 | require_relative "asciidoctor/document_ext" 5 | require_relative "bibliographer" 6 | 7 | Asciidoctor::Document.include AsciidoctorBibliography::Asciidoctor::DocumentExt 8 | 9 | Asciidoctor::Extensions.register do 10 | preprocessor AsciidoctorBibliography::Asciidoctor::BibliographerPreprocessor 11 | end 12 | -------------------------------------------------------------------------------- /samples/standard/sample-targets.adoc: -------------------------------------------------------------------------------- 1 | = Sample usage of asciidoctor-bibliography 2 | :bibliography-database: biblio.bib 3 | :bibliography-hyperlinks: true 4 | 5 | ## Standard 6 | 7 | cite:[Lane12a] 8 | 9 | cite:foo[Anderson04] 10 | 11 | cite:bar[Lane12a]+foo[Lane12b] 12 | 13 | ## Bibliographies 14 | 15 | ### Default 16 | 17 | bibliography::default[] 18 | 19 | ### Foo 20 | 21 | bibliography::foo[] 22 | 23 | ### Bar 24 | 25 | bibliography::bar[] 26 | -------------------------------------------------------------------------------- /samples/standard/sample-ieee.adoc: -------------------------------------------------------------------------------- 1 | = Sample usage of asciidoctor-bibliography 2 | :bibliography-database: biblio.bib 3 | :bibliography-style: ieee 4 | 5 | ## Standard 6 | 7 | cite:[Anderson04] 8 | 9 | cite:[Anderson04, page=10] 10 | 11 | cite:[Anderson04, chapter=10] 12 | 13 | cite:[Anderson04, page=10, chapter=12] 14 | 15 | cite:[Lane12a]+[Lane12b] 16 | 17 | cite:[Lane12a, page=42]+[Lane12b, opus=12] 18 | 19 | ## Bibliography 20 | 21 | bibliography::[] 22 | 23 | -------------------------------------------------------------------------------- /samples/standard/sample-default.adoc: -------------------------------------------------------------------------------- 1 | = Sample usage of asciidoctor-bibliography 2 | :bibliography-database: biblio.bib 3 | :bibliography-hyperlinks: true 4 | 5 | ## Standard 6 | 7 | cite:[Lane12a]+[Lane12b] 8 | 9 | cite:[Anderson04] 10 | 11 | cite:[Anderson04, page=10] 12 | 13 | cite:[Anderson04, chapter=10] 14 | 15 | cite:[Anderson04, page=10, chapter=12] 16 | 17 | cite:[Lane12a, page=42]+[Lane12b, opus=12] 18 | 19 | ## Bibliography 20 | 21 | bibliography::[] 22 | 23 | -------------------------------------------------------------------------------- /lib/asciidoctor-bibliography/errors.rb: -------------------------------------------------------------------------------- 1 | module AsciidoctorBibliography 2 | module Errors 3 | class Error < StandardError; end 4 | 5 | module Options 6 | class Missing < Error; end 7 | class Invalid < Error; end 8 | end 9 | 10 | module Database 11 | class UnsupportedFormat < Error; end 12 | class FileNotFound < Error; end 13 | class IdNotFound < Error; end 14 | class ConflictingIds < Error; end 15 | end 16 | end 17 | end 18 | -------------------------------------------------------------------------------- /samples/standard/sample-din.adoc: -------------------------------------------------------------------------------- 1 | = Sample usage of asciidoctor-bibliography 2 | :bibliography-database: biblio.bib 3 | :bibliography-style: din-1505-2-alphanumeric 4 | 5 | ## Standard 6 | 7 | cite:[Anderson04] 8 | 9 | cite:[Anderson04, page=10] 10 | 11 | cite:[Anderson04, chapter=10] 12 | 13 | cite:[Anderson04, page=10, chapter=12] 14 | 15 | cite:[Lane12a]+[Lane12b] 16 | 17 | cite:[Lane12a, page=42]+[Lane12b, opus=12] 18 | 19 | ## Bibliography 20 | 21 | bibliography::[] 22 | 23 | -------------------------------------------------------------------------------- /samples/latex_macros_in_bibtex/reference.bib: -------------------------------------------------------------------------------- 1 | @article{guo2009, 2 | title = {Validation and Verification of Computer Forensic Software 3 | tools\textemdash{}{{Searching Function}} 4 | {\url{http://www.csoonline.com/article/2122329/investigations-forensics/the-rise-of-anti-forensics.html}}}, 5 | volume = {6}, 6 | issn = {17422876}, 7 | doi = {10.1016/j.diin.2009.06.015}, 8 | language = {en}, 9 | timestamp = {2016-06-13T16:44:17Z}, 10 | urldate = {2016-06-13}, 11 | journal = {Digital Investigation}, 12 | author = {Guo, Yinghua and Slay, Jill and Beckett, Jason}, 13 | month = sep, 14 | year = {2009}, 15 | pages = {S12--S22} 16 | } 17 | -------------------------------------------------------------------------------- /spec/index_spec.rb: -------------------------------------------------------------------------------- 1 | # coding: utf-8 2 | 3 | require_relative "citation_helper" 4 | 5 | describe AsciidoctorBibliography::Index do 6 | describe ".render" do 7 | subject { described_class.new([], "default", "") } 8 | 9 | it "does not fail when no citations occur in the document" do 10 | options = { "bibliography-style" => "ieee", "bibliography-database" => "database.bibtex", "bibliography-passthrough" => "true", "bibliography-prepend-empty" => "false" } 11 | bibliographer = init_bibliographer options: options 12 | expect { subject.render bibliographer}.to_not raise_exception 13 | end 14 | end 15 | end 16 | -------------------------------------------------------------------------------- /samples/tex/biblio.bib: -------------------------------------------------------------------------------- 1 | @book{Lane12a, 2 | author = {P. Lane}, 3 | title = {Book title}, 4 | publisher = {Publisher}, 5 | year = {2000} 6 | } 7 | 8 | @book{Lane12b, 9 | author = {K. Mane and D. Smith}, 10 | title = {Book title}, 11 | publisher = {Publisher}, 12 | year = {2000} 13 | } 14 | 15 | @book{Anderson98, 16 | editor = {J. R. Anderson and C. Lebiere}, 17 | title = {The Atomic Components of {2\sum} Thought}, 18 | publisher = {Lawrence Erlbaum}, 19 | address = {Mahwah, NJ}, 20 | year = {1998} 21 | } 22 | 23 | @article{Anderson04, 24 | author = {J. R. Anderson and D. Bothell and M. D. Byrne and S. Douglass and C. Lebiere and Y. L. Qin}, 25 | title = {An integrated theory of the mind}, 26 | journal = {Psychological Review}, 27 | volume = {111}, 28 | number = {4}, 29 | pages = {1036--1060}, 30 | year = {2004} 31 | } 32 | -------------------------------------------------------------------------------- /samples/standard/biblio.bib: -------------------------------------------------------------------------------- 1 | @book{Lane12a, 2 | author = {P. Lane}, 3 | title = {Book title}, 4 | publisher = {Publisher}, 5 | year = {2000} 6 | } 7 | 8 | @book{Lane12b, 9 | author = {K. Mane and D. Smith}, 10 | title = {Book title}, 11 | publisher = {Publisher}, 12 | year = {2000} 13 | } 14 | 15 | @book{Anderson98, 16 | editor = {J. R. Anderson and C. Lebiere}, 17 | title = {The Atomic Components of {2\sum} Thought}, 18 | publisher = {Lawrence Erlbaum}, 19 | address = {Mahwah, NJ}, 20 | year = {1998} 21 | } 22 | 23 | @article{Anderson04, 24 | author = {J. R. Anderson and D. Bothell and M. D. Byrne and S. Douglass and C. Lebiere and Y. L. Qin}, 25 | title = {An integrated theory of the mind}, 26 | journal = {Psychological Review}, 27 | volume = {111}, 28 | number = {4}, 29 | pages = {1036--1060}, 30 | year = {2004} 31 | } 32 | -------------------------------------------------------------------------------- /bin/rspec: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # frozen_string_literal: true 3 | 4 | # 5 | # This file was generated by Bundler. 6 | # 7 | # The application 'rspec' is installed as part of a gem, and 8 | # this file is here to facilitate running it. 9 | # 10 | 11 | require "pathname" 12 | ENV["BUNDLE_GEMFILE"] ||= File.expand_path( 13 | "../../Gemfile", Pathname.new(__FILE__).realpath 14 | ) 15 | 16 | bundle_binstub = File.expand_path("bundle", __dir__) 17 | 18 | if File.file?(bundle_binstub) 19 | if File.read(bundle_binstub, 300) =~ /This file was generated by Bundler/ 20 | load(bundle_binstub) 21 | else 22 | abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. 23 | Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") 24 | end 25 | end 26 | 27 | require "rubygems" 28 | require "bundler/setup" 29 | 30 | load Gem.bin_path("rspec-core", "rspec") 31 | -------------------------------------------------------------------------------- /lib/csl/styles/rfc-v2.csl: -------------------------------------------------------------------------------- 1 | 2 | 27 | -------------------------------------------------------------------------------- /lib/csl/styles/rfc-v3.csl: -------------------------------------------------------------------------------- 1 | 2 | 27 | -------------------------------------------------------------------------------- /lib/asciidoctor-bibliography/formatter.rb: -------------------------------------------------------------------------------- 1 | require "citeproc" 2 | require "csl/styles" 3 | require "yaml" 4 | 5 | require_relative "../citeproc/ruby/formats/adoc" 6 | 7 | module AsciidoctorBibliography 8 | class Formatter < ::CiteProc::Processor 9 | def initialize(style, locale: "en-US") 10 | super style: style, format: :adoc, locale: locale 11 | end 12 | 13 | def replace_bibliography_sort(array) 14 | new_keys = array.map(&::CSL::Style::Sort::Key.method(:new)) 15 | new_sort = ::CSL::Style::Sort.new.add_children(*new_keys) 16 | 17 | bibliography = engine.style.find_child("bibliography") 18 | bibliography.find_child("sort")&.unlink 19 | 20 | bibliography.add_child new_sort 21 | end 22 | 23 | def force_sort!(mode:) 24 | # Valid modes are :citation and :bibliography 25 | engine.sort! data, engine.style.send(mode).sort_keys if engine.style.send(mode).sort? 26 | end 27 | end 28 | end 29 | -------------------------------------------------------------------------------- /lib/asciidoctor-bibliography/bibliographer.rb: -------------------------------------------------------------------------------- 1 | module AsciidoctorBibliography 2 | class Bibliographer 3 | attr_accessor :citations 4 | attr_accessor :indices 5 | attr_accessor :database 6 | attr_reader :occurring_keys 7 | attr_accessor :options 8 | 9 | def initialize 10 | @options = {} 11 | @citations = [] 12 | @indices = [] 13 | @database = nil 14 | @occurring_keys = {} 15 | end 16 | 17 | def add_citation(citation) 18 | citations << citation 19 | 20 | # NOTE: Since we're rendering the whole (possibly composite) citation as missing - even if 21 | # NOTE: a single key is nil - we add none of them to the occurring keys to be rendered in indices. 22 | return if citation.any_missing_id?(self) 23 | 24 | citation.citation_items.group_by(&:target).each do |target, citation_items| 25 | @occurring_keys[target] ||= [] 26 | @occurring_keys[target].concat(citation_items.map(&:key)).uniq! 27 | end 28 | end 29 | 30 | def appearance_index_of(target, id) 31 | @occurring_keys[target].index(id) + 1 32 | end 33 | end 34 | end 35 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2017 Ribose Inc. 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. 22 | -------------------------------------------------------------------------------- /lib/asciidoctor-bibliography/citation_item.rb: -------------------------------------------------------------------------------- 1 | require "asciidoctor/attribute_list" 2 | 3 | module AsciidoctorBibliography 4 | class CitationItem 5 | LOCATORS = CiteProc::CitationItem.labels.map(&:to_s).push("locator").freeze 6 | 7 | attr_accessor :key, :target, :positional_attributes, :named_attributes 8 | 9 | def initialize 10 | yield self if block_given? 11 | end 12 | 13 | def prefix 14 | named_attributes["prefix"] 15 | end 16 | 17 | def suffix 18 | named_attributes["suffix"] 19 | end 20 | 21 | def text 22 | named_attributes["text"] 23 | end 24 | 25 | def locators 26 | named_attributes.select { |key, _| LOCATORS.include? key } 27 | end 28 | 29 | def locator 30 | locators.first 31 | end 32 | 33 | def parse_attribute_list(string) 34 | parsed_attributes = ::Asciidoctor::AttributeList.new(string).parse 35 | self.named_attributes = parsed_attributes.reject { |key, _| key.is_a? Integer } 36 | self.positional_attributes = parsed_attributes.select { |key, _| key.is_a? Integer }.values 37 | self.key = positional_attributes.shift 38 | end 39 | end 40 | end 41 | -------------------------------------------------------------------------------- /spec/integration_spec.rb: -------------------------------------------------------------------------------- 1 | # coding: utf-8 2 | 3 | require "asciidoctor-bibliography" 4 | 5 | describe "rendering citations styles containing square brackets" do 6 | let(:parsed_document) do 7 | Asciidoctor::Document.new(<<~ADOC_INPUT).tap(&:parse) 8 | = Sample document 9 | :bibliography-database: spec/fixtures/database.bib 10 | :bibliography-hyperlinks: true 11 | :bibliography-style: ieee 12 | ... 13 | 14 | This paragraph contains a citation: cite:[Lane12a]. 15 | It also contains [.my-class]#some# inline styling. 16 | ADOC_INPUT 17 | end 18 | 19 | it "does not confuse rendered brackets with macro brackets in the paragraph" do 20 | # I.e. we're trying to avoid results like 21 | # ``` 22 | #

This paragraph contains a citation: some inline styling.

24 | # ``` 25 | expect(parsed_document.render).to eq(<<~HTML_OUTPUT.strip) 26 |
27 |

This paragraph contains a citation: [1]. 28 | It also contains some inline styling.

29 |
30 | HTML_OUTPUT 31 | end 32 | end 33 | -------------------------------------------------------------------------------- /.github/workflows/test-and-release.yml: -------------------------------------------------------------------------------- 1 | name: test-and-release 2 | 3 | on: 4 | push: 5 | branches: [ main ] 6 | tags: [ 'v*' ] 7 | pull_request: 8 | 9 | concurrency: 10 | group: '${{ github.workflow }}-${{ github.job }}-${{ github.head_ref || github.ref_name }}' 11 | cancel-in-progress: true 12 | 13 | jobs: 14 | test: 15 | name: Test on Ruby ${{ matrix.ruby }} ${{ matrix.os }} 16 | runs-on: ${{ matrix.os }} 17 | continue-on-error: false 18 | strategy: 19 | fail-fast: false 20 | matrix: 21 | ruby: [ '2.5', '2.6', '2.7', '3.0', '3.1' ] 22 | os: [ ubuntu-latest, windows-latest, macos-latest ] 23 | 24 | steps: 25 | - uses: actions/checkout@v3 26 | 27 | - uses: ruby/setup-ruby@v1 28 | with: 29 | ruby-version: ${{ matrix.ruby }} 30 | bundler-cache: true 31 | 32 | - run: bundle exec rspec 33 | 34 | release: 35 | name: Release gem 36 | needs: test 37 | runs-on: ubuntu-latest 38 | if: contains(github.ref, 'refs/tags/v') 39 | steps: 40 | - uses: actions/checkout@v3 41 | - uses: ruby/setup-ruby@v1 42 | with: 43 | ruby-version: 2.7 44 | bundler-cache: true 45 | - uses: cadwallion/publish-rubygems-action@master 46 | env: 47 | RUBYGEMS_API_KEY: ${{secrets.RIBOSE_RUBYGEMS_API_KEY}} 48 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.gem 2 | *.rbc 3 | /.config 4 | /coverage/ 5 | /InstalledFiles 6 | /pkg/ 7 | /spec/reports/ 8 | /spec/examples.txt 9 | /test/tmp/ 10 | /test/version_tmp/ 11 | /tmp/ 12 | 13 | # Used by dotenv library to load environment variables. 14 | # .env 15 | 16 | ## Specific to RubyMotion: 17 | .dat* 18 | .repl_history 19 | build/ 20 | *.bridgesupport 21 | build-iPhoneOS/ 22 | build-iPhoneSimulator/ 23 | 24 | ## Specific to RubyMotion (use of CocoaPods): 25 | # 26 | # We recommend against adding the Pods directory to your .gitignore. However 27 | # you should judge for yourself, the pros and cons are mentioned at: 28 | # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control 29 | # 30 | # vendor/Pods/ 31 | 32 | ## Documentation cache and generated files: 33 | /.yardoc/ 34 | /_yardoc/ 35 | /doc/ 36 | /rdoc/ 37 | 38 | ## Environment normalization: 39 | /.bundle/ 40 | /vendor/bundle 41 | /lib/bundler/man/ 42 | 43 | # for a library or gem, you might want to ignore these files since the code is 44 | # intended to run in multiple environments; otherwise, check them in: 45 | Gemfile.lock 46 | .ruby-version 47 | .ruby-gemset 48 | 49 | # unless supporting rvm < 1.11.0 or doing something fancy, ignore this: 50 | .rvmrc 51 | 52 | **/.byebug_history 53 | 54 | # omit compiled documents 55 | samples/**/*.html 56 | README.html 57 | 58 | # omit cache of remote shared rubocop config 59 | .rubocop-https---raw-githubusercontent-com-riboseinc-oss-guides-master-style--rubocop-yml -------------------------------------------------------------------------------- /lib/citeproc/ruby/formats/adoc.rb: -------------------------------------------------------------------------------- 1 | require "citeproc/ruby/format" 2 | 3 | module CiteProc 4 | module Ruby 5 | module Formats 6 | class Adoc < Format 7 | def apply_font_style 8 | output.replace "_#{output}_" if options[:'font-style'] == "italic" 9 | end 10 | 11 | # TODO 12 | # def apply_font_variant 13 | # output.replace "*#{output}*" if options[:'font-variant'] == 'small-caps' 14 | # end 15 | 16 | def apply_font_weight 17 | output.replace "*#{output}*" if options[:'font-weight'] == "bold" 18 | end 19 | 20 | # TODO 21 | # def apply_text_decoration 22 | # output.replace "*#{output}*" if options[:'text-decoration'] == 'underline' 23 | # end 24 | 25 | def apply_vertical_align 26 | output.replace "^#{output}^" if options[:"vertical-align"] == "sup" 27 | output.replace "~#{output}~" if options[:"vertical-align"] == "sub" 28 | end 29 | 30 | def apply_suffix 31 | options[:suffix] += " " if aligned_first_field? 32 | super 33 | end 34 | 35 | private 36 | 37 | def aligned_first_field? 38 | return node.root.bibliography.layout.children.first == node if aligned_first_accessible? 39 | false 40 | end 41 | 42 | def aligned_first_accessible? 43 | !(node.root.is_a? CSL::Locale) && 44 | node.root.respond_to?(:bibliography) && 45 | node.root.bibliography["second-field-align"] 46 | end 47 | end 48 | end 49 | end 50 | end 51 | -------------------------------------------------------------------------------- /spec/csl/styles/tex_citealp_numeric_spec.rb: -------------------------------------------------------------------------------- 1 | # coding: utf-8 2 | 3 | require_relative "../../citation_helper" 4 | 5 | describe "citealp macro with numeric style" do 6 | let(:options) { { "bibliography-tex-style" => "numeric", "bibliography-database" => "database.bib" } } 7 | 8 | it "formats a single citation" do 9 | expect(formatted_citation("citealp:[Erdos65]", options: options)). 10 | to eq "1" 11 | end 12 | 13 | it "formats a grouped citation" do 14 | expect(formatted_citation("citealp:[Erdos65]+[Einstein35]", options: options)). 15 | to eq "1, 2" 16 | end 17 | 18 | it "formats a single citation with a prefix" do 19 | expect(formatted_citation("citealp:[Erdos65, prefix=see]", options: options)). 20 | to eq "see 1" 21 | end 22 | 23 | it "formats a single citation with a suffix" do 24 | expect(formatted_citation("citealp:[Erdos65, suffix=new edition]", options: options)). 25 | to eq "1, new edition" 26 | end 27 | 28 | it "formats a single citation with both a prefix and a suffix" do 29 | expect(formatted_citation("citealp:[Erdos65, prefix=see, suffix=new edition]", options: options)). 30 | to eq "see 1, new edition" 31 | end 32 | 33 | it "formats a single citation with a standard locator" do 34 | expect(formatted_citation("citealp:[Erdos65, page=41-43]", options: options)). 35 | to eq "1, pp. 41-43" 36 | end 37 | 38 | it "formats a single citation with a custom locator" do 39 | expect(formatted_citation("citealp:[Erdos65, locator=somewhere]", options: options)). 40 | to eq "1, somewhere" 41 | end 42 | end 43 | -------------------------------------------------------------------------------- /spec/csl/styles/tex_citep_numeric_spec.rb: -------------------------------------------------------------------------------- 1 | # coding: utf-8 2 | 3 | require_relative "../../citation_helper" 4 | 5 | describe "citep macro with numeric style" do 6 | let(:options) { { "bibliography-tex-style" => "numeric", "bibliography-database" => "database.bib" } } 7 | 8 | it "formats a single citation" do 9 | expect(formatted_citation("citep:[Erdos65]", options: options)). 10 | to eq "[1]" 11 | end 12 | 13 | it "formats a grouped citation" do 14 | expect(formatted_citation("citep:[Erdos65]+[Einstein35]", options: options)). 15 | to eq "[1, 2]" 16 | end 17 | 18 | it "formats a single citation with a prefix" do 19 | expect(formatted_citation("citep:[Erdos65, prefix=see]", options: options)). 20 | to eq "[see 1]" 21 | end 22 | 23 | it "formats a single citation with a suffix" do 24 | expect(formatted_citation("citep:[Erdos65, suffix=new edition]", options: options)). 25 | to eq "[1, new edition]" 26 | end 27 | 28 | it "formats a single citation with both a prefix and a suffix" do 29 | expect(formatted_citation("citep:[Erdos65, prefix=see, suffix=new edition]", options: options)). 30 | to eq "[see 1, new edition]" 31 | end 32 | 33 | it "formats a single citation with a standard locator" do 34 | expect(formatted_citation("citep:[Erdos65, page=41-43]", options: options)). 35 | to eq "[1, pp. 41-43]" 36 | end 37 | 38 | it "formats a single citation with a custom locator" do 39 | expect(formatted_citation("citep:[Erdos65, locator=somewhere]", options: options)). 40 | to eq "[1, somewhere]" 41 | end 42 | end 43 | -------------------------------------------------------------------------------- /spec/csl/styles/tex_citeps_numeric_spec.rb: -------------------------------------------------------------------------------- 1 | # coding: utf-8 2 | 3 | require_relative "../../citation_helper" 4 | 5 | describe "citep* macro with numeric style" do 6 | let(:options) { { "bibliography-tex-style" => "numeric", "bibliography-database" => "database.bib" } } 7 | 8 | it "formats a single citation" do 9 | expect(formatted_citation("citep*:[Erdos65]", options: options)). 10 | to eq "[1]" 11 | end 12 | 13 | it "formats a grouped citation" do 14 | expect(formatted_citation("citep*:[Erdos65]+[Einstein35]", options: options)). 15 | to eq "[1, 2]" 16 | end 17 | 18 | it "formats a single citation with a prefix" do 19 | expect(formatted_citation("citep*:[Erdos65, prefix=see]", options: options)). 20 | to eq "[see 1]" 21 | end 22 | 23 | it "formats a single citation with a suffix" do 24 | expect(formatted_citation("citep*:[Erdos65, suffix=new edition]", options: options)). 25 | to eq "[1, new edition]" 26 | end 27 | 28 | it "formats a single citation with both a prefix and a suffix" do 29 | expect(formatted_citation("citep*:[Erdos65, prefix=see, suffix=new edition]", options: options)). 30 | to eq "[see 1, new edition]" 31 | end 32 | 33 | it "formats a single citation with a standard locator" do 34 | expect(formatted_citation("citep*:[Erdos65, page=41-43]", options: options)). 35 | to eq "[1, pp. 41-43]" 36 | end 37 | 38 | it "formats a single citation with a custom locator" do 39 | expect(formatted_citation("citep*:[Erdos65, locator=somewhere]", options: options)). 40 | to eq "[1, somewhere]" 41 | end 42 | end 43 | -------------------------------------------------------------------------------- /spec/csl/styles/tex_citealps_numeric_spec.rb: -------------------------------------------------------------------------------- 1 | # coding: utf-8 2 | 3 | require_relative "../../citation_helper" 4 | 5 | describe "citealp* macro with numeric style" do 6 | let(:options) { { "bibliography-tex-style" => "numeric", "bibliography-database" => "database.bib" } } 7 | 8 | it "formats a single citation" do 9 | expect(formatted_citation("citealp*:[Erdos65]", options: options)). 10 | to eq "1" 11 | end 12 | 13 | it "formats a grouped citation" do 14 | expect(formatted_citation("citealp*:[Erdos65]+[Einstein35]", options: options)). 15 | to eq "1, 2" 16 | end 17 | 18 | it "formats a single citation with a prefix" do 19 | expect(formatted_citation("citealp*:[Erdos65, prefix=see]", options: options)). 20 | to eq "see 1" 21 | end 22 | 23 | it "formats a single citation with a suffix" do 24 | expect(formatted_citation("citealp*:[Erdos65, suffix=new edition]", options: options)). 25 | to eq "1, new edition" 26 | end 27 | 28 | it "formats a single citation with both a prefix and a suffix" do 29 | expect(formatted_citation("citealp*:[Erdos65, prefix=see, suffix=new edition]", options: options)). 30 | to eq "see 1, new edition" 31 | end 32 | 33 | it "formats a single citation with a standard locator" do 34 | expect(formatted_citation("citealp*:[Erdos65, page=41-43]", options: options)). 35 | to eq "1, pp. 41-43" 36 | end 37 | 38 | it "formats a single citation with a custom locator" do 39 | expect(formatted_citation("citealp*:[Erdos65, locator=somewhere]", options: options)). 40 | to eq "1, somewhere" 41 | end 42 | end 43 | -------------------------------------------------------------------------------- /samples/tex/sample-authoryear.adoc: -------------------------------------------------------------------------------- 1 | = Sample usage of asciidoctor-bibliography 2 | :bibliography-database: biblio.bib 3 | :bibliography-tex-style: authoryear 4 | :bibliography-style: apa 5 | 6 | ## Citations 7 | 8 | citet:[Anderson04] (citet, single) 9 | 10 | citet:[Lane12a]+[Lane12b] (citet, multiple) 11 | 12 | citet*:[Anderson04] (citet*, single) 13 | 14 | citet*:[Lane12a]+[Lane12b] (citet*, multiple) 15 | 16 | citealt:[Anderson04] (citealt, single) 17 | 18 | citealt:[Lane12a]+[Lane12b] (citealt, multiple) 19 | 20 | citealt*:[Anderson04] (citealt*, single) 21 | 22 | citealt*:[Lane12a]+[Lane12b] (citealt*, multiple) 23 | 24 | citep:[Anderson04] (citep, single) 25 | 26 | citep:[Lane12a]+[Lane12b] (citep, multiple) 27 | 28 | citep*:[Anderson04] (citep*, single) 29 | 30 | citep*:[Lane12a]+[Lane12b] (citep*, multiple) 31 | 32 | citealp:[Anderson04] (citealp, single) 33 | 34 | citealp:[Lane12a]+[Lane12b] (citealp, multiple) 35 | 36 | citealp*:[Anderson04] (citealp*, single) 37 | 38 | citealp*:[Lane12a]+[Lane12b] (citealp*, multiple) 39 | 40 | citeauthor:[Anderson04] (citeauthor, single) 41 | 42 | citeauthor:[Lane12a]+[Lane12b] (citeauthor, multiple) 43 | 44 | citeauthor*:[Anderson04] (citeauthor*, single) 45 | 46 | citeauthor*:[Lane12a]+[Lane12b] (citeauthor*, multiple) 47 | 48 | citeyear:[Anderson04] (citeyear, single) 49 | 50 | citeyear:[Lane12a]+[Lane12b] (citeyear, multiple) 51 | 52 | citeyearpar:[Anderson04] (citeyearpar, single) 53 | 54 | citeyearpar:[Lane12a]+[Lane12b] (citeyearpar, multiple) 55 | 56 | fullcite:[Anderson04] (fullcite) 57 | 58 | 59 | ## Bibliography 60 | 61 | 62 | bibliography::[] 63 | 64 | -------------------------------------------------------------------------------- /spec/csl/styles/tex_citeyear_numeric_spec.rb: -------------------------------------------------------------------------------- 1 | # coding: utf-8 2 | 3 | require_relative "../../citation_helper" 4 | 5 | describe "citeyear macro with numeric style" do 6 | let(:options) { { "bibliography-tex-style" => "numeric", "bibliography-database" => "database.bib" } } 7 | 8 | it "formats a single citation" do 9 | expect(formatted_citation("citeyear:[Erdos65]", options: options)). 10 | to eq "1965" 11 | end 12 | 13 | it "formats a grouped citation" do 14 | expect(formatted_citation("citeyear:[Erdos65]+[Einstein35]", options: options)). 15 | to eq "1965, 1935" 16 | end 17 | 18 | it "formats a single citation with a prefix" do 19 | expect(formatted_citation("citeyear:[Erdos65, prefix=see]", options: options)). 20 | to eq "see 1965" 21 | end 22 | 23 | it "formats a single citation with a suffix" do 24 | expect(formatted_citation("citeyear:[Erdos65, suffix=new edition]", options: options)). 25 | to eq "1965, new edition" 26 | end 27 | 28 | it "formats a single citation with both a prefix and a suffix" do 29 | expect(formatted_citation("citeyear:[Erdos65, prefix=see, suffix=new edition]", options: options)). 30 | to eq "see 1965, new edition" 31 | end 32 | 33 | it "formats a single citation with a standard locator" do 34 | expect(formatted_citation("citeyear:[Erdos65, page=41-43]", options: options)). 35 | to eq "1965, pp. 41-43" 36 | end 37 | 38 | it "formats a single citation with a custom locator" do 39 | expect(formatted_citation("citeyear:[Erdos65, locator=somewhere]", options: options)). 40 | to eq "1965, somewhere" 41 | end 42 | end 43 | -------------------------------------------------------------------------------- /samples/tex/sample-numbers.adoc: -------------------------------------------------------------------------------- 1 | = Sample usage of asciidoctor-bibliography 2 | :bibliography-database: biblio.bib 3 | :bibliography-tex-style: numeric 4 | :bibliography-style: ieee 5 | 6 | 7 | ## Citations 8 | 9 | 10 | citet:[Anderson04] (citet, single) 11 | 12 | citet:[Lane12a]+[Lane12b] (citet, multiple) 13 | 14 | citet*:[Anderson04] (citet*, single) 15 | 16 | citet*:[Lane12a]+[Lane12b] (citet*, multiple) 17 | 18 | citealt:[Anderson04] (citealt, single) 19 | 20 | citealt:[Lane12a]+[Lane12b] (citealt, multiple) 21 | 22 | citealt*:[Anderson04] (citealt*, single) 23 | 24 | citealt*:[Lane12a]+[Lane12b] (citealt*, multiple) 25 | 26 | citep:[Anderson04] (citep, single) 27 | 28 | citep:[Lane12a]+[Lane12b] (citep, multiple) 29 | 30 | citep*:[Anderson04] (citep*, single) 31 | 32 | citep*:[Lane12a]+[Lane12b] (citep*, multiple) 33 | 34 | citealp:[Anderson04] (citealp, single) 35 | 36 | citealp:[Lane12a]+[Lane12b] (citealp, multiple) 37 | 38 | citealp*:[Anderson04] (citealp*, single) 39 | 40 | citealp*:[Lane12a]+[Lane12b] (citealp*, multiple) 41 | 42 | citeauthor:[Anderson04] (citeauthor, single) 43 | 44 | citeauthor:[Lane12a]+[Lane12b] (citeauthor, multiple) 45 | 46 | citeauthor*:[Anderson04] (citeauthor*, single) 47 | 48 | citeauthor*:[Lane12a]+[Lane12b] (citeauthor*, multiple) 49 | 50 | citeyear:[Anderson04] (citeyear, single) 51 | 52 | citeyear:[Lane12a]+[Lane12b] (citeyear, multiple) 53 | 54 | citeyearpar:[Anderson04] (citeyearpar, single) 55 | 56 | citeyearpar:[Lane12a]+[Lane12b] (citeyearpar, multiple) 57 | 58 | fullcite:[Anderson04] (fullcite) 59 | 60 | 61 | ## Bibliography 62 | 63 | 64 | bibliography::[] 65 | 66 | -------------------------------------------------------------------------------- /spec/csl/styles/tex_citeyear_authoryear_spec.rb: -------------------------------------------------------------------------------- 1 | # coding: utf-8 2 | 3 | require_relative "../../citation_helper" 4 | 5 | describe "citeyear macro with authoryear style" do 6 | let(:options) { { "bibliography-tex-style" => "authoryear", "bibliography-database" => "database.bib" } } 7 | 8 | it "formats a single citation" do 9 | expect(formatted_citation("citeyear:[Erdos65]", options: options)). 10 | to eq "1965" 11 | end 12 | 13 | it "formats a grouped citation" do 14 | expect(formatted_citation("citeyear:[Erdos65]+[Einstein35]", options: options)). 15 | to eq "1965; 1935" 16 | end 17 | 18 | it "formats a single citation with a prefix" do 19 | expect(formatted_citation("citeyear:[Erdos65, prefix=see]", options: options)). 20 | to eq "see 1965" 21 | end 22 | 23 | it "formats a single citation with a suffix" do 24 | expect(formatted_citation("citeyear:[Erdos65, suffix=new edition]", options: options)). 25 | to eq "1965, new edition" 26 | end 27 | 28 | it "formats a single citation with both a prefix and a suffix" do 29 | expect(formatted_citation("citeyear:[Erdos65, prefix=see, suffix=new edition]", options: options)). 30 | to eq "see 1965, new edition" 31 | end 32 | 33 | it "formats a single citation with a standard locator" do 34 | expect(formatted_citation("citeyear:[Erdos65, page=41-43]", options: options)). 35 | to eq "1965, pp. 41-43" 36 | end 37 | 38 | it "formats a single citation with a custom locator" do 39 | expect(formatted_citation("citeyear:[Erdos65, locator=somewhere]", options: options)). 40 | to eq "1965, somewhere" 41 | end 42 | end 43 | -------------------------------------------------------------------------------- /spec/csl/styles/tex_citeyearpar_numeric_spec.rb: -------------------------------------------------------------------------------- 1 | # coding: utf-8 2 | 3 | require_relative "../../citation_helper" 4 | 5 | describe "citeyearpar macro with numeric style" do 6 | let(:options) { { "bibliography-tex-style" => "numeric", "bibliography-database" => "database.bib" } } 7 | 8 | it "formats a single citation" do 9 | expect(formatted_citation("citeyearpar:[Erdos65]", options: options)). 10 | to eq "[1965]" 11 | end 12 | 13 | it "formats a grouped citation" do 14 | expect(formatted_citation("citeyearpar:[Erdos65]+[Einstein35]", options: options)). 15 | to eq "[1965, 1935]" 16 | end 17 | 18 | it "formats a single citation with a prefix" do 19 | expect(formatted_citation("citeyearpar:[Erdos65, prefix=see]", options: options)). 20 | to eq "[see 1965]" 21 | end 22 | 23 | it "formats a single citation with a suffix" do 24 | expect(formatted_citation("citeyearpar:[Erdos65, suffix=new edition]", options: options)). 25 | to eq "[1965, new edition]" 26 | end 27 | 28 | it "formats a single citation with both a prefix and a suffix" do 29 | expect(formatted_citation("citeyearpar:[Erdos65, prefix=see, suffix=new edition]", options: options)). 30 | to eq "[see 1965, new edition]" 31 | end 32 | 33 | it "formats a single citation with a standard locator" do 34 | expect(formatted_citation("citeyearpar:[Erdos65, page=41-43]", options: options)). 35 | to eq "[1965, pp. 41-43]" 36 | end 37 | 38 | it "formats a single citation with a custom locator" do 39 | expect(formatted_citation("citeyearpar:[Erdos65, locator=somewhere]", options: options)). 40 | to eq "[1965, somewhere]" 41 | end 42 | end 43 | -------------------------------------------------------------------------------- /spec/csl/styles/tex_citeyearpar_authoryear_spec.rb: -------------------------------------------------------------------------------- 1 | # coding: utf-8 2 | 3 | require_relative "../../citation_helper" 4 | 5 | describe "citeyearpar macro with authoryear style" do 6 | let(:options) { { "bibliography-tex-style" => "authoryear", "bibliography-database" => "database.bib" } } 7 | 8 | it "formats a single citation" do 9 | expect(formatted_citation("citeyearpar:[Erdos65]", options: options)). 10 | to eq "(1965)" 11 | end 12 | 13 | it "formats a grouped citation" do 14 | expect(formatted_citation("citeyearpar:[Erdos65]+[Einstein35]", options: options)). 15 | to eq "(1965; 1935)" 16 | end 17 | 18 | it "formats a single citation with a prefix" do 19 | expect(formatted_citation("citeyearpar:[Erdos65, prefix=see]", options: options)). 20 | to eq "(see 1965)" 21 | end 22 | 23 | it "formats a single citation with a suffix" do 24 | expect(formatted_citation("citeyearpar:[Erdos65, suffix=new edition]", options: options)). 25 | to eq "(1965, new edition)" 26 | end 27 | 28 | it "formats a single citation with both a prefix and a suffix" do 29 | expect(formatted_citation("citeyearpar:[Erdos65, prefix=see, suffix=new edition]", options: options)). 30 | to eq "(see 1965, new edition)" 31 | end 32 | 33 | it "formats a single citation with a standard locator" do 34 | expect(formatted_citation("citeyearpar:[Erdos65, page=41-43]", options: options)). 35 | to eq "(1965, pp. 41-43)" 36 | end 37 | 38 | it "formats a single citation with a custom locator" do 39 | expect(formatted_citation("citeyearpar:[Erdos65, locator=somewhere]", options: options)). 40 | to eq "(1965, somewhere)" 41 | end 42 | end 43 | -------------------------------------------------------------------------------- /spec/csl/styles/rfc_v2_spec.rb: -------------------------------------------------------------------------------- 1 | # coding: utf-8 2 | 3 | require_relative "../../citation_helper" 4 | 5 | describe "cite macro with rfc-v2 style" do 6 | let(:options) { { "bibliography-style" => "rfc-v2", "bibliography-database" => "database.rfc.xml", "bibliography-passthrough" => "true", "bibliography-prepend-empty" => "false" } } 7 | 8 | it "formats a single citation" do 9 | expect(formatted_citation("cite:[RFC2119]", options: options)). 10 | to eq '++++++' 11 | end 12 | 13 | it "formats a single citation with locator" do 14 | expect(formatted_citation("cite:[RFC2119, section=1.2.3]", options: options)). 15 | to eq '++++++' 16 | end 17 | 18 | it "formats a single bibliography entry" do 19 | expect(formatted_bibliography("cite:[RFC2119]", options: options)). 20 | to eq '+++Key words for use in RFCs to Indicate Requirement LevelsIn many standards track documents several words are used to signify the requirements in the specification. These words are often capitalized. This document defines these words as they should be interpreted in IETF documents. This document specifies an Internet Best Current Practices for the Internet Community, and requests discussion and suggestions for improvements.+++' 21 | end 22 | end 23 | -------------------------------------------------------------------------------- /spec/csl/styles/rfc_v3_spec.rb: -------------------------------------------------------------------------------- 1 | # coding: utf-8 2 | 3 | require_relative "../../citation_helper" 4 | 5 | describe "cite macro with rfc-v3 style" do 6 | let(:options) { { "bibliography-style" => "rfc-v3", "bibliography-database" => "database.rfc.xml", "bibliography-passthrough" => "true", "bibliography-prepend-empty" => "false" } } 7 | 8 | it "formats a single citation" do 9 | expect(formatted_citation("cite:[RFC2119]", options: options)). 10 | to eq '++++++' 11 | end 12 | 13 | it "formats a single citation with locator" do 14 | expect(formatted_citation("cite:[RFC2119, section=1.2.3]", options: options)). 15 | to eq '++++++' 16 | end 17 | 18 | it "formats a single bibliography entry" do 19 | expect(formatted_bibliography("cite:[RFC2119]", options: options)). 20 | to eq '+++Key words for use in RFCs to Indicate Requirement LevelsIn many standards track documents several words are used to signify the requirements in the specification. These words are often capitalized. This document defines these words as they should be interpreted in IETF documents. This document specifies an Internet Best Current Practices for the Internet Community, and requests discussion and suggestions for improvements.+++' 21 | end 22 | end 23 | -------------------------------------------------------------------------------- /lib/asciidoctor-bibliography/database.rb: -------------------------------------------------------------------------------- 1 | require_relative "databases/bibtex" 2 | require_relative "databases/rfc" 3 | require_relative "errors" 4 | 5 | module AsciidoctorBibliography 6 | # This is an array of citeproc entries. 7 | class Database < Array 8 | def initialize(*filepaths) 9 | filepaths.each do |filepath| 10 | append filepath 11 | end 12 | end 13 | 14 | def append(filepath) 15 | concat Database.load(filepath) 16 | ensure_no_conflicts! 17 | self 18 | end 19 | 20 | def find_entry_by_id(id) 21 | result = detect { |entry| entry["id"] == id } 22 | if result.nil? 23 | message = "No entry with id '#{id}' was found in the bibliographic database." 24 | raise Errors::Database::IdNotFound, message 25 | end 26 | result 27 | end 28 | 29 | def self.load(filepath) 30 | raise Errors::Database::FileNotFound, filepath unless File.exist?(filepath) 31 | 32 | fileext = File.extname filepath 33 | case fileext 34 | when *Databases::BibTeX::EXTENSIONS 35 | Databases::BibTeX.load filepath 36 | when *Databases::RFC::EXTENSIONS 37 | Databases::RFC.load filepath 38 | else 39 | raise Errors::Database::UnsupportedFormat, fileext 40 | end 41 | end 42 | 43 | private 44 | 45 | def ensure_no_conflicts! 46 | ids = map { |entry| entry["id"] } 47 | conflicting_ids = ids.select { |id| ids.count(id) > 1 }.uniq.sort 48 | raise Errors::Database::ConflictingIds, <<~MESSAGE if conflicting_ids.any? 49 | Conflicting ids were found during database import: #{conflicting_ids}. 50 | MESSAGE 51 | end 52 | end 53 | end 54 | -------------------------------------------------------------------------------- /spec/csl/styles/tex_citealt_numeric_spec.rb: -------------------------------------------------------------------------------- 1 | # coding: utf-8 2 | 3 | require_relative "../../citation_helper" 4 | 5 | describe "citealt macro with numeric style" do 6 | let(:options) { { "bibliography-tex-style" => "numeric", "bibliography-database" => "database.bib" } } 7 | 8 | it "formats a single citation" do 9 | expect(formatted_citation("citealt:[Erdos65]", options: options)). 10 | to eq "Erdős et al. 1" 11 | end 12 | 13 | it "formats a grouped citation" do 14 | expect(formatted_citation("citealt:[Erdos65]+[Einstein35]", options: options)). 15 | to eq "Erdős et al. 1, Einstein et al. 2" 16 | end 17 | 18 | it "formats a single citation with a prefix" do 19 | expect(formatted_citation("citealt:[Erdos65, prefix=see]", options: options)). 20 | to eq "Erdős et al. see 1" 21 | end 22 | 23 | it "formats a single citation with a suffix" do 24 | expect(formatted_citation("citealt:[Erdos65, suffix=new edition]", options: options)). 25 | to eq "Erdős et al. 1, new edition" 26 | end 27 | 28 | it "formats a single citation with both a prefix and a suffix" do 29 | expect(formatted_citation("citealt:[Erdos65, prefix=see, suffix=new edition]", options: options)). 30 | to eq "Erdős et al. see 1, new edition" 31 | end 32 | 33 | it "formats a single citation with a standard locator" do 34 | expect(formatted_citation("citealt:[Erdos65, page=41-43]", options: options)). 35 | to eq "Erdős et al. 1, pp. 41-43" 36 | end 37 | 38 | it "formats a single citation with a custom locator" do 39 | expect(formatted_citation("citealt:[Erdos65, locator=somewhere]", options: options)). 40 | to eq "Erdős et al. 1, somewhere" 41 | end 42 | end 43 | -------------------------------------------------------------------------------- /spec/csl/styles/tex_citeauthor_numeric_spec.rb: -------------------------------------------------------------------------------- 1 | # coding: utf-8 2 | 3 | require_relative "../../citation_helper" 4 | 5 | describe "citeauthor macro with numeric style" do 6 | let(:options) { { "bibliography-tex-style" => "numeric", "bibliography-database" => "database.bib" } } 7 | 8 | it "formats a single citation" do 9 | expect(formatted_citation("citeauthor:[Erdos65]", options: options)). 10 | to eq "Erdős et al." 11 | end 12 | 13 | it "formats a grouped citation" do 14 | expect(formatted_citation("citeauthor:[Erdos65]+[Einstein35]", options: options)). 15 | to eq "Erdős et al., Einstein et al." 16 | end 17 | 18 | it "formats a single citation with a prefix" do 19 | expect(formatted_citation("citeauthor:[Erdos65, prefix=see]", options: options)). 20 | to eq "see Erdős et al." 21 | end 22 | 23 | it "formats a single citation with a suffix" do 24 | expect(formatted_citation("citeauthor:[Erdos65, suffix=new edition]", options: options)). 25 | to eq "Erdős et al., new edition" 26 | end 27 | 28 | it "formats a single citation with both a prefix and a suffix" do 29 | expect(formatted_citation("citeauthor:[Erdos65, prefix=see, suffix=new edition]", options: options)). 30 | to eq "see Erdős et al., new edition" 31 | end 32 | 33 | it "formats a single citation with a standard locator" do 34 | expect(formatted_citation("citeauthor:[Erdos65, page=41-43]", options: options)). 35 | to eq "Erdős et al., pp. 41-43" 36 | end 37 | 38 | it "formats a single citation with a custom locator" do 39 | expect(formatted_citation("citeauthor:[Erdos65, locator=somewhere]", options: options)). 40 | to eq "Erdős et al., somewhere" 41 | end 42 | end 43 | -------------------------------------------------------------------------------- /spec/csl/styles/tex_citeauthor_authoryear_spec.rb: -------------------------------------------------------------------------------- 1 | # coding: utf-8 2 | 3 | require_relative "../../citation_helper" 4 | 5 | describe "citeauthor macro with authoryear style" do 6 | let(:options) { { "bibliography-tex-style" => "authoryear", "bibliography-database" => "database.bib" } } 7 | 8 | it "formats a single citation" do 9 | expect(formatted_citation("citeauthor:[Erdos65]", options: options)). 10 | to eq "Erdős et al." 11 | end 12 | 13 | it "formats a grouped citation" do 14 | expect(formatted_citation("citeauthor:[Erdos65]+[Einstein35]", options: options)). 15 | to eq "Erdős et al.; Einstein et al." 16 | end 17 | 18 | it "formats a single citation with a prefix" do 19 | expect(formatted_citation("citeauthor:[Erdos65, prefix=see]", options: options)). 20 | to eq "see Erdős et al." 21 | end 22 | 23 | it "formats a single citation with a suffix" do 24 | expect(formatted_citation("citeauthor:[Erdos65, suffix=new edition]", options: options)). 25 | to eq "Erdős et al., new edition" 26 | end 27 | 28 | it "formats a single citation with both a prefix and a suffix" do 29 | expect(formatted_citation("citeauthor:[Erdos65, prefix=see, suffix=new edition]", options: options)). 30 | to eq "see Erdős et al., new edition" 31 | end 32 | 33 | it "formats a single citation with a standard locator" do 34 | expect(formatted_citation("citeauthor:[Erdos65, page=41-43]", options: options)). 35 | to eq "Erdős et al., pp. 41-43" 36 | end 37 | 38 | it "formats a single citation with a custom locator" do 39 | expect(formatted_citation("citeauthor:[Erdos65, locator=somewhere]", options: options)). 40 | to eq "Erdős et al., somewhere" 41 | end 42 | end 43 | -------------------------------------------------------------------------------- /spec/csl/styles/tex_citealt_authoryear_spec.rb: -------------------------------------------------------------------------------- 1 | # coding: utf-8 2 | 3 | require_relative "../../citation_helper" 4 | 5 | describe "citealt macro with authoryear style" do 6 | let(:options) { { "bibliography-tex-style" => "authoryear", "bibliography-database" => "database.bib" } } 7 | 8 | it "formats a single citation" do 9 | expect(formatted_citation("citealt:[Erdos65]", options: options)). 10 | to eq "Erdős et al. 1965" 11 | end 12 | 13 | it "formats a grouped citation" do 14 | expect(formatted_citation("citealt:[Erdos65]+[Einstein35]", options: options)). 15 | to eq "Erdős et al. 1965; Einstein et al. 1935" 16 | end 17 | 18 | it "formats a single citation with a prefix" do 19 | expect(formatted_citation("citealt:[Erdos65, prefix=see]", options: options)). 20 | to eq "Erdős et al. see 1965" 21 | end 22 | 23 | it "formats a single citation with a suffix" do 24 | expect(formatted_citation("citealt:[Erdos65, suffix=new edition]", options: options)). 25 | to eq "Erdős et al. 1965, new edition" 26 | end 27 | 28 | it "formats a single citation with both a prefix and a suffix" do 29 | expect(formatted_citation("citealt:[Erdos65, prefix=see, suffix=new edition]", options: options)). 30 | to eq "Erdős et al. see 1965, new edition" 31 | end 32 | 33 | it "formats a single citation with a standard locator" do 34 | expect(formatted_citation("citealt:[Erdos65, page=41-43]", options: options)). 35 | to eq "Erdős et al. 1965, pp. 41-43" 36 | end 37 | 38 | it "formats a single citation with a custom locator" do 39 | expect(formatted_citation("citealt:[Erdos65, locator=somewhere]", options: options)). 40 | to eq "Erdős et al. 1965, somewhere" 41 | end 42 | end 43 | -------------------------------------------------------------------------------- /spec/csl/styles/tex_citet_authoryear_spec.rb: -------------------------------------------------------------------------------- 1 | # coding: utf-8 2 | 3 | require_relative "../../citation_helper" 4 | 5 | describe "citet macro with authoryear style" do 6 | let(:options) { { "bibliography-tex-style" => "authoryear", "bibliography-database" => "database.bib" } } 7 | 8 | it "formats a single citation" do 9 | expect(formatted_citation("citet:[Erdos65]", options: options)). 10 | to eq "Erdős et al. (1965)" 11 | end 12 | 13 | it "formats a grouped citation" do 14 | expect(formatted_citation("citet:[Erdos65]+[Einstein35]", options: options)). 15 | to eq "Erdős et al. (1965); Einstein et al. (1935)" 16 | end 17 | 18 | it "formats a single citation with a prefix" do 19 | expect(formatted_citation("citet:[Erdos65, prefix=see]", options: options)). 20 | to eq "Erdős et al. (see 1965)" 21 | end 22 | 23 | it "formats a single citation with a suffix" do 24 | expect(formatted_citation("citet:[Erdos65, suffix=new edition]", options: options)). 25 | to eq "Erdős et al. (1965, new edition)" 26 | end 27 | 28 | it "formats a single citation with both a prefix and a suffix" do 29 | expect(formatted_citation("citet:[Erdos65, prefix=see, suffix=new edition]", options: options)). 30 | to eq "Erdős et al. (see 1965, new edition)" 31 | end 32 | 33 | it "formats a single citation with a standard locator" do 34 | expect(formatted_citation("citet:[Erdos65, page=41-43]", options: options)). 35 | to eq "Erdős et al. (1965, pp. 41-43)" 36 | end 37 | 38 | it "formats a single citation with a custom locator" do 39 | expect(formatted_citation("citet:[Erdos65, locator=somewhere]", options: options)). 40 | to eq "Erdős et al. (1965, somewhere)" 41 | end 42 | end 43 | -------------------------------------------------------------------------------- /spec/csl/styles/tex_citep_authoryear_spec.rb: -------------------------------------------------------------------------------- 1 | # coding: utf-8 2 | 3 | require_relative "../../citation_helper" 4 | 5 | describe "citep macro with authoryear style" do 6 | let(:options) { { "bibliography-tex-style" => "authoryear", "bibliography-database" => "database.bib" } } 7 | 8 | it "formats a single citation" do 9 | expect(formatted_citation("citep:[Erdos65]", options: options)). 10 | to eq "(Erdős et al., 1965)" 11 | end 12 | 13 | it "formats a grouped citation" do 14 | expect(formatted_citation("citep:[Erdos65]+[Einstein35]", options: options)). 15 | to eq "(Erdős et al., 1965; Einstein et al., 1935)" 16 | end 17 | 18 | it "formats a single citation with a prefix" do 19 | expect(formatted_citation("citep:[Erdos65, prefix=see]", options: options)). 20 | to eq "(see Erdős et al., 1965)" 21 | end 22 | 23 | it "formats a single citation with a suffix" do 24 | expect(formatted_citation("citep:[Erdos65, suffix=new edition]", options: options)). 25 | to eq "(Erdős et al., 1965, new edition)" 26 | end 27 | 28 | it "formats a single citation with both a prefix and a suffix" do 29 | expect(formatted_citation("citep:[Erdos65, prefix=see, suffix=new edition]", options: options)). 30 | to eq "(see Erdős et al., 1965, new edition)" 31 | end 32 | 33 | it "formats a single citation with a standard locator" do 34 | expect(formatted_citation("citep:[Erdos65, page=41-43]", options: options)). 35 | to eq "(Erdős et al., 1965, pp. 41-43)" 36 | end 37 | 38 | it "formats a single citation with a custom locator" do 39 | expect(formatted_citation("citep:[Erdos65, locator=somewhere]", options: options)). 40 | to eq "(Erdős et al., 1965, somewhere)" 41 | end 42 | end 43 | -------------------------------------------------------------------------------- /spec/csl/styles/tex_citealp_authoryear_spec.rb: -------------------------------------------------------------------------------- 1 | # coding: utf-8 2 | 3 | require_relative "../../citation_helper" 4 | 5 | describe "citealp macro with authoryear style" do 6 | let(:options) { { "bibliography-tex-style" => "authoryear", "bibliography-database" => "database.bib" } } 7 | 8 | it "formats a single citation" do 9 | expect(formatted_citation("citealp:[Erdos65]", options: options)). 10 | to eq "Erdős et al., 1965" 11 | end 12 | 13 | it "formats a grouped citation" do 14 | expect(formatted_citation("citealp:[Erdos65]+[Einstein35]", options: options)). 15 | to eq "Erdős et al., 1965; Einstein et al., 1935" 16 | end 17 | 18 | it "formats a single citation with a prefix" do 19 | expect(formatted_citation("citealp:[Erdos65, prefix=see]", options: options)). 20 | to eq "see Erdős et al., 1965" 21 | end 22 | 23 | it "formats a single citation with a suffix" do 24 | expect(formatted_citation("citealp:[Erdos65, suffix=new edition]", options: options)). 25 | to eq "Erdős et al., 1965, new edition" 26 | end 27 | 28 | it "formats a single citation with both a prefix and a suffix" do 29 | expect(formatted_citation("citealp:[Erdos65, prefix=see, suffix=new edition]", options: options)). 30 | to eq "see Erdős et al., 1965, new edition" 31 | end 32 | 33 | it "formats a single citation with a standard locator" do 34 | expect(formatted_citation("citealp:[Erdos65, page=41-43]", options: options)). 35 | to eq "Erdős et al., 1965, pp. 41-43" 36 | end 37 | 38 | it "formats a single citation with a custom locator" do 39 | expect(formatted_citation("citealp:[Erdos65, locator=somewhere]", options: options)). 40 | to eq "Erdős et al., 1965, somewhere" 41 | end 42 | end 43 | -------------------------------------------------------------------------------- /spec/fixtures/database-issue84.bib: -------------------------------------------------------------------------------- 1 | 2 | @article{baran_distributed_1964, 3 | title = {On distributed communications networks}, 4 | volume = {12}, 5 | issn = {0096-1965}, 6 | number = {1}, 7 | journal = {IEEE transactions on Communications Systems}, 8 | author = {Baran, Paul}, 9 | year = {1964}, 10 | pages = {1--9}, 11 | file = {Bar64.pdf:https://www.rand.org/pubs/papers/P2626.html:text/html} 12 | } 13 | 14 | @article{lukasik_why_2011, 15 | title = {Why the {Arpanet} {Was} {Built}}, 16 | volume = {33}, 17 | issn = {1058-6180}, 18 | url = {http://ieeexplore.ieee.org/document/5432117/}, 19 | doi = {10.1109/MAHC.2010.11}, 20 | language = {en}, 21 | number = {3}, 22 | urldate = {2019-02-20}, 23 | journal = {IEEE Annals of the History of Computing}, 24 | author = {Lukasik, Stephen}, 25 | month = mar, 26 | year = {2011}, 27 | pages = {4--21}, 28 | file = {Lukasik - 2011 - Why the Arpanet Was Built.pdf:application/pdf} 29 | } 30 | 31 | @inproceedings{roberts_arpanet_1986, 32 | title = {The {Arpanet} and computer networks}, 33 | isbn = {0-89791-176-8}, 34 | publisher = {ACM}, 35 | author = {Roberts, Larry}, 36 | year = {1986}, 37 | pages = {51--58}, 38 | file = {p51-roberts.pdf:application/pdf} 39 | } 40 | 41 | @article{dommering_internet:_2015, 42 | title = {The {Internet}: a global free space with limited state control}, 43 | shorttitle = {The {Internet}}, 44 | url = {https://dare.uva.nl/search?identifier=8672fb24-0825-4bdb-98ac-989e370446ae}, 45 | language = {en}, 46 | urldate = {2019-02-20}, 47 | author = {Dommering, E. and van Ginkel, B. and de Goede, M. and Koops, B. J. and Plooij-van Gorsel, E. and Verrijn Stuart, H. and Smallenbroek, J.}, 48 | year = {2015}, 49 | file = {THE INTERNET A GLOBAL FREE SPACE WITH LIMITED STAT.pdf:application/pdf} 50 | } 51 | -------------------------------------------------------------------------------- /spec/csl/styles/tex_citet_numeric_spec.rb: -------------------------------------------------------------------------------- 1 | # coding: utf-8 2 | 3 | require_relative "../../citation_helper" 4 | 5 | describe "citet macro with numeric style" do 6 | let(:options) { { "bibliography-tex-style" => "numeric", "bibliography-database" => "database.bib" } } 7 | 8 | it "formats a single citation" do 9 | expect(formatted_citation("citet:[Erdos65]", options: options)). 10 | to eq "Erdős et al. [1]" 11 | end 12 | 13 | it "formats a grouped citation" do 14 | expect(formatted_citation("citet:[Erdos65]+[Einstein35]", options: options)). 15 | to eq "Erdős et al. [1], Einstein et al. [2]" 16 | end 17 | 18 | it "formats a single citation with a prefix" do 19 | expect(formatted_citation("citet:[Erdos65, prefix=see]", options: options)). 20 | to eq "Erdős et al. [see 1]" 21 | end 22 | 23 | it "formats a single citation with a suffix" do 24 | expect(formatted_citation("citet:[Erdos65, suffix=new edition]", options: options)). 25 | to eq "Erdős et al. [1, new edition]" 26 | end 27 | 28 | it "formats a single citation with both a prefix and a suffix" do 29 | expect(formatted_citation("citet:[Erdos65, prefix=see, suffix=new edition]", options: options)). 30 | to eq "Erdős et al. [see 1, new edition]" 31 | end 32 | 33 | it "formats a single citation with a standard locator" do 34 | expect(formatted_citation("citet:[Erdos65, page=41-43]", options: options)). 35 | to eq "Erdős et al. [1, pp. 41-43]" 36 | end 37 | 38 | it "formats a single citation with a custom locator" do 39 | expect(formatted_citation("citet:[Erdos65, locator=somewhere]", options: options)). 40 | to eq "Erdős et al. [1, somewhere]" 41 | end 42 | end 43 | -------------------------------------------------------------------------------- /spec/csl/styles/tex_citealts_numeric_spec.rb: -------------------------------------------------------------------------------- 1 | # coding: utf-8 2 | 3 | require_relative "../../citation_helper" 4 | 5 | describe "citealt* macro with numeric style" do 6 | let(:options) { { "bibliography-tex-style" => "numeric", "bibliography-database" => "database.bib" } } 7 | 8 | it "formats a single citation" do 9 | expect(formatted_citation("citealt*:[Erdos65]", options: options)). 10 | to eq "Erdős, Heyting, and Brouwer 1" 11 | end 12 | 13 | it "formats a grouped citation" do 14 | expect(formatted_citation("citealt*:[Erdos65]+[Einstein35]", options: options)). 15 | to eq "Erdős, Heyting, and Brouwer 1, Einstein, Podolsky, and Rosen 2" 16 | end 17 | 18 | it "formats a single citation with a prefix" do 19 | expect(formatted_citation("citealt*:[Erdos65, prefix=see]", options: options)). 20 | to eq "Erdős, Heyting, and Brouwer see 1" 21 | end 22 | 23 | it "formats a single citation with a suffix" do 24 | expect(formatted_citation("citealt*:[Erdos65, suffix=new edition]", options: options)). 25 | to eq "Erdős, Heyting, and Brouwer 1, new edition" 26 | end 27 | 28 | it "formats a single citation with both a prefix and a suffix" do 29 | expect(formatted_citation("citealt*:[Erdos65, prefix=see, suffix=new edition]", options: options)). 30 | to eq "Erdős, Heyting, and Brouwer see 1, new edition" 31 | end 32 | 33 | it "formats a single citation with a standard locator" do 34 | expect(formatted_citation("citealt*:[Erdos65, page=41-43]", options: options)). 35 | to eq "Erdős, Heyting, and Brouwer 1, pp. 41-43" 36 | end 37 | 38 | it "formats a single citation with a custom locator" do 39 | expect(formatted_citation("citealt*:[Erdos65, locator=somewhere]", options: options)). 40 | to eq "Erdős, Heyting, and Brouwer 1, somewhere" 41 | end 42 | end 43 | -------------------------------------------------------------------------------- /spec/csl/styles/tex_citeauthors_numeric_spec.rb: -------------------------------------------------------------------------------- 1 | # coding: utf-8 2 | 3 | require_relative "../../citation_helper" 4 | 5 | describe "citeauthor* macro with numeric style" do 6 | let(:options) { { "bibliography-tex-style" => "numeric", "bibliography-database" => "database.bib" } } 7 | 8 | it "formats a single citation" do 9 | expect(formatted_citation("citeauthor*:[Erdos65]", options: options)). 10 | to eq "Erdős, Heyting, and Brouwer" 11 | end 12 | 13 | it "formats a grouped citation" do 14 | expect(formatted_citation("citeauthor*:[Erdos65]+[Einstein35]", options: options)). 15 | to eq "Erdős, Heyting, and Brouwer, Einstein, Podolsky, and Rosen" 16 | end 17 | 18 | it "formats a single citation with a prefix" do 19 | expect(formatted_citation("citeauthor*:[Erdos65, prefix=see]", options: options)). 20 | to eq "see Erdős, Heyting, and Brouwer" 21 | end 22 | 23 | it "formats a single citation with a suffix" do 24 | expect(formatted_citation("citeauthor*:[Erdos65, suffix=new edition]", options: options)). 25 | to eq "Erdős, Heyting, and Brouwer, new edition" 26 | end 27 | 28 | it "formats a single citation with both a prefix and a suffix" do 29 | expect(formatted_citation("citeauthor*:[Erdos65, prefix=see, suffix=new edition]", options: options)). 30 | to eq "see Erdős, Heyting, and Brouwer, new edition" 31 | end 32 | 33 | it "formats a single citation with a standard locator" do 34 | expect(formatted_citation("citeauthor*:[Erdos65, page=41-43]", options: options)). 35 | to eq "Erdős, Heyting, and Brouwer, pp. 41-43" 36 | end 37 | 38 | it "formats a single citation with a custom locator" do 39 | expect(formatted_citation("citeauthor*:[Erdos65, locator=somewhere]", options: options)). 40 | to eq "Erdős, Heyting, and Brouwer, somewhere" 41 | end 42 | end 43 | -------------------------------------------------------------------------------- /lib/asciidoctor-bibliography/databases/rfc.rb: -------------------------------------------------------------------------------- 1 | # coding: utf-8 2 | 3 | require "nokogiri" 4 | 5 | module AsciidoctorBibliography 6 | module Databases 7 | module RFC 8 | EXTENSIONS = %w[.rfc .xml].freeze 9 | 10 | MONTHS = %w{january february march april may june july 11 | august september october november december}.freeze 12 | 13 | def self.load(filename) 14 | ::Nokogiri::XML(File.open(filename)). 15 | xpath("//reference"). 16 | map { |reference_tag| tag_to_citeproc reference_tag } 17 | end 18 | 19 | def self.tag_to_citeproc(reference_tag) 20 | { 21 | "id" => reference_tag.attr("anchor"), 22 | "author" => get_author_list(reference_tag), 23 | "title" => reference_tag.xpath("//title").first&.text&.strip, 24 | "issued" => { 25 | "date-parts" => get_date_parts(reference_tag) 26 | }, 27 | # NOTE: we keep the original XML to re-render it when needed 28 | "note" => reference_tag.to_xml 29 | } 30 | end 31 | 32 | def self.get_date_parts(reference_tag) 33 | date_tag = reference_tag.xpath("//date").first 34 | year = date_tag&.attr("year") 35 | month = date_tag&.attr("month") 36 | day = date_tag&.attr("day") 37 | month = MONTHS.index(month.downcase) + 1 unless month.nil? 38 | [year, month, day].take_while { |date_part| !date_part.nil? }.map(&:to_s) 39 | end 40 | 41 | def self.get_author_list(reference_tag) 42 | author_tags = reference_tag.xpath("//author") 43 | author_tags.map do |author_tag| 44 | { 45 | "family" => author_tag&.attr("surname"), 46 | "given" => author_tag&.attr("initials") 47 | } 48 | end 49 | end 50 | end 51 | end 52 | end 53 | -------------------------------------------------------------------------------- /spec/csl/styles/tex_citeauthors_authoryear_spec.rb: -------------------------------------------------------------------------------- 1 | # coding: utf-8 2 | 3 | require_relative "../../citation_helper" 4 | 5 | describe "citeauthor* macro with authoryear style" do 6 | let(:options) { { "bibliography-tex-style" => "authoryear", "bibliography-database" => "database.bib" } } 7 | 8 | it "formats a single citation" do 9 | expect(formatted_citation("citeauthor*:[Erdos65]", options: options)). 10 | to eq "Erdős, Heyting, and Brouwer" 11 | end 12 | 13 | it "formats a grouped citation" do 14 | expect(formatted_citation("citeauthor*:[Erdos65]+[Einstein35]", options: options)). 15 | to eq "Erdős, Heyting, and Brouwer; Einstein, Podolsky, and Rosen" 16 | end 17 | 18 | it "formats a single citation with a prefix" do 19 | expect(formatted_citation("citeauthor*:[Erdos65, prefix=see]", options: options)). 20 | to eq "see Erdős, Heyting, and Brouwer" 21 | end 22 | 23 | it "formats a single citation with a suffix" do 24 | expect(formatted_citation("citeauthor*:[Erdos65, suffix=new edition]", options: options)). 25 | to eq "Erdős, Heyting, and Brouwer, new edition" 26 | end 27 | 28 | it "formats a single citation with both a prefix and a suffix" do 29 | expect(formatted_citation("citeauthor*:[Erdos65, prefix=see, suffix=new edition]", options: options)). 30 | to eq "see Erdős, Heyting, and Brouwer, new edition" 31 | end 32 | 33 | it "formats a single citation with a standard locator" do 34 | expect(formatted_citation("citeauthor*:[Erdos65, page=41-43]", options: options)). 35 | to eq "Erdős, Heyting, and Brouwer, pp. 41-43" 36 | end 37 | 38 | it "formats a single citation with a custom locator" do 39 | expect(formatted_citation("citeauthor*:[Erdos65, locator=somewhere]", options: options)). 40 | to eq "Erdős, Heyting, and Brouwer, somewhere" 41 | end 42 | end 43 | -------------------------------------------------------------------------------- /spec/csl/styles/tex_citealts_authoryear_spec.rb: -------------------------------------------------------------------------------- 1 | # coding: utf-8 2 | 3 | require_relative "../../citation_helper" 4 | 5 | describe "citealt* macro with authoryear style" do 6 | let(:options) { { "bibliography-tex-style" => "authoryear", "bibliography-database" => "database.bib" } } 7 | 8 | it "formats a single citation" do 9 | expect(formatted_citation("citealt*:[Erdos65]", options: options)). 10 | to eq "Erdős, Heyting, and Brouwer 1965" 11 | end 12 | 13 | it "formats a grouped citation" do 14 | expect(formatted_citation("citealt*:[Erdos65]+[Einstein35]", options: options)). 15 | to eq "Erdős, Heyting, and Brouwer 1965; Einstein, Podolsky, and Rosen 1935" 16 | end 17 | 18 | it "formats a single citation with a prefix" do 19 | expect(formatted_citation("citealt*:[Erdos65, prefix=see]", options: options)). 20 | to eq "Erdős, Heyting, and Brouwer see 1965" 21 | end 22 | 23 | it "formats a single citation with a suffix" do 24 | expect(formatted_citation("citealt*:[Erdos65, suffix=new edition]", options: options)). 25 | to eq "Erdős, Heyting, and Brouwer 1965, new edition" 26 | end 27 | 28 | it "formats a single citation with both a prefix and a suffix" do 29 | expect(formatted_citation("citealt*:[Erdos65, prefix=see, suffix=new edition]", options: options)). 30 | to eq "Erdős, Heyting, and Brouwer see 1965, new edition" 31 | end 32 | 33 | it "formats a single citation with a standard locator" do 34 | expect(formatted_citation("citealt*:[Erdos65, page=41-43]", options: options)). 35 | to eq "Erdős, Heyting, and Brouwer 1965, pp. 41-43" 36 | end 37 | 38 | it "formats a single citation with a custom locator" do 39 | expect(formatted_citation("citealt*:[Erdos65, locator=somewhere]", options: options)). 40 | to eq "Erdős, Heyting, and Brouwer 1965, somewhere" 41 | end 42 | end 43 | -------------------------------------------------------------------------------- /spec/csl/styles/tex_citets_authoryear_spec.rb: -------------------------------------------------------------------------------- 1 | # coding: utf-8 2 | 3 | require_relative "../../citation_helper" 4 | 5 | describe "citet* macro with authoryear style" do 6 | let(:options) { { "bibliography-tex-style" => "authoryear", "bibliography-database" => "database.bib" } } 7 | 8 | it "formats a single citation" do 9 | expect(formatted_citation("citet*:[Erdos65]", options: options)). 10 | to eq "Erdős, Heyting, and Brouwer (1965)" 11 | end 12 | 13 | it "formats a grouped citation" do 14 | expect(formatted_citation("citet*:[Erdos65]+[Einstein35]", options: options)). 15 | to eq "Erdős, Heyting, and Brouwer (1965); Einstein, Podolsky, and Rosen (1935)" 16 | end 17 | 18 | it "formats a single citation with a prefix" do 19 | expect(formatted_citation("citet*:[Erdos65, prefix=see]", options: options)). 20 | to eq "Erdős, Heyting, and Brouwer (see 1965)" 21 | end 22 | 23 | it "formats a single citation with a suffix" do 24 | expect(formatted_citation("citet*:[Erdos65, suffix=new edition]", options: options)). 25 | to eq "Erdős, Heyting, and Brouwer (1965, new edition)" 26 | end 27 | 28 | it "formats a single citation with both a prefix and a suffix" do 29 | expect(formatted_citation("citet*:[Erdos65, prefix=see, suffix=new edition]", options: options)). 30 | to eq "Erdős, Heyting, and Brouwer (see 1965, new edition)" 31 | end 32 | 33 | it "formats a single citation with a standard locator" do 34 | expect(formatted_citation("citet*:[Erdos65, page=41-43]", options: options)). 35 | to eq "Erdős, Heyting, and Brouwer (1965, pp. 41-43)" 36 | end 37 | 38 | it "formats a single citation with a custom locator" do 39 | expect(formatted_citation("citet*:[Erdos65, locator=somewhere]", options: options)). 40 | to eq "Erdős, Heyting, and Brouwer (1965, somewhere)" 41 | end 42 | end 43 | -------------------------------------------------------------------------------- /spec/csl/styles/tex_citeps_authoryear_spec.rb: -------------------------------------------------------------------------------- 1 | # coding: utf-8 2 | 3 | require_relative "../../citation_helper" 4 | 5 | describe "citep* macro with authoryear style" do 6 | let(:options) { { "bibliography-tex-style" => "authoryear", "bibliography-database" => "database.bib" } } 7 | 8 | it "formats a single citation" do 9 | expect(formatted_citation("citep*:[Erdos65]", options: options)). 10 | to eq "(Erdős, Heyting, and Brouwer, 1965)" 11 | end 12 | 13 | it "formats a grouped citation" do 14 | expect(formatted_citation("citep*:[Erdos65]+[Einstein35]", options: options)). 15 | to eq "(Erdős, Heyting, and Brouwer, 1965; Einstein, Podolsky, and Rosen, 1935)" 16 | end 17 | 18 | it "formats a single citation with a prefix" do 19 | expect(formatted_citation("citep*:[Erdos65, prefix=see]", options: options)). 20 | to eq "(see Erdős, Heyting, and Brouwer, 1965)" 21 | end 22 | 23 | it "formats a single citation with a suffix" do 24 | expect(formatted_citation("citep*:[Erdos65, suffix=new edition]", options: options)). 25 | to eq "(Erdős, Heyting, and Brouwer, 1965, new edition)" 26 | end 27 | 28 | it "formats a single citation with both a prefix and a suffix" do 29 | expect(formatted_citation("citep*:[Erdos65, prefix=see, suffix=new edition]", options: options)). 30 | to eq "(see Erdős, Heyting, and Brouwer, 1965, new edition)" 31 | end 32 | 33 | it "formats a single citation with a standard locator" do 34 | expect(formatted_citation("citep*:[Erdos65, page=41-43]", options: options)). 35 | to eq "(Erdős, Heyting, and Brouwer, 1965, pp. 41-43)" 36 | end 37 | 38 | it "formats a single citation with a custom locator" do 39 | expect(formatted_citation("citep*:[Erdos65, locator=somewhere]", options: options)). 40 | to eq "(Erdős, Heyting, and Brouwer, 1965, somewhere)" 41 | end 42 | end 43 | -------------------------------------------------------------------------------- /spec/csl/styles/tex_citealps_authoryear_spec.rb: -------------------------------------------------------------------------------- 1 | # coding: utf-8 2 | 3 | require_relative "../../citation_helper" 4 | 5 | describe "citealp* macro with authoryear style" do 6 | let(:options) { { "bibliography-tex-style" => "authoryear", "bibliography-database" => "database.bib" } } 7 | 8 | it "formats a single citation" do 9 | expect(formatted_citation("citealp*:[Erdos65]", options: options)). 10 | to eq "Erdős, Heyting, and Brouwer, 1965" 11 | end 12 | 13 | it "formats a grouped citation" do 14 | expect(formatted_citation("citealp*:[Erdos65]+[Einstein35]", options: options)). 15 | to eq "Erdős, Heyting, and Brouwer, 1965; Einstein, Podolsky, and Rosen, 1935" 16 | end 17 | 18 | it "formats a single citation with a prefix" do 19 | expect(formatted_citation("citealp*:[Erdos65, prefix=see]", options: options)). 20 | to eq "see Erdős, Heyting, and Brouwer, 1965" 21 | end 22 | 23 | it "formats a single citation with a suffix" do 24 | expect(formatted_citation("citealp*:[Erdos65, suffix=new edition]", options: options)). 25 | to eq "Erdős, Heyting, and Brouwer, 1965, new edition" 26 | end 27 | 28 | it "formats a single citation with both a prefix and a suffix" do 29 | expect(formatted_citation("citealp*:[Erdos65, prefix=see, suffix=new edition]", options: options)). 30 | to eq "see Erdős, Heyting, and Brouwer, 1965, new edition" 31 | end 32 | 33 | it "formats a single citation with a standard locator" do 34 | expect(formatted_citation("citealp*:[Erdos65, page=41-43]", options: options)). 35 | to eq "Erdős, Heyting, and Brouwer, 1965, pp. 41-43" 36 | end 37 | 38 | it "formats a single citation with a custom locator" do 39 | expect(formatted_citation("citealp*:[Erdos65, locator=somewhere]", options: options)). 40 | to eq "Erdős, Heyting, and Brouwer, 1965, somewhere" 41 | end 42 | end 43 | -------------------------------------------------------------------------------- /spec/citation_helper.rb: -------------------------------------------------------------------------------- 1 | # coding: utf-8 2 | 3 | require "asciidoctor-bibliography" 4 | 5 | def init_bibliographer(options: {}) 6 | bibliographer = AsciidoctorBibliography::Bibliographer.new 7 | 8 | opts = options.dup 9 | 10 | db_path = File.join __dir__, "fixtures", opts.delete("bibliography-database") 11 | bibliographer.database = AsciidoctorBibliography::Database.new.append db_path 12 | 13 | bibliographer.options = 14 | AsciidoctorBibliography::Options.new. 15 | merge( 16 | "bibliography-hyperlinks" => "false", 17 | "bibliography-prepend-empty" => "false", 18 | ).merge(opts) 19 | 20 | bibliographer 21 | end 22 | 23 | def formatted_citation(macro, options: {}) 24 | bibliographer = init_bibliographer options: options 25 | 26 | macro.gsub(AsciidoctorBibliography::Citation::REGEXP) do 27 | macro_name, macro_pars = Regexp.last_match.captures 28 | target_and_attributes_list_pairs = macro_pars.scan(AsciidoctorBibliography::Citation::MACRO_PARAMETERS_REGEXP) 29 | citation = AsciidoctorBibliography::Citation.new(macro_name, *target_and_attributes_list_pairs) 30 | bibliographer.add_citation(citation) 31 | citation.render bibliographer 32 | end 33 | end 34 | 35 | def formatted_bibliography(macro, options: {}) 36 | bibliographer = init_bibliographer options: options 37 | macro.gsub(AsciidoctorBibliography::Citation::REGEXP) do 38 | macro_name, macro_pars = Regexp.last_match.captures 39 | target_and_attributes_list_pairs = macro_pars.scan(AsciidoctorBibliography::Citation::MACRO_PARAMETERS_REGEXP) 40 | citation = AsciidoctorBibliography::Citation.new(macro_name, *target_and_attributes_list_pairs) 41 | bibliographer.add_citation(citation) 42 | # citation.render bibliographer 43 | index = AsciidoctorBibliography::Index.new("bibliography", "", "") 44 | index.render(bibliographer).join 45 | end 46 | end 47 | -------------------------------------------------------------------------------- /spec/csl/styles/tex_citets_numeric_spec.rb: -------------------------------------------------------------------------------- 1 | # coding: utf-8 2 | 3 | require_relative "../../citation_helper" 4 | 5 | describe "citet* macro with numeric style" do 6 | let(:options) { { "bibliography-tex-style" => "numeric", "bibliography-database" => "database.bib" } } 7 | 8 | it "formats a single citation" do 9 | expect(formatted_citation("citet*:[Erdos65]", options: options)). 10 | to eq "Erdős, Heyting, and Brouwer [1]" 11 | end 12 | 13 | it "formats a grouped citation" do 14 | expect(formatted_citation("citet*:[Erdos65]+[Einstein35]", options: options)). 15 | to eq "Erdős, Heyting, and Brouwer [1], Einstein, Podolsky, and Rosen [2]" 16 | end 17 | 18 | it "formats a single citation with a prefix" do 19 | expect(formatted_citation("citet*:[Erdos65, prefix=see]", options: options)). 20 | to eq "Erdős, Heyting, and Brouwer [see 1]" 21 | end 22 | 23 | it "formats a single citation with a suffix" do 24 | expect(formatted_citation("citet*:[Erdos65, suffix=new edition]", options: options)). 25 | to eq "Erdős, Heyting, and Brouwer [1, new edition]" 26 | end 27 | 28 | it "formats a single citation with both a prefix and a suffix" do 29 | expect(formatted_citation("citet*:[Erdos65, prefix=see, suffix=new edition]", options: options)). 30 | to eq "Erdős, Heyting, and Brouwer [see 1, new edition]" 31 | end 32 | 33 | it "formats a single citation with a standard locator" do 34 | expect(formatted_citation("citet*:[Erdos65, page=41-43]", options: options)). 35 | to eq "Erdős, Heyting, and Brouwer [1, pp. 41-43]" 36 | end 37 | 38 | it "formats a single citation with a custom locator" do 39 | expect(formatted_citation("citet*:[Erdos65, locator=somewhere]", options: options)). 40 | to eq "Erdős, Heyting, and Brouwer [1, somewhere]" 41 | end 42 | end 43 | -------------------------------------------------------------------------------- /spec/citeproc/ruby/formats/adoc_spec.rb: -------------------------------------------------------------------------------- 1 | # coding: utf-8 2 | 3 | require "asciidoctor-bibliography" 4 | require_relative "../../../citation_helper" 5 | 6 | describe CiteProc::Ruby::Formats::Adoc do 7 | before { processor.import(BibTeX.open("spec/fixtures/database.bib").to_citeproc) } 8 | 9 | context "using apa citations" do 10 | let(:processor) { CiteProc::Processor.new(style: "apa", format: "adoc") } 11 | let(:year) { processor.engine.style.citation.children["layout"].children[0].children[1] } 12 | let(:rendered_citation) { processor.render(:citation, id: "Gettier63") } 13 | 14 | describe ".apply_font_style" do 15 | it "makes journal italic" do 16 | year["font-style"] = "italic" 17 | expect(rendered_citation).to eq("(Gettier, _1963_)") 18 | end 19 | end 20 | 21 | describe ".apply_font_weight" do 22 | it "makes journal bold" do 23 | year["font-weight"] = "bold" 24 | expect(rendered_citation).to eq("(Gettier, *1963*)") 25 | end 26 | end 27 | 28 | describe ".apply_vertical_align" do 29 | it "makes journal supscript " do 30 | year["vertical-align"] = "sup" 31 | expect(rendered_citation).to eq("(Gettier, ^1963^)") 32 | end 33 | 34 | it "makes journal subscript " do 35 | year["vertical-align"] = "sub" 36 | expect(rendered_citation).to eq("(Gettier, ~1963~)") 37 | end 38 | end 39 | end 40 | 41 | context "using ieee bibliography" do 42 | let(:processor) { CiteProc::Processor.new(style: "ieee", format: "adoc") } 43 | let(:rendered_bibliography) { processor.render(:bibliography, id: "Gettier63").first } 44 | 45 | describe ".apply_suffix" do 46 | before { processor.import(BibTeX.open("spec/fixtures/database.bib").to_citeproc) } 47 | it "adds space between first and second field" do 48 | processor.items["Gettier63"].merge("citation-number": "0") 49 | expect(rendered_bibliography).to match(/^\[0\] E. L. Gettier/) 50 | end 51 | end 52 | end 53 | end 54 | -------------------------------------------------------------------------------- /spec/nocite_spec.rb: -------------------------------------------------------------------------------- 1 | # coding: utf-8 2 | 3 | require "asciidoctor-bibliography" 4 | 5 | describe "a typical usage of nocite" do 6 | let(:document) do 7 | input = <<~'ASCIIDOC' 8 | :bibliography-database: ./spec/fixtures/database.bib 9 | :bibliography-style: apa 10 | 11 | == Hidden citations 12 | Nothing here: nocite:[Lane12a]. 13 | Nothing here: nocite:[Erdos65]+special[Einstein35]. 14 | 15 | == Default bibliography 16 | bibliography::[] 17 | 18 | == Special bibliography 19 | bibliography::special[] 20 | ASCIIDOC 21 | document = ::Asciidoctor::Document.new(input) 22 | document.parse 23 | document 24 | end 25 | 26 | it "hides citations and show references" do 27 | expect(document.convert).to eq <<~HTML.rstrip 28 |
29 |

Hidden citations

30 |
31 |
32 |

Nothing here: . 33 | Nothing here: .

34 |
35 |
36 |
37 |
38 |

Default bibliography

39 |
40 |
41 |

Erdős, P., Heyting, A., & Brouwer, L. E. (1965). Some very hard sums. Difficult Maths Today, 30.

42 |
43 |
44 |

Lane, P. (2000). Book title. Publisher.

45 |
46 |
47 |
48 |
49 |

Special bibliography

50 |
51 |
52 |

Einstein, A., Podolsky, B., & Rosen, N. (1935). Can quantum-mechanical description of physical reality be considered complete? Physical Review, 47(10), 777.

53 |
54 |
55 |
56 | HTML 57 | end 58 | end 59 | -------------------------------------------------------------------------------- /asciidoctor-bibliography.gemspec: -------------------------------------------------------------------------------- 1 | # coding: utf-8 2 | 3 | lib = File.expand_path("../lib", __FILE__) 4 | $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib) 5 | require "asciidoctor-bibliography/version" 6 | 7 | Gem::Specification.new do |spec| # rubocop:disable Metrics/BlockLength 8 | spec.name = "asciidoctor-bibliography" 9 | spec.version = AsciidoctorBibliography::VERSION 10 | spec.authors = ["Ribose Inc."] 11 | spec.email = ["open.source@ribose.com"] 12 | 13 | spec.summary = 'Citations and bibliography the "asciidoctor-way"' 14 | spec.description = <<~SPEC 15 | asciidoctor-bibliography lets you handle citations and bibliography the "asciidoctor-way"! 16 | 17 | Its syntax is designed to be native-asciidoctor: 18 | * single cite `cite:[key]`; 19 | * contextual cite `cite[key, page=3]`; 20 | * multiple cites `cite:[key1]+[key2]`; 21 | * full cite `fullcite:[key]`; and 22 | * TeX-compatible macros including `citep:[key]`, `citet:[key]` and friends. 23 | 24 | Citation output styles are fully bridged to the CSL library, supporting formats such as IEEE, APA, Chicago, DIN and ISO 690. 25 | 26 | The `bibliography::[]` command generates a full reference list that adheres to your configured citation style. 27 | SPEC 28 | 29 | spec.homepage = "https://github.com/riboseinc/asciidoctor-bibliography" 30 | spec.license = "MIT" 31 | 32 | spec.require_paths = ["lib"] 33 | spec.files = `git ls-files`.split("\n") 34 | spec.test_files = `git ls-files -- {spec}/*`.split("\n") 35 | spec.required_ruby_version = Gem::Requirement.new(">= 2.5.0") 36 | 37 | spec.add_dependency "asciidoctor", ">= 1.5.6" 38 | spec.add_dependency "bibtex-ruby", "~> 6.0.0" 39 | spec.add_dependency "citeproc-ruby", "~> 1.1.7" 40 | spec.add_dependency "csl-styles", "~> 1.0.1" 41 | spec.add_dependency "latex-decode", "~> 0.2.2" 42 | spec.add_dependency "nokogiri", "~> 1.8" 43 | 44 | spec.add_development_dependency "byebug" 45 | spec.add_development_dependency "rake", "~> 12.3" 46 | spec.add_development_dependency "rspec", "~> 3.7" 47 | spec.add_development_dependency "rubocop" 48 | spec.add_development_dependency "simplecov" 49 | spec.add_development_dependency "yard" 50 | end 51 | -------------------------------------------------------------------------------- /lib/asciidoctor-bibliography/databases/bibtex.rb: -------------------------------------------------------------------------------- 1 | require "bibtex" 2 | require "bibtex/filters" 3 | require "latex/decode/base" 4 | require "latex/decode/maths" 5 | require "latex/decode/accents" 6 | require "latex/decode/diacritics" 7 | require "latex/decode/punctuation" 8 | require "latex/decode/symbols" 9 | require "latex/decode/greek" 10 | 11 | module AsciidoctorBibliography 12 | module Databases 13 | module BibTeX 14 | EXTENSIONS = %w[.bib .bibtex .biblatex].freeze 15 | 16 | def self.load(filename) 17 | # TODO: detect BibLaTeX code w/ other extensions 18 | warn <<~MESSAGE if File.extname(filename) == '.biblatex' 19 | WARNING: you are requiring a BibLaTeX database; only features compatible with BibTeX are guaranteed to work. 20 | MESSAGE 21 | ::BibTeX.open(filename, filter: [LatexFilter]).to_citeproc 22 | end 23 | 24 | # NOTE: the class below comes from asciidoctor-bibtex 25 | 26 | # This filter extends the original latex filter in bibtex-ruby to handle 27 | # unknown latex macros more gracefully. We could have used latex-decode 28 | # gem together with our custom replacement rules, but latex-decode eats up 29 | # all braces after it finishes all decoding. So we hack over the 30 | # LaTeX.decode function and insert our rules before `strip_braces`. 31 | class LatexFilter < ::BibTeX::Filter 32 | def apply(value) # rubocop:disable Metrics/MethodLength; keep this a list, though! 33 | text = value.to_s 34 | LaTeX::Decode::Base.normalize(text) 35 | LaTeX::Decode::Maths.decode!(text) 36 | LaTeX::Decode::Accents.decode!(text) 37 | LaTeX::Decode::Diacritics.decode!(text) 38 | LaTeX::Decode::Punctuation.decode!(text) 39 | LaTeX::Decode::Symbols.decode!(text) 40 | LaTeX::Decode::Greek.decode!(text) 41 | # TODO: could we be doing something smarter with some macros, e.g. \url? 42 | text.gsub!(/\\url\{(.+?)\}/, ' \\1 ') 43 | text.gsub!(/\\\w+(?=\s+\w)/, "") 44 | text.gsub!(/\\\w+(?:\[.+?\])?\s*\{(.+?)\}/, '\\1') 45 | LaTeX::Decode::Base.strip_braces(text) 46 | LaTeX.normalize_C(text) 47 | end 48 | end 49 | end 50 | end 51 | end 52 | -------------------------------------------------------------------------------- /spec/fixtures/database.bib: -------------------------------------------------------------------------------- 1 | @book{Lane12a, 2 | author = {P. Lane}, 3 | title = {Book title}, 4 | publisher = {Publisher}, 5 | year = {2000} 6 | } 7 | 8 | @book{Lane12b, 9 | author = {K. Mane and D. Smith}, 10 | title = {Book title}, 11 | publisher = {Publisher}, 12 | year = {2000} 13 | } 14 | 15 | @book{Anderson98, 16 | editor = {J. R. Anderson and C. Lebiere}, 17 | title = {The Atomic Components of {2\sum} Thought}, 18 | publisher = {Lawrence Erlbaum}, 19 | address = {Mahwah, NJ}, 20 | year = {1998} 21 | } 22 | 23 | @article{Anderson04, 24 | author = {J. R. Anderson and D. Bothell and M. D. Byrne and S. Douglass and C. Lebiere and Y. L. Qin}, 25 | title = {An integrated theory of the mind}, 26 | journal = {Psychological Review}, 27 | volume = {111}, 28 | number = {4}, 29 | pages = {1036--1060}, 30 | year = {2004} 31 | } 32 | 33 | @article{Erdos65, 34 | title = {Some very hard sums}, 35 | journal={Difficult Maths Today}, 36 | author={Paul Erdős and Arend Heyting and Luitzen Egbertus Brouwer}, 37 | year={1965}, 38 | pages={30} 39 | } 40 | 41 | @article{Einstein35, 42 | title={Can quantum-mechanical description of physical reality be considered complete?}, 43 | author={Einstein, Albert and Podolsky, Boris and Rosen, Nathan}, 44 | journal={Physical review}, 45 | volume={47}, 46 | number={10}, 47 | pages={777}, 48 | year={1935}, 49 | publisher={APS} 50 | } 51 | 52 | @article{Gettier63, 53 | title={Is justified true belief knowledge?}, 54 | author={Gettier, Edmund L}, 55 | journal={analysis}, 56 | volume={23}, 57 | number={6}, 58 | pages={121--123}, 59 | year={1963}, 60 | publisher={JSTOR} 61 | } 62 | 63 | @techreport{iso:31000, 64 | author = {ISO}, 65 | institution = {International Organization for Standardization}, 66 | address = {Geneva, Switzerland}, 67 | title = {Risk management---Principles and guidelines}, 68 | number = {31000:2009}, 69 | shorthand = {ISO 31000:2009}, 70 | type = {ISO}, 71 | year = {2009} 72 | } 73 | 74 | @techreport{iso:guide73, 75 | author = {ISO}, 76 | institution = {International Organization for Standardization}, 77 | address = {Geneva, Switzerland}, 78 | title = {Risk management---Vocabulary}, 79 | number = {73:2009(E/F)}, 80 | shorthand = {ISO Guide 73:2009}, 81 | type = {ISO Guide}, 82 | year = {2013} 83 | } 84 | -------------------------------------------------------------------------------- /lib/asciidoctor-bibliography/index.rb: -------------------------------------------------------------------------------- 1 | require "asciidoctor/attribute_list" 2 | require_relative "formatter" 3 | 4 | module AsciidoctorBibliography 5 | class Index 6 | REGEXP = /^(bibliography)::(\S+)?\[(|.*?[^\\])\]$/ 7 | 8 | attr_reader :macro, :target, :attributes 9 | 10 | def initialize(macro, target, attributes) 11 | @macro = macro 12 | @target = target.to_s.empty? ? "default" : target 13 | @attributes = ::Asciidoctor::AttributeList.new(attributes).parse 14 | end 15 | 16 | def render(bibliographer) 17 | formatter = setup_formatter bibliographer 18 | 19 | lines = [] 20 | formatter.bibliography.each_with_index do |reference, index| 21 | id = anchor_id "bibliography", target, formatter.data[index].id 22 | lines << wrap_up_reference(reference: reference, id: id, bibliographer: bibliographer) 23 | end 24 | 25 | # Intersperse the lines with empty ones to render as paragraphs. 26 | lines.join("\n\n").lines.map(&:strip) 27 | end 28 | 29 | private 30 | 31 | def wrap_up_reference(reference:, id:, bibliographer:) 32 | text = reference.dup 33 | text.prepend "anchor:#{id}[]" if bibliographer.options.hyperlinks? 34 | text = ["+++", reference, "+++"].join if bibliographer.options.passthrough?(:reference) 35 | text.prepend "{empty}" if bibliographer.options.prepend_empty?(:reference) 36 | text 37 | end 38 | 39 | def setup_formatter(bibliographer) 40 | formatter = Formatter.new(bibliographer.options.style, locale: bibliographer.options.locale) 41 | 42 | formatter.replace_bibliography_sort bibliographer.options.sort unless bibliographer.options.sort.nil? 43 | 44 | filtered_db = prepare_filtered_db bibliographer 45 | formatter.import filtered_db 46 | formatter.force_sort!(mode: :bibliography) 47 | 48 | formatter 49 | end 50 | 51 | def prepare_filtered_db(bibliographer) 52 | if bibliographer.occurring_keys.include? target 53 | bibliographer.occurring_keys[target]. 54 | map { |id| bibliographer.database.find_entry_by_id(id) }. 55 | map { |entry| prepare_entry_metadata bibliographer, entry } 56 | else {} 57 | end 58 | end 59 | 60 | def prepare_entry_metadata(bibliographer, entry) 61 | entry. 62 | merge('citation-number': bibliographer.appearance_index_of(target, entry["id"])). 63 | merge('citation-label': entry["id"]) # TODO: smart label generators 64 | end 65 | 66 | def anchor_id(*fragments) 67 | fragments.compact.join("-") 68 | end 69 | end 70 | end 71 | -------------------------------------------------------------------------------- /spec/end_to_end_spec.rb: -------------------------------------------------------------------------------- 1 | # coding: utf-8 2 | 3 | require "asciidoctor-bibliography" 4 | require "asciidoctor-bibliography/asciidoctor/bibliographer_preprocessor" 5 | 6 | describe "an asciidoctor document with bibliography usage" do 7 | let(:document) do 8 | input = <<~'ASCIIDOC' 9 | = This is the document title 10 | :doctype: book 11 | :bibliography-database: ./spec/fixtures/database-issue84.bib 12 | :bibliography-style: university-of-york-mla 13 | == Section 1 14 | The Advanced Research Projects Agency Network (ARPANET), 15 | an early network connecting many major universities and 16 | research institutions in the USA, 17 | was first demonstrated publicly in October 1972 18 | cite:[roberts_arpanet_1986, page=3]. 19 | It was initially funded by the United States 20 | Department of Defense during the cold war as a part of 21 | "the command and control assignment" of the ARPA program 22 | cite:[lukasik_why_2011, page=10]. 23 | The ((ARPANET)) was designed to be "as distributed as possible," 24 | because its routing algorithm was adapted from an article by Paul Baran, 25 | written at the time he was at the RAND Corporation researching 26 | on highly survivable communication networks "in the thermonuclear era" 27 | cite:[baran_distributed_1964, page=18]. 28 | With the support of the US National Science Foundation, ARPANET gradually 29 | "evolved into a commercial, worldwide open network" -- the Internet 30 | cite:[dommering_internet:_2015, page=13]. 31 | [bibliography] 32 | == Bibliography 33 | bibliography::[] 34 | ASCIIDOC 35 | document = ::Asciidoctor::Document.new(input) 36 | document.parse 37 | document 38 | end 39 | 40 | it "creates a valid internal bibliographer state" do 41 | expect(document.bibliographer.occurring_keys["default"]). 42 | to eq ["roberts_arpanet_1986", 43 | "lukasik_why_2011", 44 | "baran_distributed_1964", 45 | "dommering_internet:_2015"] 46 | end 47 | 48 | it "generates the correct mla bibliography" do 49 | expect(document.catalog[:refs]["_bibliography"].blocks[0].lines[0]). 50 | to include("Baran, Paul.") 51 | expect(document.catalog[:refs]["_bibliography"].blocks[1].lines[0]). 52 | to include("Dommering, E., et al.") 53 | expect(document.catalog[:refs]["_bibliography"].blocks[2].lines[0]). 54 | to include("Lukasik, Stephen.") 55 | expect(document.catalog[:refs]["_bibliography"].blocks[3].lines[0]). 56 | to include("Roberts, Larry.") 57 | end 58 | end 59 | -------------------------------------------------------------------------------- /spec/database_spec.rb: -------------------------------------------------------------------------------- 1 | # coding: utf-8 2 | 3 | describe AsciidoctorBibliography::Database do 4 | describe ".new" do 5 | it "is by default an empty array" do 6 | expect(described_class.new).to eq([]) 7 | end 8 | 9 | it "can be initialized with a single database" do 10 | expect(described_class.new("spec/fixtures/database.bib")).to_not eq([]) 11 | end 12 | 13 | it "can be initialized with a list of databases" do 14 | expect(described_class.new("spec/fixtures/database.bib", "spec/fixtures/database.bibtex")).to_not eq([]) 15 | end 16 | end 17 | 18 | describe "#find_entry_by_id" do 19 | subject { described_class.new("spec/fixtures/database.bib") } 20 | 21 | it "finds an existing id" do 22 | expect { subject.find_entry_by_id("foo") }. 23 | to raise_exception AsciidoctorBibliography::Errors::Database::IdNotFound 24 | end 25 | 26 | it "raises error if asked to retrieve unexisting id" do 27 | expect(subject.find_entry_by_id("Lane12a")). 28 | to eq("author" => [{ "family" => "Lane", "given" => "P." }], 29 | "title" => "Book title", 30 | "publisher" => "Publisher", 31 | "id" => "Lane12a", 32 | "issued" => { "date-parts" => [[2000]] }, 33 | "type" => "book") 34 | end 35 | end 36 | 37 | describe "#append" do 38 | let(:db) { described_class.new } 39 | 40 | it "can load and concatenate databases after initialization" do 41 | expect(db.length).to eq(0) 42 | expect { db.append("spec/fixtures/database.bib") }.to(change { db.length }) 43 | expect { db.append("spec/fixtures/database.bibtex") }.to(change { db.length }) 44 | end 45 | 46 | it "raises error if conflicting ids are found" do 47 | db.append("spec/fixtures/database.bib") 48 | expect { db.append("spec/fixtures/database.bib") }. 49 | to raise_exception AsciidoctorBibliography::Errors::Database::ConflictingIds 50 | end 51 | end 52 | 53 | describe ".load" do 54 | it "raises error if given non existing file" do 55 | expect { described_class.load "spec/fixtures/database.xxx" }. 56 | to raise_exception AsciidoctorBibliography::Errors::Database::FileNotFound 57 | end 58 | 59 | it "raises error if given unknown format" do 60 | expect { described_class.load "spec/fixtures/database.unk" }. 61 | to raise_exception AsciidoctorBibliography::Errors::Database::UnsupportedFormat 62 | end 63 | 64 | it "recognizes Bib(La)Tex databases" do 65 | expect { described_class.load "spec/fixtures/database.bib" }.to_not raise_exception 66 | expect { described_class.load "spec/fixtures/database.bibtex" }.to_not raise_exception 67 | end 68 | end 69 | end 70 | -------------------------------------------------------------------------------- /spec/macros_spec.rb: -------------------------------------------------------------------------------- 1 | # coding: utf-8 2 | 3 | require_relative "citation_helper" 4 | 5 | describe "cite macro with apa style" do 6 | it "formats a complex citation" do 7 | expect(formatted_citation("cite:[Erdos65, prefix='see ']+[Einstein35, page=41-43]", 8 | options: { "bibliography-style" => "apa", 9 | "bibliography-database" => "database.bib", 10 | "bibliography-hyperlinks" => "true" })). 11 | to eq "(<>; " + 12 | "<>)" 13 | end 14 | end 15 | 16 | describe "cite macro with arbitrary interpolated text" do 17 | it "formats a complex citation" do 18 | expect(formatted_citation("cite:[Erdos65, text=foo {cite} bar]", 19 | options: { "bibliography-style" => "apa", 20 | "bibliography-database" => "database.bib", 21 | "bibliography-hyperlinks" => "true" })). 22 | to eq "(<>)" 23 | end 24 | end 25 | 26 | describe "fullcite macro with apa style" do 27 | it "formats a complex citation" do 28 | expect(formatted_citation("fullcite:[Erdos65]", 29 | options: { "bibliography-style" => "apa", 30 | "bibliography-database" => "database.bib" })). 31 | to eq "Erdős, P., Heyting, A., & Brouwer, L. E. (1965). Some very hard sums. _Difficult Maths Today_, 30." 32 | end 33 | end 34 | 35 | describe "cite macro using an unknown key" do 36 | it "formats bold question marks" do 37 | expect(formatted_citation("cite:[Erdos65]+[foobar]", 38 | options: { "bibliography-style" => "apa", 39 | "bibliography-database" => "database.bib", 40 | "bibliography-hyperlinks" => "true" })). 41 | to eq "*??*" 42 | end 43 | end 44 | 45 | describe "cite macro using more than two keys" do 46 | it "formats all cited keys" do 47 | expect(formatted_citation("cite:[Lane12a]+[Lane12b]+[Erdos65]+[Einstein35]", 48 | options: { "bibliography-style" => "apa", 49 | "bibliography-database" => "database.bib", 50 | "bibliography-hyperlinks" => "true" })). 51 | to eq "(<>; <>; <>; <>)" 52 | end 53 | end 54 | -------------------------------------------------------------------------------- /SYNTAX.adoc: -------------------------------------------------------------------------------- 1 | = asciidoctor-bibliography Syntax 2 | 3 | We base our syntax off the asciidoctor `footnoteref` command. 4 | 5 | [source,ruby] 6 | ---- 7 | footnoteref:[ref,Opinions are my own.] 8 | footnoteref:[ref] 9 | ---- 10 | 11 | asciidoctor supports these commands now: 12 | 13 | Attributes: 14 | [source,ruby] 15 | ---- 16 | video::video_file.mp4[width=640, start=60, end=140, options=autoplay] 17 | ---- 18 | 19 | Options: 20 | [source,ruby] 21 | ---- 22 | audio::ocean_waves.mp3[options="autoplay,loop"] 23 | ---- 24 | 25 | The "and" syntax: 26 | 27 | [source,ruby] 28 | ---- 29 | \ifdef::env-github+backend-html5[HTML5 only.] 30 | ---- 31 | 32 | 33 | == Proposed Syntax 34 | 35 | === Basic Usage 36 | 37 | [source,ruby] 38 | ---- 39 | # Output => "[1]" 40 | cite:[foo] 41 | 42 | # Output => "[1, Page 5]" 43 | cite:[foo, page=5] 44 | 45 | # Output => "[1, Page 5; 2, Chapter 21]" 46 | cite:[foo, page=5]+[foobar, chapter=21] 47 | 48 | # Output => "[1, 2]" 49 | # or => "[1-2]" 50 | cite:[foo]+[foobar] 51 | 52 | # Output => "[1, 3]" 53 | cite:[foo]+[bar] 54 | ---- 55 | 56 | === BibTeX-compatible Usage 57 | 58 | [source,ruby] 59 | ---- 60 | # BibTeX \citet{goossens93} 61 | # Output: "Goossens et al. (1993)" 62 | citet:[goossens93] 63 | cite:[goossens93] 64 | cite:[goossens93, authors=abbrev, format="%authors% (%year%)"] 65 | 66 | # BibTeX \citet{goossens93} 67 | # Output "(Goossens et al., 1993)" 68 | citep:[goossens93] 69 | cite:[goossens93, type=parens] 70 | cite:[goossens93, authors=abbrev, format="(%authors%, %year%)"] 71 | 72 | # BibTeX \citet*{goossens93} 73 | # Output "Goossens, Mittlebach, and Samarin (1993)" 74 | citets:[goossens93] 75 | cite:[goossens93, authors=full, type=text] 76 | cite:[goossens93, authors=full, format="%authors% (%year%)"] 77 | 78 | # BibTeX \citep*{goossens93} 79 | # Output "(Goossens, Mittlebach, and Samarin, 1993)" 80 | citeps:[goossens93] 81 | cite:[goossens93, authors=full, type=parens] 82 | cite:[goossens93, authors=full, format="(%authors%, %year%)"] 83 | 84 | # BibTeX \citeauthor{goossens93} 85 | # Output "Goossens et al." 86 | citeauthor:[goossens93] 87 | cite:[goossens93, only=authors, authors=abbrev] 88 | cite:[goossens93, authors=abbrev, format="%authors%"] 89 | 90 | # BibTeX \citeauthor*{goossens93} 91 | # Output => "Goossens, Mittlebach, and Samarin" 92 | citeauthors:[goossens93] 93 | cite:[goossens93, only=authors, authors=full] 94 | cite:[goossens93, authors=full, format="%authors%"] 95 | 96 | # BibTeX \citeyear{goossens93} 97 | # Output => "1993" 98 | citeyear:[goossens93] 99 | cite:[goossens93, only=year] 100 | cite:[goossens93, format="%year%"] 101 | 102 | # BibTeX \citeyearpar{goossens93} 103 | # Output => "(1993)" 104 | citeyear:[goossens93] 105 | cite:[goossens93, format="(%year%)"] 106 | 107 | # BibTeX \citealt{goossens93} 108 | # Output => "Goossens et al. 1993" 109 | citealt:[goossens93] 110 | cite:[goossens93, authors=abbrev, format="%authors% %year%"] 111 | 112 | # BibTeX \citealp{goossens93} 113 | # Output => "Goossens et al., 1993" 114 | citealp:[goossens93] 115 | cite:[goossens93, authors=abbrev, format="%authors%, %year%"] 116 | ---- 117 | 118 | -------------------------------------------------------------------------------- /lib/asciidoctor-bibliography/asciidoctor/bibliographer_preprocessor.rb: -------------------------------------------------------------------------------- 1 | require "asciidoctor" 2 | 3 | require_relative "../database" 4 | require_relative "../citation" 5 | require_relative "../index" 6 | require_relative "../options" 7 | 8 | module AsciidoctorBibliography 9 | module Asciidoctor 10 | class BibliographerPreprocessor < ::Asciidoctor::Extensions::Preprocessor 11 | def process(document, reader) 12 | document.bibliographer.options = 13 | ::AsciidoctorBibliography::Options.build document, reader 14 | 15 | document.bibliographer.database = 16 | ::AsciidoctorBibliography::Database.new *expand_db_globs(document) 17 | 18 | lines = remove_comments(reader.read_lines) 19 | processed_lines = process_lines lines, document.bibliographer 20 | reader.unshift_lines processed_lines 21 | reader 22 | end 23 | 24 | private 25 | 26 | def process_lines(lines, bibliographer) 27 | # First we fetch citations and replace them with uuids, 28 | lines = fetch_citations lines, bibliographer 29 | # then we render them 30 | lines = render_citations lines, bibliographer 31 | # and finally we render indices. 32 | render_indices lines, bibliographer 33 | end 34 | 35 | def remove_comments(lines) 36 | # Remove block comments 37 | ls = lines.join("\n").split(/^\/\/\/\/\n/). 38 | select.with_index { |_, i| i.even? }.join 39 | # Remove line comments 40 | ls.split("\n").reject { |line| line.start_with?("//") } 41 | end 42 | 43 | def fetch_citations(lines, bibliographer) 44 | lines.join("\n").gsub(Citation::REGEXP) do 45 | macro_name, macro_pars = Regexp.last_match.captures 46 | target_and_attributes_list_pairs = macro_pars.scan(Citation::MACRO_PARAMETERS_REGEXP) 47 | citation = Citation.new(macro_name, *target_and_attributes_list_pairs) 48 | bibliographer.add_citation(citation) 49 | citation.uuid 50 | end.lines.map(&:chomp) 51 | end 52 | 53 | def render_citations(lines, bibliographer) 54 | processed_lines = lines.join("\n") 55 | bibliographer.citations.each do |citation| 56 | processed_lines.sub!(citation.uuid) do 57 | citation.render bibliographer 58 | end 59 | end 60 | processed_lines.lines.map(&:chomp) 61 | end 62 | 63 | def render_indices(lines, bibliographer) 64 | lines.map do |line| 65 | if line =~ Index::REGEXP 66 | index = Index.new(*Regexp.last_match.captures) 67 | index.render bibliographer 68 | else 69 | line 70 | end 71 | end.flatten 72 | end 73 | 74 | def expand_db_globs(document) 75 | glob_pattern( 76 | document.bibliographer.options.database, 77 | document.base_dir, 78 | ) 79 | end 80 | 81 | def glob_pattern(pattern_string, base_dir) 82 | pattern_string.split.map do |pattern| 83 | Dir.chdir(base_dir) { Dir.glob(normalize_separator(pattern)) } 84 | end.flatten 85 | end 86 | 87 | def normalize_separator(path) 88 | return path if File::ALT_SEPARATOR.nil? 89 | path.gsub(File::ALT_SEPARATOR, File::SEPARATOR) 90 | end 91 | end 92 | end 93 | end 94 | -------------------------------------------------------------------------------- /spec/citation_item_spec.rb: -------------------------------------------------------------------------------- 1 | describe AsciidoctorBibliography::CitationItem do 2 | describe ".new" do 3 | it "can be mutely initialized" do 4 | expect { described_class.new }.to_not raise_exception 5 | end 6 | 7 | it "can be initialized with a block operating on itself" do 8 | itself = nil 9 | expect(described_class.new { |ci| itself = ci }).to be(itself) 10 | end 11 | end 12 | 13 | describe "#parse_attribute_list" do 14 | subject { described_class.new } 15 | 16 | before do 17 | subject.parse_attribute_list "foo, lol=bar, baz, qux, zod=13" 18 | end 19 | 20 | it "treats the first positional attribute as the id" do 21 | expect(subject.key).to eq "foo" 22 | end 23 | 24 | it "extracts the positional attributes in order, except the first one" do 25 | expect(subject.positional_attributes).to eq ["baz", "qux"] 26 | end 27 | 28 | it "extracts all named attributes" do 29 | expect(subject.named_attributes).to eq("lol" => "bar", "zod" => "13") 30 | end 31 | end 32 | 33 | describe "#locators" do 34 | subject { described_class.new } 35 | 36 | it "returns no locator if none are present" do 37 | subject.parse_attribute_list "foo, lol=bar, baz, qux, zod=42" 38 | expect(subject.locator).to be_nil 39 | end 40 | 41 | it "recognizes all CSL locators" do 42 | locators = %w[book chapter column figure folio issue line note opus 43 | page paragraph part section sub-verbo verse volume] 44 | locators_hash = locators.map { |l| [l, rand(10).to_s] }.to_h 45 | locators_string = locators_hash.to_a.map { |a| a.join "=" }.join(", ") 46 | 47 | subject.parse_attribute_list "foo, #{locators_string}" 48 | expect(subject.locators).to eq locators_hash 49 | end 50 | 51 | it "recognizes non standard locator" do 52 | subject.parse_attribute_list "foo, locator=' somewhere'" 53 | expect(subject.locators).to eq("locator" => " somewhere") 54 | end 55 | end 56 | 57 | describe "#locator" do 58 | subject { described_class.new } 59 | 60 | it "returns the first locator if existing" do 61 | subject.parse_attribute_list("foo, page=42, locator=bar, chapter=24") 62 | expect(subject.locator).to eq(%w[page 42]) 63 | end 64 | 65 | it "returns nil if no loctor exist" do 66 | subject.parse_attribute_list("foo, bar, zod=quz") 67 | expect(subject.locator).to be_nil 68 | end 69 | end 70 | 71 | describe "#prefix" do 72 | subject { described_class.new } 73 | 74 | it "returns the prefix if it exist" do 75 | subject.parse_attribute_list("foo, prefix=bar") 76 | expect(subject.prefix).to eq("bar") 77 | end 78 | 79 | it "returns nil if no prefix exists" do 80 | subject.parse_attribute_list("foo, bar, zod=quz") 81 | expect(subject.prefix).to be_nil 82 | end 83 | end 84 | 85 | describe "#suffix" do 86 | subject { described_class.new } 87 | 88 | it "returns the suffix if it exist" do 89 | subject.parse_attribute_list("foo, suffix=bar") 90 | expect(subject.suffix).to eq("bar") 91 | end 92 | 93 | it "returns nil if no suffix exists" do 94 | subject.parse_attribute_list("foo, bar, zod=quz") 95 | expect(subject.suffix).to be_nil 96 | end 97 | end 98 | 99 | describe "#text" do 100 | subject { described_class.new } 101 | 102 | it "returns the text if it exist" do 103 | subject.parse_attribute_list("foo, text='prefix {ref} suffix'") 104 | expect(subject.text).to eq("prefix {ref} suffix") 105 | end 106 | 107 | it "returns nil if no text exists" do 108 | subject.parse_attribute_list("foo, bar, zod=quz") 109 | expect(subject.text).to be_nil 110 | end 111 | end 112 | end 113 | -------------------------------------------------------------------------------- /lib/csl/styles/tex-citealp-numeric.csl: -------------------------------------------------------------------------------- 1 | 2 | 117 | -------------------------------------------------------------------------------- /lib/csl/styles/tex-citealps-numeric.csl: -------------------------------------------------------------------------------- 1 | 2 | 117 | -------------------------------------------------------------------------------- /lib/csl/styles/tex-citeauthor-numeric.csl: -------------------------------------------------------------------------------- 1 | 2 | 117 | -------------------------------------------------------------------------------- /lib/csl/styles/tex-citeauthors-numeric.csl: -------------------------------------------------------------------------------- 1 | 2 | 117 | -------------------------------------------------------------------------------- /lib/csl/styles/tex-citeauthor-authoryear.csl: -------------------------------------------------------------------------------- 1 | 2 | 117 | -------------------------------------------------------------------------------- /lib/csl/styles/tex-citeauthors-authoryear.csl: -------------------------------------------------------------------------------- 1 | 2 | 117 | -------------------------------------------------------------------------------- /lib/csl/styles/tex-citep-numeric.csl: -------------------------------------------------------------------------------- 1 | 2 | 117 | -------------------------------------------------------------------------------- /lib/csl/styles/tex-citeps-numeric.csl: -------------------------------------------------------------------------------- 1 | 2 | 117 | -------------------------------------------------------------------------------- /lib/csl/styles/tex-citeyear-numeric.csl: -------------------------------------------------------------------------------- 1 | 2 | 117 | -------------------------------------------------------------------------------- /lib/csl/styles/tex-citeyear-authoryear.csl: -------------------------------------------------------------------------------- 1 | 2 | 117 | -------------------------------------------------------------------------------- /lib/csl/styles/tex-citeyearpar-numeric.csl: -------------------------------------------------------------------------------- 1 | 2 | 117 | -------------------------------------------------------------------------------- /lib/csl/styles/tex-citeyearpar-authoryear.csl: -------------------------------------------------------------------------------- 1 | 2 | 117 | -------------------------------------------------------------------------------- /lib/csl/styles/tex-citealp-authoryear.csl: -------------------------------------------------------------------------------- 1 | 2 | 118 | -------------------------------------------------------------------------------- /lib/csl/styles/tex-citealps-authoryear.csl: -------------------------------------------------------------------------------- 1 | 2 | 118 | -------------------------------------------------------------------------------- /lib/csl/styles/tex-citep-authoryear.csl: -------------------------------------------------------------------------------- 1 | 2 | 118 | -------------------------------------------------------------------------------- /lib/csl/styles/tex-citeps-authoryear.csl: -------------------------------------------------------------------------------- 1 | 2 | 118 | -------------------------------------------------------------------------------- /spec/fixtures/database.rfc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Key words for use in RFCs to Indicate Requirement Levels 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | In many standards track documents several words are used to signify the requirements in the specification. These words are often capitalized. This document defines these words as they should be interpreted in IETF documents. This document specifies an Internet Best Current Practices for the Internet Community, and requests discussion and suggestions for improvements. 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | Writing I-Ds and RFCs using XML 24 | 25 | 26 | 27 | 28 | 29 | 30 | This memo presents a technique for using XML (Extensible Markup Language) as a source format for documents in the Internet-Drafts (I-Ds) and Request for Comments (RFC) series. This memo provides information for the Internet community. 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | Guidelines for Writing RFC Text on Security Considerations 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | All RFCs are required to have a Security Considerations section. Historically, such sections have been relatively weak. This document provides guidelines to RFC authors on how to write a good Security Considerations section. This document specifies an Internet Best Current Practices for the Internet Community, and requests discussion and suggestions for improvements. 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | Guidelines for Writing an IANA Considerations Section in RFCs 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | Many protocols make use of identifiers consisting of constants and other well-known values. Even after a protocol has been defined and deployment has begun, new values may need to be assigned (e.g., for a new option type in DHCP, or a new encryption or authentication transform for IPsec). To ensure that such quantities have consistent values and interpretations across all implementations, their assignment must be administered by a central authority. For IETF protocols, that role is provided by the Internet Assigned Numbers Authority (IANA). 74 | 75 | 76 | In order for IANA to manage a given namespace prudently, it needs guidelines describing the conditions under which new values can be assigned or when modifications to existing values can be made. If IANA is expected to play a role in the management of a namespace, IANA must be given clear and concise instructions describing that role. This document discusses issues that should be considered in formulating a policy for assigning values to a namespace and provides guidelines for authors on the specific text that must be included in documents that place demands on IANA. 77 | 78 | 79 | This document obsoletes RFC 2434. This document specifies an Internet Best Current Practices for the Internet Community, and requests discussion and suggestions for improvements. 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | -------------------------------------------------------------------------------- /lib/csl/styles/tex-citealt-numeric.csl: -------------------------------------------------------------------------------- 1 | 2 | 120 | -------------------------------------------------------------------------------- /lib/csl/styles/tex-citealts-numeric.csl: -------------------------------------------------------------------------------- 1 | 2 | 120 | -------------------------------------------------------------------------------- /lib/csl/styles/tex-citet-numeric.csl: -------------------------------------------------------------------------------- 1 | 2 | 120 | -------------------------------------------------------------------------------- /lib/csl/styles/tex-citets-numeric.csl: -------------------------------------------------------------------------------- 1 | 2 | 120 | -------------------------------------------------------------------------------- /lib/csl/styles/tex-citealt-authoryear.csl: -------------------------------------------------------------------------------- 1 | 2 | 120 | -------------------------------------------------------------------------------- /lib/csl/styles/tex-citealts-authoryear.csl: -------------------------------------------------------------------------------- 1 | 2 | 120 | -------------------------------------------------------------------------------- /lib/csl/styles/tex-citet-authoryear.csl: -------------------------------------------------------------------------------- 1 | 2 | 120 | -------------------------------------------------------------------------------- /lib/csl/styles/tex-citets-authoryear.csl: -------------------------------------------------------------------------------- 1 | 2 | 120 | --------------------------------------------------------------------------------