diff --git a/README.adoc b/README.adoc index 8d0222a..9def6b0 100644 --- a/README.adoc +++ b/README.adoc @@ -1,4 +1,4 @@ -= RelatonBib += Relaton::Bib image:https://img.shields.io/gem/v/relaton-bib.svg["Gem Version", link="https://rubygems.org/gems/relaton-bib"] image:https://github.com/relaton/relaton-bib/workflows/rake/badge.svg["Build Status", link="https://github.com/relaton/relaton-bib/actions?workflow=rake"] @@ -6,7 +6,7 @@ image:https://codeclimate.com/github/relaton/relaton-bib/badges/gpa.svg["Code Cl image:https://img.shields.io/github/issues-pr-raw/relaton/relaton-bib.svg["Pull Requests", link="https://github.com/relaton/relaton-bib/pulls"] image:https://img.shields.io/github/commits-since/relaton/relaton-bib/latest.svg["Commits since latest",link="https://github.com/relaton/relaton-bib/releases"] -RelatonBib is a Ruby gem that implements the https://github.com/metanorma/relaton-models#bibliography-uml-models[BibliographicItem model]. +Relaton::Bib is a Ruby gem that implements the https://github.com/metanorma/relaton-models#bibliography-uml-models[BibliographicItem model]. == Installation @@ -27,23 +27,34 @@ Or install it yourself as: == Usage -=== Create bibliographic item +=== Configuration + +Configuration is optional. The available option is `logger` which is a `Logger` instance. By default, the logger is `Logger.new($stderr)` with `Logger::WARN` level. To change the logger level, use `Relaton::Bib.configure` block. [source,ruby] ---- require 'relaton_bib' => true +Relaton::Bib.configure do |config| + config.logger.level = Logger::DEBUG +end +---- + +=== Create bibliographic item + +[source,ruby] +---- hash = YAML.load_file "spec/examples/bib_item.yml" => {"id"=>"ISOTC211", "fetched"=>"2022-05-02", "title"=>["Geographic information", {"content"=>"Information géographique", "language"=>"fr", "script"=>"Latn"}], ... -item = RelatonBib::BibliographicItem.from_hash(hash) -=> #<RelatonBib::BibliographicItem:0x00007f962f030710 +item = Relaton::Bib::Item.from_hash(hash) +=> #<Relaton::Bib::Item:0x00007f962f030710 @abstract= - [#<RelatonBib::FormattedString:0x00007f962f02acc0 + [#<Relaton::Bib::FormattedString:0x00007f962f02acc0 ... ---- @@ -52,24 +63,24 @@ item = RelatonBib::BibliographicItem.from_hash(hash) [source,ruby] ---- item.title -=> #<RelatonBib::TypedTitleStringCollection:0x00007fea821ec6b0 +=> #<Relaton::Bib::TitleCollection:0x00007fea821ec6b0 @array= - [#<RelatonBib::TypedTitleString:0x00007fea821ecb60 - @title=#<RelatonBib::FormattedString:0x00007fea821eca70 @content="Geographic information", @format="text/plain", @language=nil, @script=nil>, + [#<Relaton::Bib::Title:0x00007fea821ecb60 + @title=#<Relaton::Bib::FormattedString:0x00007fea821eca70 @content="Geographic information", @format="text/plain", @language=nil, @script=nil>, @type="title-main">, - #<RelatonBib::TypedTitleString:0x00007fea821ec8b8 - @title=#<RelatonBib::FormattedString:0x00007fea821ec818 @content="Geographic information", @format="text/plain", @language=nil, @script=nil>, + #<Relaton::Bib::Title:0x00007fea821ec8b8 + @title=#<Relaton::Bib::FormattedString:0x00007fea821ec818 @content="Geographic information", @format="text/plain", @language=nil, @script=nil>, @type="main">, - #<RelatonBib::TypedTitleString:0x00007fea821ec610 + #<Relaton::Bib::Title:0x00007fea821ec610 @title= - #<RelatonBib::FormattedString:0x00007fea821ec570 @content="Information géographique", @format="text/plain", @language=["fr"], @script=["Latn"]>, + #<Relaton::Bib::FormattedString:0x00007fea821ec570 @content="Information géographique", @format="text/plain", @language=["fr"], @script=["Latn"]>, @type=nil>]> item.title lang: "fr" -=> #<RelatonBib::TypedTitleStringCollection:0x00007fea8222d908 +=> #<Relaton::Bib::TitleCollection:0x00007fea8222d908 @array= - [#<RelatonBib::TypedTitleString:0x00007fea821ec610 - @title=#<RelatonBib::FormattedString:0x00007fea821ec570 @content="Information géographique", @format="text/plain", @language=["fr"], @script=["Latn"]>, + [#<Relaton::Bib::Title:0x00007fea821ec610 + @title=#<Relaton::Bib::FormattedString:0x00007fea821ec570 @content="Information géographique", @format="text/plain", @language=["fr"], @script=["Latn"]>, @type=nil>]> ---- @@ -78,12 +89,12 @@ item.title lang: "fr" [source,ruby] ---- item.abstract -=> [#<RelatonBib::FormattedString:0x00007fea82236828 +=> [#<Relaton::Bib::FormattedString:0x00007fea82236828 @content="<p>ISO 19115-1:2014 defines the schema required for ...</p>", @format="text/html", @language=["en"], @script=["Latn"]>, - #<RelatonBib::FormattedString:0x00007fea82236670 + #<Relaton::Bib::FormattedString:0x00007fea82236670 @content="L'ISO 19115-1:2014 définit le schéma requis pour ...", @format="text/plain", @language=["fr"], @@ -191,8 +202,8 @@ hash = YAML.load_file 'spec/examples/bib_item.yml' => {"id"=>"ISOTC211" ... -RelatonBib::BibliographicItem.from_hash hash -=> #<RelatonBib::BibliographicItem:0x007ff1524f8c88 +Relaton::Bib::Item.from_hash hash +=> #<Relaton::Bib::Item:0x007ff1524f8c88 ... ---- @@ -203,8 +214,8 @@ RelatonBib::BibliographicItem.from_hash hash bibxml = File.read "spec/examples/rfc.xml" => <reference anchor=... -RelatonBib::BibXMLParser.parse bibxml -=> #<RelatonBib::BibliographicItem:0x00007f9d0c75b268 +Relaton::Bib::BibXMLParser.parse bibxml +=> #<Relaton::Bib::Item:0x00007f9d0c75b268 ... ---- @@ -226,9 +237,9 @@ item.to_hash [source,ruby] ---- -RelatonBib::BibtexParser.from_bibtex File.read('spec/examples/techreport.bib') +Relaton::Bib::BibtexParser.from_bibtex File.read('spec/examples/techreport.bib') => {"ISOTC211"=> - #<RelatonBib::BibliographicItem:0x007fedee0a2ab0 + #<Relaton::Bib::Item:0x007fedee0a2ab0 ... ---- diff --git a/bin/console b/bin/console index 4db53c8..809a174 100755 --- a/bin/console +++ b/bin/console @@ -1,7 +1,7 @@ #!/usr/bin/env ruby require "bundler/setup" -require "relaton_bib" +require "relaton/bib" # You can add fixtures and/or initialization code here to make experimenting # with your gem easier. You can also use a different console, if you like. diff --git a/grammars/basicdoc.rng b/grammars/basicdoc.rng index 5a96d4a..08b0241 100644 --- a/grammars/basicdoc.rng +++ b/grammars/basicdoc.rng @@ -1,18 +1,28 @@ <?xml version="1.0" encoding="UTF-8"?> -<grammar xmlns="http://relaxng.org/ns/structure/1.0" datatypeLibrary="http://www.w3.org/2001/XMLSchema-datatypes"> +<grammar xmlns:a="http://relaxng.org/ns/compatibility/annotations/1.0" xmlns="http://relaxng.org/ns/structure/1.0" datatypeLibrary="http://www.w3.org/2001/XMLSchema-datatypes"> <define name="document"> + <a:documentation>Document</a:documentation> <element name="document"> <optional> - <attribute name="identifier"/> + <attribute name="identifier"> + <a:documentation>A globally unique identifier for the document in an agreed identifier schema. The identifier is to be used for tracking interactions with the document without depending on formal document registries; it would be exemplified by a GUID, rather than a document registry identifier such as "`ISO 639`", which belongs to `bibdata`</a:documentation> + </attribute> </optional> - <ref name="bibdata"/> - <ref name="sections"/> + <ref name="bibdata"> + <a:documentation>A bibliographic description, capturing bibliographic metadata about the document itself, including authors, title, and date of production</a:documentation> + </ref> + <ref name="sections"> + <a:documentation>Hierarchically arranged units of textual content within the document</a:documentation> + </ref> <zeroOrMore> - <ref name="references"/> + <ref name="references"> + <a:documentation>Bibliographic content</a:documentation> + </ref> </zeroOrMore> </element> </define> <define name="bibdata"> + <a:documentation>Bibliographic description of a document, used as metadata, expressed in the Relaton model</a:documentation> <element name="bibdata"> <ref name="BibData"/> </element> @@ -25,51 +35,71 @@ </element> </define> <define name="section"> + <a:documentation>Section: groups of blocks within text, which can also contain other sections</a:documentation> <element name="section"> <ref name="Basic-Section"/> <zeroOrMore> - <ref name="section"/> + <ref name="section"> + <a:documentation>Sections contained within the current section. The relation is recursive, +so the hierarchical arrangement of sections can be arbitrarily deep</a:documentation> + </ref> </zeroOrMore> </element> </define> + <define name="LanguageType"> + <a:documentation>Two-letter language code taken from ISO 639, indicating the language in which the content is written</a:documentation> + <text/> + </define> + <define name="ScriptType"> + <a:documentation>Four-letter script code taken from ISO 15924, indicating the script in which the content is written</a:documentation> + <text/> + </define> + <define name="LocaleType"> + <a:documentation>(Two-letter) Country and country subdivisions identifier taken from ISO 3166, indicating the locale in which the content is written</a:documentation> + <text/> + </define> <define name="Basic-Section"> + <a:documentation>Group of blocks within text, which is a leaf node in the hierarchical organisation of text (does not contain any sections of its own)</a:documentation> + <ref name="Basic-Section-Attributes"/> <optional> - <attribute name="id"> - <data type="ID"/> - </attribute> - </optional> - <optional> - <attribute name="language"/> - </optional> - <optional> - <attribute name="script"/> - </optional> - <optional> - <ref name="section-title"/> + <ref name="section-title"> + <a:documentation>Title of the section</a:documentation> + </ref> </optional> <zeroOrMore> - <ref name="BasicBlock"/> + <ref name="BasicBlock"> + <a:documentation>Blocks, containing the textual content of the section +(but excluding subsections, which are only present in Hierarchical Sections)</a:documentation> + </ref> </zeroOrMore> </define> + <define name="Basic-Section-Attributes"> + <ref name="OptionalId"/> + <ref name="LocalizedStringAttributes"/> + </define> <define name="references"> + <a:documentation>Sections containing zero or more bibliographical items (as described in Relaton), along with any prefatory text</a:documentation> <element name="references"> + <ref name="OptionalId"/> <optional> - <attribute name="id"> - <data type="ID"/> - </attribute> - </optional> - <optional> - <ref name="section-title"/> + <ref name="section-title"> + <a:documentation>Title of section</a:documentation> + </ref> </optional> <zeroOrMore> - <ref name="BasicBlock"/> + <ref name="BasicBlock"> + <a:documentation>Prefatory text</a:documentation> + </ref> </zeroOrMore> <zeroOrMore> - <ref name="bibitem"/> + <ref name="bibitem"> + <a:documentation>Bibliographical items included in the References section</a:documentation> + </ref> </zeroOrMore> </element> </define> <define name="section-title"> + <a:documentation>Title of a section</a:documentation> <element name="title"> <zeroOrMore> <ref name="TextElement"/> @@ -77,6 +107,7 @@ </element> </define> <define name="BasicBlock"> + <a:documentation>Block of textual content</a:documentation> <choice> <ref name="paragraph-with-footnote"/> <ref name="table"/> @@ -98,18 +129,39 @@ <ref name="amend"/> </choice> </define> + <define name="BasicBlockNoId"> + <a:documentation>Block of textual content: optional ID attributes (for use in Relaton, metadata)</a:documentation> + <choice> + <ref name="paragraph-with-footnote-no-id"/> + <ref name="table-no-id"/> + <ref name="formula-no-id"/> + <ref name="admonition-no-id"/> + <ref name="ol-no-id"/> + <ref name="ul-no-id"/> + <ref name="dl-no-id"/> + <ref name="figure-no-id"/> + <ref name="quote-no-id"/> + <ref name="sourcecode-no-id"/> + <ref name="example-no-id"/> + <ref name="review"/> + <ref name="pre-no-id"/> + <ref name="note-no-id"/> + <ref name="pagebreak"/> + <ref name="hr"/> + <ref name="bookmark"/> + <ref name="amend"/> + </choice> + </define> <define name="amend"> + <a:documentation>Block describing a change in a document, intended for human readers</a:documentation> <element name="amend"> <ref name="AmendType"/> </element> </define> <define name="AmendType"> - <optional> - <attribute name="id"> - <data type="ID"/> - </attribute> - </optional> + <ref name="OptionalId"/> <attribute name="change"> + <a:documentation>The type of change described in this block</a:documentation> <choice> <value>add</value> <value>modify</value> @@ -118,16 +170,26 @@ </choice> </attribute> <optional> - <attribute name="path"/> + <attribute name="path"> + <a:documentation>The span within location where the change applies to, +if location defines a container larger than the scope of the change</a:documentation> + </attribute> </optional> <optional> - <attribute name="path_end"/> + <attribute name="path_end"> + <a:documentation>The end of the span within location where the change applies to, +if location defines a container larger than the scope of the change. +Applicable to modify and delete</a:documentation> + </attribute> </optional> <optional> - <attribute name="title"/> + <attribute name="title"> + <a:documentation>Optional caption of this block</a:documentation> + </attribute> </optional> <optional> <element name="location"> + <a:documentation>The location(s) in the original document which have undergone the change described in this block</a:documentation> <zeroOrMore> <choice> <ref name="locality"/> @@ -138,6 +200,7 @@ </optional> <optional> <element name="description"> + <a:documentation>Description of the change described in this block</a:documentation> <zeroOrMore> <ref name="BasicBlock"/> </zeroOrMore> @@ -145,27 +208,33 @@ </optional> <optional> <element name="newcontent"> - <optional> - <attribute name="id"> - <data type="ID"/> - </attribute> - </optional> + <a:documentation>New content to be added to the document; applicable to add and modify</a:documentation> + <ref name="OptionalId"/> <zeroOrMore> <ref name="BasicBlock"/> </zeroOrMore> </element> </optional> <zeroOrMore> - <ref name="classification"/> + <ref name="classification"> + <a:documentation>Classification of the change</a:documentation> + </ref> </zeroOrMore> <zeroOrMore> - <ref name="contributor"/> + <ref name="contributor"> + <a:documentation>Contributor responsible for the change</a:documentation> + </ref> </zeroOrMore> </define> <define name="classification"> + <a:documentation>Key-value classification of an entity</a:documentation> <element name="classification"> - <ref name="classification_tag"/> - <ref name="classification_value"/> + <ref name="classification_tag"> + <a:documentation>Key for the classification</a:documentation> + </ref> + <ref name="classification_value"> + <a:documentation>Value for the classification</a:documentation> + </ref> </element> </define> <define name="classification_tag"> @@ -179,11 +248,18 @@ </element> </define> <define name="paragraph"> + <a:documentation>Default block of textual content. +Unlike the case for other document models, paragraphs _cannot_ +contain other blocks, such as lists, tables, or figures: they are modelled as a basic building block of text +Does not contain foonotes. While most paragraphs in a document can contain footnotes (paragraph-with-footnote), +the distinction is necessary, as footnotes are not appropriate for all instances of paragraph content +in a document (e.g. sourcecode annotations)</a:documentation> <element name="p"> <ref name="ParagraphType"/> </element> </define> <define name="Alignments"> + <a:documentation>The alignment of the paragraph against the margins of the document</a:documentation> <choice> <value>left</value> <value>right</value> @@ -191,133 +267,298 @@ <value>justified</value> </choice> </define> - <define name="ParagraphType"> + <define name="RequiredId"> + <a:documentation>Mandatory anchor of element, to be used for cross-references within the document</a:documentation> <attribute name="id"> <data type="ID"/> </attribute> + </define> + <define name="OptionalId"> + <a:documentation>Optional anchor of element</a:documentation> + <optional> + <attribute name="id"> + <data type="ID"/> + </attribute> + </optional> + </define> + <define name="ParagraphAttributes"> <optional> <attribute name="align"> + <a:documentation>The alignment of the paragraph against the margins of the document</a:documentation> <ref name="Alignments"/> </attribute> </optional> + </define> + <define name="ParagraphType"> + <ref name="RequiredId"/> + <ref name="ParagraphAttributes"/> + <ref name="ParagraphBody"/> + </define> + <define name="ParagraphBody"> + <a:documentation>Inline elements constituting the content of the paragraph, excluding footnotes</a:documentation> <zeroOrMore> - <ref name="TextElement"/> + <ref name="TextElement"> + <a:documentation>Inline elements constituting the content of the paragraph</a:documentation> + </ref> </zeroOrMore> <zeroOrMore> - <ref name="note"/> + <ref name="note"> + <a:documentation>Notes whose scope is the current block</a:documentation> + </ref> + </zeroOrMore> + </define> + <define name="ParagraphFnBody"> + <a:documentation>Inline elements constituting the content of the paragraph, including footnotes</a:documentation> + <zeroOrMore> + <choice> + <ref name="TextElement"> + <a:documentation>Inline elements constituting the content of the paragraph</a:documentation> + </ref> + <ref name="fn"> + <a:documentation>Footnotes interspersed with paragraph content</a:documentation> + </ref> + </choice> + </zeroOrMore> + <zeroOrMore> + <ref name="note"> + <a:documentation>Notes whose scope is the current block</a:documentation> + </ref> </zeroOrMore> </define> + <define name="paragraph-no-id"> + <a:documentation>Paragraph containing no footnotes: optional ID attributes (for use in Relaton, metadata) </a:documentation> + <element name="p"> + <ref name="OptionalId"/> + <ref name="ParagraphAttributes"/> + <ref name="ParagraphBody"/> + </element> + </define> <define name="paragraph-with-footnote"> + <a:documentation>A paragraph which may contain footnotes.</a:documentation> <element name="p"> - <attribute name="id"> - <data type="ID"/> - </attribute> - <optional> - <attribute name="align"> - <ref name="Alignments"/> - </attribute> - </optional> - <zeroOrMore> - <choice> - <ref name="TextElement"/> - <ref name="fn"/> - </choice> - </zeroOrMore> - <zeroOrMore> - <ref name="note"/> - </zeroOrMore> + <ref name="RequiredId"/> + <ref name="ParagraphAttributes"/> + <ref name="ParagraphFnBody"/> + </element> + </define> + <define name="paragraph-with-footnote-no-id"> + <a:documentation>A paragraph which may contain footnotes: optional ID attributes (for use in Relaton, metadata)</a:documentation> + <element name="p"> + <ref name="OptionalId"/> + <ref name="ParagraphAttributes"/> + <ref name="ParagraphFnBody"/> </element> </define> <define name="note"> + <a:documentation>Note block</a:documentation> <element name="note"> - <attribute name="id"> - <data type="ID"/> - </attribute> - <oneOrMore> - <ref name="paragraph"/> - </oneOrMore> + <ref name="RequiredId"/> + <ref name="NoteAttributes"/> + <ref name="NoteBody"/> + </element> + </define> + <define name="note-no-id"> + <a:documentation>Note block: optional ID attributes (for use in Relaton, metadata)</a:documentation> + <element name="note"> + <ref name="OptionalId"/> + <ref name="NoteAttributes"/> + <ref name="NoteNoIdBody"/> </element> </define> + <define name="NoteAttributes"> + <ref name="NumberingAttributes"/> + </define> + <define name="NoteBody"> + <oneOrMore> + <ref name="paragraph"/> + </oneOrMore> + </define> + <define name="NoteNoIdBody"> + <oneOrMore> + <ref name="paragraph-no-id"/> + </oneOrMore> + </define> <define name="review"> + <a:documentation>Block intended to capture reviewer comments about some text in the document</a:documentation> <element name="review"> - <attribute name="id"> - <data type="ID"/> + <ref name="RequiredId"/> + <attribute name="reviewer"> + <a:documentation>The party who has offered the comment</a:documentation> </attribute> - <attribute name="reviewer"/> <optional> - <attribute name="type"/> + <attribute name="type"> + <a:documentation>The type of reviewer comment</a:documentation> + </attribute> </optional> <optional> <attribute name="date"> + <a:documentation>The date when the comment was made</a:documentation> <data type="dateTime"/> </attribute> </optional> <optional> <attribute name="from"> + <a:documentation>Identifier for the start of the text or point in the text to which the comment applies. +If not provided, the comment applies in the vicinity of the place it has been inserted into the text</a:documentation> <data type="IDREF"/> </attribute> </optional> <optional> <attribute name="to"> + <a:documentation>Identifier for the end of the text to which the comment applies</a:documentation> <data type="IDREF"/> </attribute> </optional> <oneOrMore> - <ref name="paragraph"/> + <ref name="paragraph"> + <a:documentation>Reviewer comments content</a:documentation> + </ref> </oneOrMore> </element> </define> + <define name="NumberingAttributes"> + <optional> + <attribute name="unnumbered"> + <a:documentation>Do not number this block in rendering</a:documentation> + <data type="boolean"/> + </attribute> + </optional> + <optional> + <attribute name="subsequence"> + <a:documentation>Define a subsequence for numbering of this block; e.g. if this block would be numbered +as 7, but it has a subsequence value of XYZ, this block, and all consecutive blocks +of the same class and with the same subsequence value, will be numbered consecutively +with the same number and in a subsequence: 7a, 7b, 7c etc</a:documentation> + </attribute> + </optional> + </define> <define name="formula"> + <a:documentation>Block containing a mathematical expression or other formulas</a:documentation> <element name="formula"> - <attribute name="id"> - <data type="ID"/> - </attribute> - <optional> - <attribute name="unnumbered"> - <data type="boolean"/> - </attribute> - </optional> - <optional> - <attribute name="subsequence"/> - </optional> - <optional> - <attribute name="inequality"> - <data type="boolean"/> - </attribute> - </optional> - <ref name="stem"/> - <optional> - <ref name="dl"/> - </optional> - <zeroOrMore> - <ref name="note"/> - </zeroOrMore> + <ref name="RequiredId"/> + <ref name="FormulaAttributes"/> + <ref name="FormulaBody"/> + </element> + </define> + <define name="formula-no-id"> + <a:documentation>Block containing a mathematical expression or other formulas: optional ID attributes (for use in Relaton, metadata)</a:documentation> + <element name="formula"> + <ref name="OptionalId"/> + <ref name="FormulaAttributes"/> + <ref name="FormulaNoIdBody"/> </element> </define> + <define name="FormulaAttributes"> + <ref name="NumberingAttributes"/> + <optional> + <attribute name="inequality"> + <a:documentation>Indication that the formula is to be labelled as an Inequality, if inequalities are differentiated from equations</a:documentation> + <data type="boolean"/> + </attribute> + </optional> + </define> + <define name="FormulaBody"> + <ref name="stem"> + <a:documentation>The content of the formula, as a mathematical expression</a:documentation> + </ref> + <optional> + <ref name="dl"> + <a:documentation>A definitions list defining any symbols used in the formula</a:documentation> + </ref> + </optional> + <zeroOrMore> + <ref name="note"> + <a:documentation>Notes whose scope is the current block</a:documentation> + </ref> + </zeroOrMore> + </define> + <define name="FormulaNoIdBody"> + <ref name="stem"> + <a:documentation>The content of the formula, as a mathematical expression</a:documentation> + </ref> + <optional> + <ref name="dl-no-id"> + <a:documentation>A definitions list defining any symbols used in the formula</a:documentation> + </ref> + </optional> + <zeroOrMore> + <ref name="note-no-id"> + <a:documentation>Notes whose scope is the current block</a:documentation> + </ref> + </zeroOrMore> + </define> <define name="quote"> + <a:documentation>Block quotation, containing extensive textual content originally authored outside of the current document</a:documentation> <element name="quote"> - <attribute name="id"> - <data type="ID"/> - </attribute> - <optional> - <attribute name="alignment"> - <ref name="Alignments"/> - </attribute> - </optional> - <optional> - <ref name="quote-source"/> - </optional> - <optional> - <ref name="quote-author"/> - </optional> - <oneOrMore> - <ref name="paragraph-with-footnote"/> - </oneOrMore> - <zeroOrMore> - <ref name="note"/> - </zeroOrMore> + <ref name="RequiredId"/> + <ref name="QuoteAttributes"/> + <ref name="QuoteBody"/> + </element> + </define> + <define name="quote-no-id"> + <a:documentation>Block quotation: optional ID attributes (for use in Relaton, metadata)</a:documentation> + <element name="quote"> + <ref name="OptionalId"/> + <ref name="QuoteAttributes"/> + <ref name="QuoteNoIdBody"/> </element> </define> + <define name="QuoteAttributes"> + <optional> + <attribute name="alignment"> + <a:documentation>The alignment of the quote against the margins of the document</a:documentation> + <ref name="Alignments"/> + </attribute> + </optional> + </define> + <define name="QuoteBody"> + <optional> + <ref name="quote-source"> + <a:documentation>Bibliographic citation for the quotation</a:documentation> + </ref> + </optional> + <optional> + <ref name="quote-author"> + <a:documentation>Author of the quotation. The `author` attribute of the quotation is redundant with `source`, +since it restates information about the author that should be recoverable from the `source` citation. +It is included for convenience, in case processing the citation to extract the author is prohibitive for rendering tools</a:documentation> + </ref> + </optional> + <oneOrMore> + <ref name="paragraph-with-footnote"> + <a:documentation>Content of quote</a:documentation> + </ref> + </oneOrMore> + <zeroOrMore> + <ref name="note"> + <a:documentation>Notes whose scope is the current block</a:documentation> + </ref> + </zeroOrMore> + </define> + <define name="QuoteNoIdBody"> + <optional> + <ref name="quote-source"> + <a:documentation>Bibliographic citation for the quotation</a:documentation> + </ref> + </optional> + <optional> + <ref name="quote-author"> + <a:documentation>Author of the quotation. The `author` attribute of the quotation is redundant with `source`, +since it restates information about the author that should be recoverable from the `source` citation. +It is included for convenience, in case processing the citation to extract the author is prohibitive for rendering tools</a:documentation> + </ref> + </optional> + <oneOrMore> + <ref name="paragraph-with-footnote-no-id"> + <a:documentation>Content of quote</a:documentation> + </ref> + </oneOrMore> + <zeroOrMore> + <ref name="note-no-id"> + <a:documentation>Notes whose scope is the current block</a:documentation> + </ref> + </zeroOrMore> + </define> <define name="quote-source"> <element name="source"> <ref name="erefType"/> @@ -329,110 +570,245 @@ </element> </define> <define name="sourcecode"> + <a:documentation>Block containing computer code or comparable text</a:documentation> <element name="sourcecode"> - <attribute name="id"> - <data type="ID"/> - </attribute> - <optional> - <attribute name="unnumbered"> - <data type="boolean"/> - </attribute> - </optional> - <optional> - <attribute name="subsequence"/> - </optional> - <optional> - <attribute name="lang"/> - </optional> - <optional> - <ref name="tname"/> - </optional> - <oneOrMore> - <choice> - <text/> - <ref name="callout"/> - </choice> - </oneOrMore> - <zeroOrMore> - <ref name="annotation"/> - </zeroOrMore> - <zeroOrMore> - <ref name="note"/> - </zeroOrMore> + <ref name="RequiredId"/> + <ref name="SourceAttributes"/> + <ref name="SourceBody"/> + </element> + </define> + <define name="sourcecode-no-id"> + <a:documentation>Block containing computer code or comparable text: optional ID attributes (for use in Relaton, metadata)</a:documentation> + <element name="sourcecode"> + <ref name="OptionalId"/> + <ref name="SourceAttributes"/> + <ref name="SourceNoIdBody"/> </element> </define> + <define name="SourceAttributes"> + <ref name="NumberingAttributes"/> + <optional> + <attribute name="lang"> + <a:documentation>The computer language or other notational convention that the source code is expressed in</a:documentation> + </attribute> + </optional> + </define> + <define name="SourceBody"> + <optional> + <ref name="tname"> + <a:documentation>The caption of the block</a:documentation> + </ref> + </optional> + <oneOrMore> + <choice> + <text> + <a:documentation>The computer code or other such text presented in the block, as a single unformatted string. +(The string should be treated as pre-formatted text, with whitespace treated as significant)</a:documentation> + </text> + <ref name="callout"> + <a:documentation>Zero or more cross-references; these are intended to be embedded within the content string, and link to annotations</a:documentation> + </ref> + </choice> + </oneOrMore> + <zeroOrMore> + <ref name="annotation"> + <a:documentation>Annotations to the source code; each annotation consists of zero or more paragraphs, +and is intended to be referenced by a callout within the source code</a:documentation> + </ref> + </zeroOrMore> + <zeroOrMore> + <ref name="note"> + <a:documentation>Notes whose scope is the current block</a:documentation> + </ref> + </zeroOrMore> + </define> + <define name="SourceNoIdBody"> + <optional> + <ref name="tname"> + <a:documentation>The caption of the block</a:documentation> + </ref> + </optional> + <oneOrMore> + <choice> + <text> + <a:documentation>The computer code or other such text presented in the block, as a single unformatted string. +(The string should be treated as pre-formatted text, with whitespace treated as significant)</a:documentation> + </text> + <ref name="callout"> + <a:documentation>Zero or more cross-references; these are intended to be embedded within the content string, and link to annotations</a:documentation> + </ref> + </choice> + </oneOrMore> + <zeroOrMore> + <ref name="annotation"> + <a:documentation>Annotations to the source code; each annotation consists of zero or more paragraphs, +and is intended to be referenced by a callout within the source code</a:documentation> + </ref> + </zeroOrMore> + <zeroOrMore> + <ref name="note-no-id"> + <a:documentation>Notes whose scope is the current block</a:documentation> + </ref> + </zeroOrMore> + </define> <define name="pre"> + <a:documentation>Pre-formatted block. Wrapper for text to be rendered with fixed-width typeface, and preserving spaces including line breaks. +They are intended for a restricted number of functions, most typically ASCII Art (which is still in prominent use in some +standards documents), and computer output. In most cases, sourcecode blocks are more appropriate in markup, +as it is more clearly motivated semantically</a:documentation> <element name="pre"> - <attribute name="id"> - <data type="ID"/> - </attribute> - <optional> - <attribute name="alt"/> - </optional> - <optional> - <ref name="tname"/> - </optional> - <text/> - <zeroOrMore> - <ref name="note"/> - </zeroOrMore> + <ref name="RequiredId"/> + <ref name="PreAttributes"/> + <ref name="PreBody"/> + </element> + </define> + <define name="pre-no-id"> + <a:documentation>Pre-formatted block: optional ID attributes (for use in Relaton, metadata)</a:documentation> + <element name="pre"> + <ref name="OptionalId"/> + <ref name="PreAttributes"/> + <ref name="PreNoIdBody"/> </element> </define> + <define name="PreAttributes"> + <optional> + <attribute name="alt"> + <a:documentation>Accessible description of the preformatted text</a:documentation> + </attribute> + </optional> + </define> + <define name="PreBody"> + <optional> + <ref name="tname"> + <a:documentation>The caption of the block</a:documentation> + </ref> + </optional> + <text> + <a:documentation>The pre-formatted text presented in the block, as a single unformatted string. (Whitespace is treated as significant)</a:documentation> + </text> + <zeroOrMore> + <ref name="note"> + <a:documentation>Notes whose scope is the current block</a:documentation> + </ref> + </zeroOrMore> + </define> + <define name="PreNoIdBody"> + <optional> + <ref name="tname"> + <a:documentation>The caption of the block</a:documentation> + </ref> + </optional> + <text> + <a:documentation>The pre-formatted text presented in the block, as a single unformatted string. (Whitespace is treated as significant)</a:documentation> + </text> + <zeroOrMore> + <ref name="note-no-id"> + <a:documentation>Notes whose scope is the current block</a:documentation> + </ref> + </zeroOrMore> + </define> <define name="table"> + <a:documentation>Tabular arrangement of text</a:documentation> <element name="table"> - <attribute name="id"> - <data type="ID"/> - </attribute> - <optional> - <attribute name="unnumbered"> - <data type="boolean"/> - </attribute> - </optional> - <optional> - <attribute name="subsequence"/> - </optional> - <optional> - <attribute name="alt"/> - </optional> - <optional> - <attribute name="summary"/> - </optional> - <optional> - <attribute name="uri"> - <data type="anyURI"/> - </attribute> - </optional> - <optional> - <ref name="tname"/> - </optional> - <optional> - <ref name="thead"/> - </optional> - <ref name="tbody"/> - <optional> - <ref name="tfoot"/> - </optional> - <zeroOrMore> - <ref name="table-note"/> - </zeroOrMore> - <optional> - <ref name="dl"/> - </optional> + <ref name="RequiredId"/> + <ref name="TableAttributes"/> + <ref name="TableBody"/> </element> </define> + <define name="table-no-id"> + <a:documentation>Tabular arrangement of text: optional ID attributes recursively (for use in Relaton, metadata)</a:documentation> + <element name="table"> + <ref name="OptionalId"/> + <ref name="TableAttributes"/> + <ref name="TableNoIdBody"/> + </element> + </define> + <define name="TableAttributes"> + <ref name="NumberingAttributes"/> + <optional> + <attribute name="alt"> + <a:documentation>Accessible description of the tabular text, in case the table cannot be rendered accessibly (HTML 5)</a:documentation> + </attribute> + </optional> + <optional> + <attribute name="summary"> + <a:documentation>Alternative more extensive summary of table to be provided for accessibility purposes, +in case the table cannot be rendered accessibly (HTML 5)</a:documentation> + </attribute> + </optional> + <optional> + <attribute name="uri"> + <a:documentation>Online location of content of table (in case the table is available as a separate external document) (HTML 5)</a:documentation> + <data type="anyURI"/> + </attribute> + </optional> + </define> + <define name="TableBody"> + <a:documentation>Elements of table</a:documentation> + <optional> + <ref name="tname"> + <a:documentation>Caption for the table</a:documentation> + </ref> + </optional> + <optional> + <ref name="thead"> + <a:documentation>Table rows constituting the table header</a:documentation> + </ref> + </optional> + <ref name="tbody"> + <a:documentation>Table rows constituting the table body</a:documentation> + </ref> + <optional> + <ref name="tfoot"> + <a:documentation>Table rows constituting the table footer</a:documentation> + </ref> + </optional> + <optional> + <ref name="dl"> + <a:documentation>Definitions list defining any symbols used in the table</a:documentation> + </ref> + </optional> + <zeroOrMore> + <ref name="table-note"> + <a:documentation>Notes specific to this block</a:documentation> + </ref> + </zeroOrMore> + </define> + <define name="TableNoIdBody"> + <a:documentation>Elements of table: optional ID attributes recursively (for use in Relaton, metadata)</a:documentation> + <optional> + <ref name="tname"> + <a:documentation>Caption for the table</a:documentation> + </ref> + </optional> + <optional> + <ref name="thead-no-id"> + <a:documentation>Table rows constituting the table header</a:documentation> + </ref> + </optional> + <ref name="tbody-no-id"> + <a:documentation>Table rows constituting the table body</a:documentation> + </ref> + <optional> + <ref name="tfoot-no-id"> + <a:documentation>Table rows constituting the table footer</a:documentation> + </ref> + </optional> + <optional> + <ref name="dl-no-id"> + <a:documentation>Definitions list defining any symbols used in the table</a:documentation> + </ref> + </optional> + <zeroOrMore> + <ref name="table-note-no-id"> + <a:documentation>Notes specific to this block</a:documentation> + </ref> + </zeroOrMore> + </define> <define name="tname"> <element name="name"> <oneOrMore> - <choice> - <ref name="PureTextElement"/> - <ref name="eref"/> - <ref name="stem"/> - <ref name="keyword"/> - <ref name="xref"/> - <ref name="hyperlink"/> - <ref name="index"/> - <ref name="index-xref"/> - </choice> + <ref name="NestedTextElement"/> </oneOrMore> </element> </define> @@ -441,11 +817,21 @@ <ref name="tr"/> </element> </define> + <define name="thead-no-id"> + <element name="thead"> + <ref name="tr-no-id"/> + </element> + </define> <define name="tfoot"> <element name="tfoot"> <ref name="tr"/> </element> </define> + <define name="tfoot-no-id"> + <element name="tfoot"> + <ref name="tr-no-id"/> + </element> + </define> <define name="tbody"> <element name="tbody"> <oneOrMore> @@ -453,209 +839,409 @@ </oneOrMore> </element> </define> + <define name="tbody-no-id"> + <element name="tbody"> + <oneOrMore> + <ref name="tr-no-id"/> + </oneOrMore> + </element> + </define> <define name="table-note"> <element name="note"> <ref name="paragraph"/> </element> </define> + <define name="table-note-no-id"> + <element name="note"> + <ref name="paragraph-no-id"/> + </element> + </define> <define name="tr"> + <a:documentation>Sequence of cells to be displayed as a row in a table</a:documentation> + <element name="tr"> + <oneOrMore> + <choice> + <ref name="td"> + <a:documentation>Data cells in a table row</a:documentation> + </ref> + <ref name="th"> + <a:documentation>Header cells in a table row</a:documentation> + </ref> + </choice> + </oneOrMore> + </element> + </define> + <define name="tr-no-id"> + <a:documentation>Sequence of cells to be displayed as a row in a table: optional ID attributes recursively (for use in Relaton, metadata)</a:documentation> <element name="tr"> <oneOrMore> <choice> - <ref name="td"/> - <ref name="th"/> + <ref name="td-no-id"/> + <ref name="th-no-id"/> </choice> </oneOrMore> </element> </define> <define name="td"> + <a:documentation>Textual content constituting a basic building block of a table: data cell</a:documentation> <element name="td"> - <optional> - <attribute name="colspan"/> - </optional> - <optional> - <attribute name="rowspan"/> - </optional> - <optional> - <attribute name="align"> - <choice> - <value>left</value> - <value>right</value> - <value>center</value> - </choice> - </attribute> - </optional> - <optional> - <attribute name="valign"> - <choice> - <value>top</value> - <value>middle</value> - <value>bottom</value> - <value>baseline</value> - </choice> - </attribute> - </optional> - <choice> - <zeroOrMore> - <ref name="TextElement"/> - </zeroOrMore> - <oneOrMore> - <ref name="paragraph-with-footnote"/> - </oneOrMore> - </choice> + <ref name="TdAttributes"/> + <ref name="TdBody"/> </element> </define> - <define name="th"> - <element name="th"> - <optional> - <attribute name="colspan"/> - </optional> - <optional> - <attribute name="rowspan"/> - </optional> - <optional> - <attribute name="align"> - <choice> - <value>left</value> - <value>right</value> - <value>center</value> - </choice> - </attribute> - </optional> - <optional> - <attribute name="valign"> - <choice> - <value>top</value> - <value>middle</value> - <value>bottom</value> - <value>baseline</value> - </choice> - </attribute> - </optional> - <choice> - <zeroOrMore> - <ref name="TextElement"/> - </zeroOrMore> - <oneOrMore> - <ref name="paragraph-with-footnote"/> - </oneOrMore> - </choice> + <define name="td-no-id"> + <a:documentation>Data cell: optional ID attributes recursively (for use in Relaton, metadata)</a:documentation> + <element name="td"> + <ref name="TdAttributes"/> + <ref name="TdNoIdBody"/> </element> </define> - <define name="example"> - <element name="example"> - <attribute name="id"> - <data type="ID"/> + <define name="TdAttributes"> + <optional> + <attribute name="colspan"> + <a:documentation>Number of columns in the underlying table grid which the cell spans</a:documentation> </attribute> - <optional> - <attribute name="unnumbered"> - <data type="boolean"/> - </attribute> - </optional> - <optional> - <attribute name="subsequence"/> - </optional> - <optional> - <ref name="tname"/> - </optional> - <oneOrMore> + </optional> + <optional> + <attribute name="rowspan"> + <a:documentation>Number of rows in the underlying table grid which the cell spans</a:documentation> + </attribute> + </optional> + <optional> + <attribute name="align"> + <a:documentation>Horizontal textual alignment of the cell against the underlying table grid</a:documentation> <choice> - <ref name="formula"/> - <ref name="ul"/> - <ref name="ol"/> - <ref name="dl"/> - <ref name="quote"/> - <ref name="sourcecode"/> - <ref name="paragraph-with-footnote"/> + <value>left</value> + <value>right</value> + <value>center</value> </choice> + </attribute> + </optional> + <optional> + <attribute name="valign"> + <a:documentation>Vertical alignment of the cell against the underlying table grid</a:documentation> + <choice> + <value>top</value> + <value>middle</value> + <value>bottom</value> + <value>baseline</value> + </choice> + </attribute> + </optional> + </define> + <define name="TdBody"> + <choice> + <zeroOrMore> + <group> + <a:documentation>Table cell is a block</a:documentation> + <ref name="TextElement"/> + </group> + </zeroOrMore> + <oneOrMore> + <ref name="paragraph-with-footnote"> + <a:documentation>Table cell contains a block</a:documentation> + </ref> </oneOrMore> + </choice> + </define> + <define name="TdNoIdBody"> + <choice> <zeroOrMore> - <ref name="note"/> + <group> + <a:documentation>Table cell is a block</a:documentation> + <ref name="TextElement"/> + </group> </zeroOrMore> + <oneOrMore> + <ref name="paragraph-with-footnote-no-id"> + <a:documentation>Table cell contains a block</a:documentation> + </ref> + </oneOrMore> + </choice> + </define> + <define name="th"> + <a:documentation>Textual content constituting a basic building block of a table, treated as a header: header cell</a:documentation> + <element name="th"> + <ref name="ThAttributes"/> + <ref name="ThBody"/> + </element> + </define> + <define name="th-no-id"> + <a:documentation>Header cell: optional ID attributes recursively (for use in Relaton, metadata)</a:documentation> + <element name="th"> + <ref name="ThAttributes"/> + <ref name="ThNoIdBody"/> + </element> + </define> + <define name="ThAttributes"> + <ref name="TdAttributes"/> + </define> + <define name="ThBody"> + <ref name="TdBody"/> + </define> + <define name="ThNoIdBody"> + <ref name="TdNoIdBody"/> + </define> + <define name="example"> + <a:documentation>Block containing an example illustrating a claim made in the main flow of text</a:documentation> + <element name="example"> + <ref name="RequiredId"/> + <ref name="ExampleAttributes"/> + <ref name="ExampleBody"/> + </element> + </define> + <define name="example-no-id"> + <a:documentation>Example block: optional ID attributes recursively (for use in Relaton, metadata)</a:documentation> + <element name="example"> + <ref name="OptionalId"/> + <ref name="ExampleAttributes"/> + <ref name="ExampleNoIdBody"/> </element> </define> + <define name="ExampleAttributes"> + <ref name="NumberingAttributes"/> + </define> + <define name="ExampleBody"> + <optional> + <ref name="tname"> + <a:documentation>The caption of the example</a:documentation> + </ref> + </optional> + <oneOrMore> + <choice> + <a:documentation>Content of the example</a:documentation> + <ref name="formula"/> + <ref name="ul"/> + <ref name="ol"/> + <ref name="dl"/> + <ref name="quote"/> + <ref name="sourcecode"/> + <ref name="paragraph-with-footnote"/> + </choice> + </oneOrMore> + <zeroOrMore> + <ref name="note"> + <a:documentation>Notes whose scope is the current block</a:documentation> + </ref> + </zeroOrMore> + </define> + <define name="ExampleNoIdBody"> + <optional> + <ref name="tname"> + <a:documentation>The caption of the example</a:documentation> + </ref> + </optional> + <oneOrMore> + <choice> + <a:documentation>Content of the example</a:documentation> + <ref name="formula-no-id"/> + <ref name="ul-no-id"/> + <ref name="ol-no-id"/> + <ref name="dl-no-id"/> + <ref name="quote-no-id"/> + <ref name="sourcecode-no-id"/> + <ref name="paragraph-with-footnote-no-id"/> + </choice> + </oneOrMore> + <zeroOrMore> + <ref name="note-no-id"> + <a:documentation>Notes whose scope is the current block</a:documentation> + </ref> + </zeroOrMore> + </define> <define name="admonition"> + <a:documentation>A sidebar block outside of the main flow of text, conveying particular warnings or supplementary text to the reader</a:documentation> <element name="admonition"> - <attribute name="type"> - <ref name="AdmonitionType"/> + <ref name="RequiredId"/> + <ref name="AdmonitionAttributes"/> + <ref name="AdmonitionBody"/> + </element> + </define> + <define name="admonition-no-id"> + <a:documentation>A sidebar block outside of the main flow of text: optional ID attributes recursively (for use in Relaton, metadata)</a:documentation> + <element name="admonition"> + <ref name="OptionalId"/> + <ref name="AdmonitionAttributes"/> + <ref name="AdmonitionNoIdBody"/> + </element> + </define> + <define name="AdmonitionAttributes"> + <attribute name="type"> + <a:documentation>Subclass of admonition determining how it is to be rendered. +Distinct admonition types are often associated with distinct icons or rendering</a:documentation> + <ref name="AdmonitionType"/> + </attribute> + <optional> + <attribute name="class"> + <a:documentation>Subclass of admonition, allowing different runs of admonitions to be labelled +and auto-numbered differently, even if they are of the same type. +Typically is a subclass of an admonition type</a:documentation> </attribute> - <optional> - <attribute name="class"/> - </optional> - <attribute name="id"> - <data type="ID"/> + </optional> + <optional> + <attribute name="uri"> + <a:documentation>Location where the content of the admonition is accessible as an external document</a:documentation> + <data type="anyURI"/> </attribute> - <optional> - <attribute name="uri"> - <data type="anyURI"/> - </attribute> - </optional> - <optional> - <ref name="tname"/> - </optional> - <zeroOrMore> - <ref name="paragraph-with-footnote"/> - </zeroOrMore> - <zeroOrMore> - <ref name="note"/> - </zeroOrMore> - </element> + </optional> + </define> + <define name="AdmonitionBody"> + <optional> + <ref name="tname"> + <a:documentation>Caption of admonition</a:documentation> + </ref> + </optional> + <zeroOrMore> + <ref name="paragraph-with-footnote"> + <a:documentation>Admonition content</a:documentation> + </ref> + </zeroOrMore> + <zeroOrMore> + <ref name="note"> + <a:documentation>Notes whose scope is the current block</a:documentation> + </ref> + </zeroOrMore> + </define> + <define name="AdmonitionNoIdBody"> + <optional> + <ref name="tname"> + <a:documentation>Caption of admonition</a:documentation> + </ref> + </optional> + <zeroOrMore> + <ref name="paragraph-with-footnote-no-id"> + <a:documentation>Admonition content</a:documentation> + </ref> + </zeroOrMore> + <zeroOrMore> + <ref name="note-no-id"> + <a:documentation>Notes whose scope is the current block</a:documentation> + </ref> + </zeroOrMore> </define> <define name="AdmonitionType"> + <a:documentation>Subclass of admonition determining how it is to be rendered</a:documentation> <choice> <value>warning</value> + <a:documentation>Warning to reader, note of risk to be avoided</a:documentation> <value>note</value> + <a:documentation>Supplementary, explanatory information</a:documentation> <value>tip</value> + <a:documentation>Instructive information to assist in the fulfilment of tasks related to content</a:documentation> <value>important</value> + <a:documentation>Note to reader of something crucial to be borne in mind</a:documentation> <value>caution</value> + <a:documentation>Caution to reader, note of potential surprise or difficulty</a:documentation> </choice> </define> <define name="figure"> + <a:documentation>Block containing a figure: a visual rather than textual asset, possibly with accompanying text</a:documentation> <element name="figure"> - <attribute name="id"> - <data type="ID"/> + <ref name="RequiredId"/> + <ref name="FigureAttributes"/> + <ref name="FigureBody"/> + </element> + </define> + <define name="figure-no-id"> + <a:documentation>Block containing a figure: optional ID attributes recursively (for use in Relaton, metadata)</a:documentation> + <element name="figure"> + <ref name="OptionalId"/> + <ref name="FigureAttributes"/> + <ref name="FigureNoIdBody"/> + </element> + </define> + <define name="FigureAttributes"> + <ref name="NumberingAttributes"/> + <optional> + <attribute name="class"> + <a:documentation>The semantic category of the figure. This is to allow different classes of figure (e.g. _Plate_, _Chart_, _Diagram_) +to be auto-numbered and captioned differently</a:documentation> </attribute> - <optional> - <attribute name="unnumbered"> - <data type="boolean"/> - </attribute> - </optional> - <optional> - <attribute name="subsequence"/> - </optional> - <optional> - <attribute name="class"/> - </optional> - <optional> - <ref name="source"/> - </optional> - <optional> - <ref name="tname"/> - </optional> - <choice> - <ref name="image"/> - <ref name="video"/> - <ref name="audio"/> - <ref name="pre"/> - <oneOrMore> - <ref name="paragraph-with-footnote"/> - </oneOrMore> - <zeroOrMore> - <ref name="figure"/> - </zeroOrMore> - </choice> + </optional> + </define> + <define name="FigureBody"> + <optional> + <ref name="tname"> + <a:documentation>The caption of the block</a:documentation> + </ref> + </optional> + <choice> + <a:documentation>Content of the figure</a:documentation> + <ref name="image"/> + <ref name="video"/> + <ref name="audio"/> + <ref name="pre"/> + <oneOrMore> + <ref name="paragraph-with-footnote"/> + </oneOrMore> <zeroOrMore> - <ref name="fn"/> + <ref name="figure"/> </zeroOrMore> - <optional> - <ref name="dl"/> - </optional> + </choice> + <zeroOrMore> + <ref name="fn"> + <a:documentation>Footnotes specific to the figure</a:documentation> + </ref> + </zeroOrMore> + <optional> + <ref name="dl"> + <a:documentation>An optional definitions list defining any symbols used in the figure</a:documentation> + </ref> + </optional> + <zeroOrMore> + <ref name="note"> + <a:documentation>Notes whose scope is the current block</a:documentation> + </ref> + </zeroOrMore> + <optional> + <ref name="source"> + <a:documentation>A URI or other reference intended to link to an externally hosted image (or equivalent)</a:documentation> + </ref> + </optional> + </define> + <define name="FigureNoIdBody"> + <optional> + <ref name="source"> + <a:documentation>A URI or other reference intended to link to an externally hosted image (or equivalent)</a:documentation> + </ref> + </optional> + <optional> + <ref name="tname"> + <a:documentation>The caption of the block</a:documentation> + </ref> + </optional> + <choice> + <a:documentation>Content of the figure</a:documentation> + <ref name="image-no-id"/> + <ref name="video-no-id"/> + <ref name="audio-no-id"/> + <ref name="pre-no-id"/> + <oneOrMore> + <ref name="paragraph-with-footnote-no-id"/> + </oneOrMore> <zeroOrMore> - <ref name="note"/> + <ref name="figure-no-id"/> </zeroOrMore> - </element> + </choice> + <zeroOrMore> + <ref name="fn"> + <a:documentation>Footnotes specific to the figure</a:documentation> + </ref> + </zeroOrMore> + <optional> + <ref name="dl-no-id"> + <a:documentation>An optional definitions list defining any symbols used in the figure</a:documentation> + </ref> + </optional> + <zeroOrMore> + <ref name="note-no-id"> + <a:documentation>Notes whose scope is the current block</a:documentation> + </ref> + </zeroOrMore> </define> <define name="TextElement"> + <a:documentation>Any inline element containing text and associated formatting information. +Includes inline elements that are identifiers or references to identifiers</a:documentation> <choice> <text/> <ref name="em"/> @@ -682,69 +1268,91 @@ </choice> </define> <define name="PureTextElement"> + <a:documentation>Inline element containing text and associated formatting information, +but which does not contain any associated identifiers or references to identifiers. +Restricted recursively to contain only other such inline elements with no identifiers or references to identifiers</a:documentation> <choice> <text/> - <ref name="em"/> - <ref name="strong"/> + <ref name="pure_em"/> + <ref name="pure_strong"/> <ref name="sub"/> <ref name="sup"/> - <ref name="tt"/> - <ref name="underline"/> - <ref name="strike"/> - <ref name="smallcap"/> + <ref name="pure_tt"/> + <ref name="pure_underline"/> + <ref name="pure_strike"/> + <ref name="pure_smallcap"/> <ref name="br"/> </choice> </define> + <define name="NestedTextElement"> + <a:documentation>Contents of TextElement tags: leaves out tags that should occur only at top level of block: bookmark image hr pagebreak</a:documentation> + <choice> + <ref name="PureTextElement"/> + <ref name="stem"/> + <ref name="eref"/> + <ref name="xref"/> + <ref name="hyperlink"/> + <ref name="index"/> + <ref name="index-xref"/> + <ref name="ruby"/> + <ref name="keyword"/> + </choice> + </define> <define name="source"> <element name="source"> <ref name="TypedUri"/> </element> </define> <define name="em"> + <a:documentation>Emphasised text. Corresponds to HTML `em`, `i`</a:documentation> <element name="em"> <zeroOrMore> - <choice> - <ref name="PureTextElement"/> - <ref name="stem"/> - <ref name="eref"/> - <ref name="xref"/> - <ref name="hyperlink"/> - <ref name="index"/> - <ref name="index-xref"/> - </choice> + <ref name="NestedTextElement"/> + </zeroOrMore> + </element> + </define> + <define name="pure_em"> + <a:documentation>Emphasised text for PureTextElement</a:documentation> + <element name="em"> + <zeroOrMore> + <ref name="PureTextElement"/> </zeroOrMore> </element> </define> <define name="strong"> + <a:documentation>Strong text. Corresponds to HTML `strong`, `b`</a:documentation> <element name="strong"> <zeroOrMore> - <choice> - <ref name="PureTextElement"/> - <ref name="stem"/> - <ref name="eref"/> - <ref name="xref"/> - <ref name="hyperlink"/> - <ref name="index"/> - <ref name="index-xref"/> - </choice> + <ref name="NestedTextElement"/> + </zeroOrMore> + </element> + </define> + <define name="pure_strong"> + <a:documentation>Strong text for PureTextElement</a:documentation> + <element name="strong"> + <zeroOrMore> + <ref name="PureTextElement"/> </zeroOrMore> </element> </define> <define name="tt"> + <a:documentation>Monospace text. Corresponds to HTML `tt`, `code`</a:documentation> <element name="tt"> <zeroOrMore> - <choice> - <ref name="PureTextElement"/> - <ref name="eref"/> - <ref name="xref"/> - <ref name="hyperlink"/> - <ref name="index"/> - <ref name="index-xref"/> - </choice> + <ref name="NestedTextElement"/> + </zeroOrMore> + </element> + </define> + <define name="pure_tt"> + <a:documentation>Monospace text for PureTextElement</a:documentation> + <element name="tt"> + <zeroOrMore> + <ref name="PureTextElement"/> </zeroOrMore> </element> </define> <define name="keyword"> + <a:documentation>Keyword text</a:documentation> <element name="keyword"> <zeroOrMore> <choice> @@ -756,6 +1364,7 @@ </element> </define> <define name="sub"> + <a:documentation>Subscript text. Corresponds to HTML `sub`</a:documentation> <element name="sub"> <zeroOrMore> <ref name="PureTextElement"/> @@ -763,6 +1372,7 @@ </element> </define> <define name="sup"> + <a:documentation>Superscript text. Corresponds to HTML `sup`</a:documentation> <element name="sup"> <zeroOrMore> <ref name="PureTextElement"/> @@ -770,17 +1380,36 @@ </element> </define> <define name="strike"> + <a:documentation>Strikethrough text. Corresponds to HTML 4 `s`</a:documentation> <element name="strike"> <zeroOrMore> - <choice> - <ref name="PureTextElement"/> - <ref name="index"/> - <ref name="index-xref"/> - </choice> + <ref name="NestedTextElement"/> + </zeroOrMore> + </element> + </define> + <define name="pure_strike"> + <a:documentation>Strikethrough for PureTextElement</a:documentation> + <element name="strike"> + <zeroOrMore> + <ref name="PureTextElement"/> </zeroOrMore> </element> </define> <define name="underline"> + <a:documentation>Underlined text. Corresponds to HTML 4 `u`</a:documentation> + <element name="underline"> + <optional> + <attribute name="style"> + <a:documentation>CSS style to apply to underline (intended for text-decoration-style attribute keyword values: solid double dotted dashed wavy)</a:documentation> + </attribute> + </optional> + <zeroOrMore> + <ref name="NestedTextElement"/> + </zeroOrMore> + </element> + </define> + <define name="pure_underline"> + <a:documentation>Underlined text for PureTextElement</a:documentation> <element name="underline"> <optional> <attribute name="style"/> @@ -791,6 +1420,15 @@ </element> </define> <define name="smallcap"> + <a:documentation>Small caps text</a:documentation> + <element name="smallcap"> + <zeroOrMore> + <ref name="NestedTextElement"/> + </zeroOrMore> + </element> + </define> + <define name="pure_smallcap"> + <a:documentation>Small caps text for PureTextElement</a:documentation> <element name="smallcap"> <zeroOrMore> <ref name="PureTextElement"/> @@ -798,252 +1436,320 @@ </element> </define> <define name="ruby"> + <a:documentation>Text with Ruby annotations in East Asian languages. Corresponds to HTML `ruby`</a:documentation> <element name="ruby"> <choice> - <ref name="ruby_pronunciation"/> - <ref name="ruby_annotation"/> + <ref name="ruby_pronunciation"> + <a:documentation>Ruby annotation giving pronunciation</a:documentation> + </ref> + <ref name="ruby_annotation"> + <a:documentation>Ruby annotation giving other (semantic) information</a:documentation> + </ref> </choice> <choice> - <text/> - <ref name="ruby"/> + <text> + <a:documentation>Ruby annotated text which contains no further annotations</a:documentation> + </text> + <ref name="ruby"> + <a:documentation>Ruby annotated text which itself contains other Ruby annotations</a:documentation> + </ref> </choice> </element> </define> <define name="ruby_pronunciation"> + <a:documentation>Ruby annotation giving pronunciation of text</a:documentation> <element name="pronunciation"> - <attribute name="value"/> - <optional> - <attribute name="script"/> - </optional> - <optional> - <attribute name="lang"/> - </optional> + <attribute name="value"> + <a:documentation>Ruby annotation value</a:documentation> + </attribute> + <ref name="LocalizedStringAttributes"/> </element> </define> <define name="ruby_annotation"> + <a:documentation>Ruby annotation giving information other than pronunciation of text</a:documentation> <element name="annotation"> - <attribute name="value"/> - <optional> - <attribute name="script"/> - </optional> - <optional> - <attribute name="lang"/> - </optional> + <attribute name="value"> + <a:documentation>Ruby annotation value</a:documentation> + </attribute> + <ref name="LocalizedStringAttributes"/> </element> </define> <define name="br"> + <a:documentation>Line break</a:documentation> <element name="br"> <empty/> </element> </define> <define name="hr"> + <a:documentation>Horizontal rule</a:documentation> <element name="hr"> <empty/> </element> </define> <define name="pagebreak"> + <a:documentation>Page break. Only applicable in paged layouts (e.g. PDF, Word), and not flow layouts (e.g. HTML)</a:documentation> <element name="pagebreak"> <empty/> </element> </define> <define name="index"> + <a:documentation>Index term, defined as applying to the location in the text where the index element appears, as a milestone</a:documentation> <element name="index"> <optional> <attribute name="to"> + <a:documentation>A reference to an anchor element (typically a bookmark), +to indicate that the index range covers a range of locations between the current index element and the `to` anchor</a:documentation> <data type="IDREF"/> </attribute> </optional> - <element name="primary"> - <oneOrMore> - <ref name="PureTextElement"/> - </oneOrMore> - </element> - <optional> - <element name="secondary"> - <oneOrMore> - <ref name="PureTextElement"/> - </oneOrMore> - </element> - </optional> - <optional> - <element name="tertiary"> - <oneOrMore> - <ref name="PureTextElement"/> - </oneOrMore> - </element> - </optional> + <ref name="index-primary"> + <a:documentation>Primary index term to be recorded at the current location</a:documentation> + </ref> + <ref name="index-secondary"> + <a:documentation>Secondary index term to be recorded at the current location</a:documentation> + </ref> + <ref name="index-tertiary"> + <a:documentation>Tertiary index term to be recorded at the current </a:documentation> + </ref> </element> </define> <define name="index-xref"> + <a:documentation>A reference to an index term, cross-referenced within an index as an +alternative index entry, either as a "see" or a "see also" cross-reference. +The text in the inline element is the primary index term to be be cross-referenced</a:documentation> <element name="index-xref"> <attribute name="also"> + <a:documentation>The cross-reference is to be treated as "see also" rather than as "see"</a:documentation> <data type="boolean"/> </attribute> - <element name="primary"> - <oneOrMore> - <ref name="PureTextElement"/> - </oneOrMore> - </element> - <optional> - <element name="secondary"> - <oneOrMore> - <ref name="PureTextElement"/> - </oneOrMore> - </element> - </optional> - <optional> - <element name="tertiary"> - <oneOrMore> - <ref name="PureTextElement"/> - </oneOrMore> - </element> - </optional> + <ref name="index-primary"> + <a:documentation>The primary index term to be cross-referenced</a:documentation> + </ref> + <ref name="index-secondary"> + <a:documentation>The secondary index term to be cross-referenced</a:documentation> + </ref> + <ref name="index-tertiary"> + <a:documentation>The tertiary index term to be cross-referenced</a:documentation> + </ref> <element name="target"> + <a:documentation>The index term to be cross-referenced to</a:documentation> <oneOrMore> <ref name="PureTextElement"/> </oneOrMore> </element> </element> </define> - <!-- bare ID element, used for referencing arbitrary spans of text --> + <define name="index-primary"> + <element name="primary"> + <oneOrMore> + <ref name="PureTextElement"/> + </oneOrMore> + </element> + </define> + <define name="index-secondary"> + <element name="secondary"> + <oneOrMore> + <ref name="PureTextElement"/> + </oneOrMore> + </element> + </define> + <define name="index-tertiary"> + <element name="tertiary"> + <oneOrMore> + <ref name="PureTextElement"/> + </oneOrMore> + </element> + </define> <define name="bookmark"> + <a:documentation>Anchors within a block under the BasicDocument model cannot span across a number of inline elements; +bookmarks are intended as point anchors. For that reason, the Review block has a starting reference and an optional ending reference, +which can be bookmarks as well as block or section references</a:documentation> <element name="bookmark"> - <attribute name="id"> - <data type="ID"/> - </attribute> + <ref name="RequiredId"/> <empty/> </element> </define> <define name="ReferenceFormat"> + <a:documentation>The type of Reference Element, prescribing how it is to be rendered</a:documentation> <choice> <value>external</value> + <a:documentation>Reference to an external document</a:documentation> <value>inline</value> + <a:documentation>Reference to another element in the same document</a:documentation> <value>footnote</value> + <a:documentation>Inline reference to a block to be rendered as a footnote</a:documentation> <value>callout</value> + <a:documentation>Inline reference to a block to be referenced as a sourcecode callout</a:documentation> </choice> </define> <define name="eref"> + <a:documentation>An external reference to a bibliographic entity</a:documentation> <element name="eref"> <ref name="erefType"/> </element> </define> <define name="erefType"> + <ref name="erefAttributes"/> + <ref name="CitationType"> + <a:documentation>Reference cross-reference: modelled as cross-reference to the corresponding bibliographical item in a References section</a:documentation> + </ref> + <ref name="ErefBody"> + <a:documentation>The textual content of the element. The `text` is what we wish to show the link as (e.g., the "content" of `<xx>my link text</xx>`)</a:documentation> + </ref> + </define> + <define name="erefAttributes"> <optional> <attribute name="normative"> + <a:documentation>Whether the reference is to be treated as normative or informative, particularly in the context of normative documents such as standards</a:documentation> <data type="boolean"/> </attribute> </optional> - <attribute name="citeas"/> - <attribute name="type"> - <ref name="ReferenceFormat"/> + <attribute name="citeas"> + <a:documentation>Form that the bibliographic citation should take when it is rendered</a:documentation> </attribute> <optional> - <attribute name="alt"/> + <attribute name="type"> + <a:documentation>The type of Reference Element, prescribing how it is to be rendered</a:documentation> + <ref name="ReferenceFormat"/> + </attribute> + </optional> + <optional> + <attribute name="alt"> + <a:documentation>Alternate text, used for accessibility</a:documentation> + </attribute> </optional> - <ref name="CitationType"/> - <oneOrMore> - <ref name="PureTextElement"/> - </oneOrMore> </define> <define name="hyperlink"> + <a:documentation>A reference to an external document or resource</a:documentation> <element name="link"> - <attribute name="target"> - <data type="anyURI"/> - </attribute> + <ref name="HyperlinkAttributes"/> + <oneOrMore> + <ref name="PureTextElement"> + <a:documentation>The textual content of the element. The `text` is what we wish to show the link as (e.g., the "content" of `<xx>my link text</xx>`)</a:documentation> + </ref> + </oneOrMore> + </element> + </define> + <define name="HyperlinkAttributes"> + <attribute name="target"> + <a:documentation>The location or online identifier of the external document or resource</a:documentation> + <data type="anyURI"/> + </attribute> + <optional> <attribute name="type"> + <a:documentation>The type of Reference Element, prescribing how it is to be rendered</a:documentation> <ref name="ReferenceFormat"/> </attribute> - <optional> - <attribute name="alt"/> - </optional> - <oneOrMore> - <ref name="PureTextElement"/> - </oneOrMore> - </element> + </optional> + <optional> + <attribute name="alt"> + <a:documentation>Alternate text, used for accessibility</a:documentation> + </attribute> + </optional> </define> <define name="xref"> + <a:documentation>Inline element, which references an identifier of a document, a block in a document, or an element in a document</a:documentation> <element name="xref"> - <attribute name="target"> - <data type="IDREF"/> - </attribute> + <ref name="XrefAttributes"/> + <ref name="XrefBody"/> + </element> + </define> + <define name="XrefAttributes"> + <attribute name="target"> + <a:documentation>The identifier of a section, block or inlined element being referenced</a:documentation> + <data type="IDREF"/> + </attribute> + <optional> <attribute name="type"> + <a:documentation>The type of Reference Element, prescribing how it is to be rendered</a:documentation> <ref name="ReferenceFormat"/> </attribute> - <optional> - <attribute name="alt"/> - </optional> - <oneOrMore> - <ref name="PureTextElement"/> - </oneOrMore> - </element> + </optional> + <optional> + <attribute name="alt"> + <a:documentation>Alternate text, used for accessibility</a:documentation> + </attribute> + </optional> + </define> + <define name="XrefBody"> + <oneOrMore> + <ref name="PureTextElement"> + <a:documentation>The textual content of the element. The `text` is what we wish to show the link as (e.g., the "content" of `<xx>my link text</xx>`)</a:documentation> + </ref> + </oneOrMore> + </define> + <define name="ErefBody"> + <oneOrMore> + <ref name="PureTextElement"> + <a:documentation>The textual content of the element. The `text` is what we wish to show the link as (e.g., the "content" of `<xx>my link text</xx>`)</a:documentation> + </ref> + </oneOrMore> </define> <define name="fn"> + <a:documentation>Inline reference to a paragraph or paragraphs, appearing as a footnote. +The target of a footnote is the location it is embedded in within the text</a:documentation> <element name="fn"> - <attribute name="reference"/> + <attribute name="reference"> + <a:documentation>The number of the footnote, used to identify it visually</a:documentation> + </attribute> <oneOrMore> - <ref name="paragraph"/> + <ref name="paragraph"> + <a:documentation>The content of the footnote</a:documentation> + </ref> </oneOrMore> </element> </define> - <!-- - This is xref with fixed @type="footnote", and @target built in as paragraph+ - @reference replaces ReferenceElement/text - so <fn reference="2"><p>This is a footnote</p></fn> - corresponds to - <eref type="footnote" target="fn2">2</xref> <p id="fn2">This is a footnote</p> - --> <define name="callout"> + <a:documentation>Inline reference to a paragraph or paragraphs, appearing as annotation of source code</a:documentation> <element name="callout"> <attribute name="target"> + <a:documentation>The target of the callout is understood to be the location of the callout within the source code; +the extent of the target is not expressed overtly</a:documentation> <data type="IDREF"/> </attribute> - <text/> + <text> + <a:documentation>The label of the callout, used to identify its target within the source code</a:documentation> + </text> </element> </define> - <!-- - This is xref with fixed @type="callout"; the target by convention is in an annotation in the same source code snippet - so <callout target="xyz">1</callout> - corresponds to <xref type="callout" target="xyz">1</xref> - --> <define name="image"> + <a:documentation>Container for image content</a:documentation> <element name="image"> - <ref name="Image"/> + <ref name="RequiredId"/> + <ref name="ImageAttributes"/> </element> </define> - <define name="Image"> - <attribute name="id"> - <data type="ID"/> - </attribute> - <attribute name="src"> - <data type="anyURI"/> - </attribute> - <attribute name="mimetype"/> - <optional> - <attribute name="filename"/> - </optional> + <define name="image-no-id"> + <a:documentation>Container for image content: optional ID attributes recursively (for use in Relaton, metadata)</a:documentation> + <element name="image"> + <ref name="OptionalId"/> + <ref name="ImageAttributes"/> + </element> + </define> + <define name="ImageAttributes"> + <ref name="MediaAttributes"/> + <ref name="MediaAccessibilityAttributes"/> <optional> <attribute name="width"> + <a:documentation>Height of image</a:documentation> <ref name="ImageSize"/> </attribute> </optional> <optional> <attribute name="height"> + <a:documentation>Width of image</a:documentation> <ref name="ImageSize"/> </attribute> </optional> - <optional> - <attribute name="alt"/> - </optional> - <optional> - <attribute name="title"/> - </optional> - <optional> - <attribute name="longdesc"> - <data type="anyURI"/> - </attribute> - </optional> + </define> + <define name="MIMEType"> + <a:documentation>MIME encoding of media type</a:documentation> + <text/> </define> <define name="ImageSize"> + <a:documentation>Legal values for image height and width. +Attributes are realised as a real number, with optional percent sign, +or as the string "auto"</a:documentation> <choice> <data type="string"> <param name="pattern">\d+([.]\d+)?(%?)</param> @@ -1052,177 +1758,328 @@ </choice> </define> <define name="video"> + <a:documentation>Container for video content</a:documentation> <element name="video"> - <attribute name="id"> - <data type="ID"/> + <ref name="RequiredId"/> + <ref name="VideoAttributes"/> + <ref name="VideoBody"/> + </element> + </define> + <define name="video-no-id"> + <a:documentation>Container for video content: optional ID attributes recursively (for use in Relaton, metadata)</a:documentation> + <element name="video"> + <ref name="OptionalId"/> + <ref name="VideoAttributes"/> + <ref name="VideoBody"/> + </element> + </define> + <define name="VideoAttributes"> + <ref name="MediaAttributes"/> + <ref name="MediaAccessibilityAttributes"/> + <optional> + <attribute name="width"> + <a:documentation>Width of video</a:documentation> + <ref name="ImageSize"/> </attribute> - <attribute name="src"> - <data type="anyURI"/> + </optional> + <optional> + <attribute name="height"> + <a:documentation>Height of video</a:documentation> + <ref name="ImageSize"/> </attribute> - <attribute name="mimetype"/> - <optional> - <attribute name="filename"/> - </optional> - <optional> - <attribute name="width"> - <choice> - <data type="int"/> - <value>auto</value> - </choice> - </attribute> - </optional> - <optional> - <attribute name="height"> - <choice> - <data type="int"/> - <value>auto</value> - </choice> - </attribute> - </optional> - <optional> - <attribute name="alt"/> - </optional> - <optional> - <attribute name="title"/> - </optional> - <optional> - <attribute name="longdesc"> - <data type="anyURI"/> - </attribute> - </optional> - <zeroOrMore> - <ref name="altsource"/> - </zeroOrMore> - </element> + </optional> + </define> + <define name="VideoBody"> + <zeroOrMore> + <ref name="altsource"> + <a:documentation>Alternative files to use as media</a:documentation> + </ref> + </zeroOrMore> </define> <define name="audio"> + <a:documentation>Container for audio content</a:documentation> <element name="audio"> - <attribute name="id"> - <data type="ID"/> - </attribute> - <attribute name="src"> - <data type="anyURI"/> - </attribute> - <attribute name="mimetype"/> - <optional> - <attribute name="filename"/> - </optional> - <optional> - <attribute name="alt"/> - </optional> - <optional> - <attribute name="title"/> - </optional> - <optional> - <attribute name="longdesc"> - <data type="anyURI"/> - </attribute> - </optional> - <zeroOrMore> - <ref name="altsource"/> - </zeroOrMore> + <ref name="RequiredId"/> + <ref name="AudioAttributes"/> + <ref name="AudioBody"/> + </element> + </define> + <define name="audio-no-id"> + <a:documentation>Container for audio content: optional ID attributes recursively (for use in Relaton, metadata)</a:documentation> + <element name="audio"> + <ref name="OptionalId"/> + <ref name="AudioAttributes"/> + <ref name="AudioBody"/> </element> </define> + <define name="AudioAttributes"> + <ref name="MediaAttributes"/> + <ref name="MediaAccessibilityAttributes"/> + </define> + <define name="AudioBody"> + <zeroOrMore> + <ref name="altsource"> + <a:documentation>Alternative files to use as media</a:documentation> + </ref> + </zeroOrMore> + </define> <define name="altsource"> + <a:documentation>Alternative file to use as media</a:documentation> <element name="altsource"> - <attribute name="src"> + <ref name="MediaAttributes"/> + </element> + </define> + <define name="MediaAttributes"> + <attribute name="src"> + <a:documentation>URI of the media file</a:documentation> + <data type="anyURI"/> + </attribute> + <attribute name="mimetype"> + <a:documentation>Type of the media file, in MIME</a:documentation> + <ref name="MIMEType"/> + </attribute> + <optional> + <attribute name="filename"> + <a:documentation>File name corresponding to the media, to which the media can be extracted if it is represented inline +(e.g. in Base64 encoding in the URI)</a:documentation> + </attribute> + </optional> + </define> + <define name="MediaAccessibilityAttributes"> + <optional> + <attribute name="alt"> + <a:documentation>Alternate text, supplied for accessibility</a:documentation> + </attribute> + </optional> + <optional> + <attribute name="title"> + <a:documentation>Title, supplied for accessibility</a:documentation> + </attribute> + </optional> + <optional> + <attribute name="longdesc"> + <a:documentation>URI pointing to more extensive alternate text description, supplied for accessibility</a:documentation> <data type="anyURI"/> </attribute> - <attribute name="mimetype"/> - <optional> - <attribute name="filename"/> - </optional> - </element> + </optional> </define> <define name="stem"> + <a:documentation>Mathematically formatted text</a:documentation> <element name="stem"> - <attribute name="type"> - <choice> - <value>MathML</value> - <value>AsciiMath</value> - </choice> - </attribute> + <ref name="StemAttributes"/> <oneOrMore> <choice> + <a:documentation>The content of the mathematically formatted text</a:documentation> <text/> <ref name="AnyElement"/> </choice> </oneOrMore> </element> </define> + <define name="StemAttributes"> + <attribute name="type"> + <a:documentation>The notation used to mathematically format the text</a:documentation> + <choice> + <value>MathML</value> + <value>AsciiMath</value> + <value>LaTeX</value> + </choice> + </attribute> + </define> <define name="annotation"> <element name="annotation"> - <attribute name="id"> - <data type="ID"/> - </attribute> - <ref name="paragraph"/> + <ref name="RequiredId"/> + <oneOrMore> + <ref name="paragraph"/> + </oneOrMore> </element> </define> <define name="ul"> + <a:documentation>Unordered list block</a:documentation> <element name="ul"> - <attribute name="id"> - <data type="ID"/> - </attribute> - <oneOrMore> - <ref name="li"/> - </oneOrMore> - <zeroOrMore> - <ref name="note"/> - </zeroOrMore> + <ref name="RequiredId"/> + <ref name="UlAttributes"/> + <ref name="UlBody"/> + </element> + </define> + <define name="ul-no-id"> + <a:documentation>Unordered list block: optional ID attributes recursively (for use in Relaton, metadata)</a:documentation> + <element name="ul"> + <ref name="OptionalId"/> + <ref name="UlAttributes"/> + <ref name="UlNoIdBody"/> </element> </define> + <define name="UlAttributes"> + <empty/> + </define> + <define name="UlBody"> + <oneOrMore> + <ref name="li"> + <a:documentation>List items</a:documentation> + </ref> + </oneOrMore> + <zeroOrMore> + <ref name="note"> + <a:documentation>Notes whose scope is the current block</a:documentation> + </ref> + </zeroOrMore> + </define> + <define name="UlNoIdBody"> + <oneOrMore> + <ref name="li-no-id"> + <a:documentation>List items</a:documentation> + </ref> + </oneOrMore> + <zeroOrMore> + <ref name="note-no-id"> + <a:documentation>Notes whose scope is the current block</a:documentation> + </ref> + </zeroOrMore> + </define> <define name="li"> + <a:documentation>Item in a list block</a:documentation> <element name="li"> - <optional> - <attribute name="id"> - <data type="ID"/> - </attribute> - </optional> - <oneOrMore> - <ref name="paragraph-with-footnote"/> - </oneOrMore> + <ref name="OptionalId"/> + <ref name="LiAttributes"/> + <ref name="LiBody"/> + </element> + </define> + <define name="li-no-id"> + <a:documentation>Item in a list block: optional ID attributes recursively (for use in Relaton, metadata)</a:documentation> + <element name="li"> + <ref name="OptionalId"/> + <ref name="LiAttributes"/> + <ref name="LiNoIdBody"/> </element> </define> + <define name="LiAttributes"> + <empty/> + </define> + <define name="LiBody"> + <oneOrMore> + <ref name="paragraph-with-footnote"/> + </oneOrMore> + </define> + <define name="LiNoIdBody"> + <oneOrMore> + <ref name="paragraph-with-footnote-no-id"/> + </oneOrMore> + </define> <define name="ol"> + <a:documentation>Ordered list, with numbering applied to the list items</a:documentation> <element name="ol"> - <attribute name="id"> - <data type="ID"/> - </attribute> - <attribute name="type"> - <choice> - <value>roman</value> - <value>alphabet</value> - <value>arabic</value> - <value>roman_upper</value> - <value>alphabet_upper</value> - </choice> - </attribute> - <optional> - <attribute name="start"/> - </optional> - <oneOrMore> - <ref name="li"/> - </oneOrMore> - <zeroOrMore> - <ref name="note"/> - </zeroOrMore> + <ref name="RequiredId"/> + <ref name="OlAttributes"/> + <ref name="OlBody"/> + </element> + </define> + <define name="ol-no-id"> + <a:documentation>Ordered list: optional ID attributes recursively (for use in Relaton, metadata)</a:documentation> + <element name="ol"> + <ref name="OptionalId"/> + <ref name="OlAttributes"/> + <ref name="OlNoIdBody"/> </element> </define> + <define name="OlAttributes"> + <attribute name="type"> + <a:documentation>Type of numbering to be applied to the list items</a:documentation> + <choice> + <value>roman</value> + <value>alphabet</value> + <value>arabic</value> + <value>roman_upper</value> + <value>alphabet_upper</value> + </choice> + </attribute> + <optional> + <attribute name="start"> + <a:documentation>Starting value for numbering of the list items; is a number, regardless of the type, +and is mapped to the ordinal represented in the type</a:documentation> + </attribute> + </optional> + </define> + <define name="OlBody"> + <oneOrMore> + <ref name="li"> + <a:documentation>List item</a:documentation> + </ref> + </oneOrMore> + <zeroOrMore> + <ref name="note"> + <a:documentation>Notes whose scope is the current block</a:documentation> + </ref> + </zeroOrMore> + </define> + <define name="OlNoIdBody"> + <oneOrMore> + <ref name="li-no-id"> + <a:documentation>List item</a:documentation> + </ref> + </oneOrMore> + <zeroOrMore> + <ref name="note-no-id"> + <a:documentation>Notes whose scope is the current block</a:documentation> + </ref> + </zeroOrMore> + </define> <define name="dl"> + <a:documentation>Definition list, composed of definitions rather than list items</a:documentation> <element name="dl"> - <attribute name="id"> - <data type="ID"/> - </attribute> - <oneOrMore> - <ref name="dt"/> - <ref name="dd"/> - </oneOrMore> - <zeroOrMore> - <ref name="note"/> - </zeroOrMore> + <ref name="RequiredId"/> + <ref name="DlAttributes"/> + <ref name="DlBody"/> + </element> + </define> + <define name="dl-no-id"> + <a:documentation>Definition list: optional ID attributes recursively (for use in Relaton, metadata)</a:documentation> + <element name="dl"> + <ref name="OptionalId"/> + <ref name="DlNoIdBody"/> </element> </define> + <define name="DlAttributes"> + <empty/> + </define> + <define name="DlBody"> + <oneOrMore> + <group> + <a:documentation>Entry-Definition pair used to constitute a definition list</a:documentation> + <ref name="dt"> + <a:documentation>Entry being defined in the definition</a:documentation> + </ref> + <ref name="dd"> + <a:documentation>Definition of the entry</a:documentation> + </ref> + </group> + </oneOrMore> + <zeroOrMore> + <ref name="note"> + <a:documentation>Notes whose scope is the current block</a:documentation> + </ref> + </zeroOrMore> + </define> + <define name="DlNoIdBody"> + <oneOrMore> + <group> + <a:documentation>Entry-Definition pair used to constitute a definition list</a:documentation> + <ref name="dt"> + <a:documentation>Entry being defined in the definition</a:documentation> + </ref> + <ref name="dd-no-id"> + <a:documentation>Definition of the entry</a:documentation> + </ref> + </group> + </oneOrMore> + <zeroOrMore> + <ref name="note-no-id"> + <a:documentation>Notes whose scope is the current block</a:documentation> + </ref> + </zeroOrMore> + </define> <define name="dt"> + <a:documentation>Entry in a definition list</a:documentation> <element name="dt"> <zeroOrMore> <ref name="TextElement"/> @@ -1230,10 +2087,19 @@ </element> </define> <define name="dd"> + <a:documentation>Definition in a definition list</a:documentation> <element name="dd"> <zeroOrMore> <ref name="paragraph-with-footnote"/> </zeroOrMore> </element> </define> + <define name="dd-no-id"> + <a:documentation>Definition in a definition list: optional ID attributes recursively (for use in Relaton, metadata)</a:documentation> + <element name="dd"> + <zeroOrMore> + <ref name="paragraph-with-footnote-no-id"/> + </zeroOrMore> + </element> + </define> </grammar> diff --git a/grammars/biblio-standoc.rng b/grammars/biblio-standoc.rng index 2373865..6588af6 100644 --- a/grammars/biblio-standoc.rng +++ b/grammars/biblio-standoc.rng @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8"?> -<grammar xmlns="http://relaxng.org/ns/structure/1.0"> +<grammar xmlns:a="http://relaxng.org/ns/compatibility/annotations/1.0" xmlns="http://relaxng.org/ns/structure/1.0"> <!-- Add-ons to biblio.rnc for standoc model: defines the extension point BibDataExtensionType of relaton @@ -9,19 +9,23 @@ --> <include href="biblio.rng"> <define name="BibData"> + <a:documentation>The bibliographic description of a standardisation document</a:documentation> <ref name="StandardBibliographicItem"/> <optional> - <ref name="ext"/> + <ref name="ext"> + <a:documentation>The extension point of the bibliographic description of a standardisation document</a:documentation> + </ref> </optional> </define> <define name="docrelation"> + <a:documentation>Update to StandardReducedBibliographicItem</a:documentation> <element name="relation"> <attribute name="type"> <ref name="DocRelationType"/> </attribute> <optional> <element name="description"> - <ref name="FormattedString"/> + <ref name="LocalizedMarkedUpString"/> </element> </optional> <element name="bibitem"> @@ -47,34 +51,58 @@ </define> </include> <define name="ext"> + <a:documentation>The extension point of the bibliographic description of a standardisation document</a:documentation> <element name="ext"> <ref name="BibDataExtensionType"/> </element> </define> <define name="BibDataExtensionType"> <optional> - <attribute name="schema-version"/> + <attribute name="schema-version"> + <a:documentation>The version of the flavour-specific schema that this extension point conforms to</a:documentation> + </attribute> </optional> - <ref name="doctype"/> + <ref name="doctype"> + <a:documentation>Classification of the standardisation document that is treated as a distinct series by the +standards defining organization, and that is rendered in a distinct manner</a:documentation> + </ref> <optional> - <ref name="docsubtype"/> + <ref name="docsubtype"> + <a:documentation>Subclass of the standardisation document, that is treated or processed differently +from other documents in the same doctype</a:documentation> + </ref> </optional> + <ref name="flavor"> + <a:documentation>Flavour of Metanorma used to process this document</a:documentation> + </ref> <optional> - <ref name="editorialgroup"/> + <ref name="editorialgroup"> + <a:documentation>Groups associated with the production of the standards document, typically within +a standards definition organization</a:documentation> + </ref> </optional> <zeroOrMore> - <ref name="ics"/> + <ref name="ics"> + <a:documentation>Classification of the document contents taken from the International Classification of Standards</a:documentation> + </ref> </zeroOrMore> <zeroOrMore> - <ref name="structuredidentifier"/> + <ref name="structuredidentifier"> + <a:documentation>Representation of the identifier for the standardisation document, giving its individual semantic components</a:documentation> + </ref> </zeroOrMore> </define> <define name="doctype"> + <a:documentation>Classification of the standardisation document</a:documentation> <element name="doctype"> <optional> - <attribute name="abbreviation"/> + <attribute name="abbreviation"> + <a:documentation>Standard abbreviation for the doctype value used by the standards defining organization</a:documentation> + </attribute> </optional> - <ref name="DocumentType"/> + <ref name="DocumentType"> + <a:documentation>Name of the doctype</a:documentation> + </ref> </element> </define> <define name="DocumentType"> @@ -88,105 +116,153 @@ <define name="DocumentSubtype"> <text/> </define> + <define name="flavor"> + <element name="flavor"> + <ref name="MetanormaFlavor"/> + </element> + </define> + <define name="MetanormaFlavor"> + <a:documentation>This is in fact an enum, as of this writing: standoc iso generic ietf ieee itu nist ogc csa cc iho ribose jis iec bsi bipm plateau. +However we prefer not to hardcode it, given ongoing extension.</a:documentation> + <text/> + </define> <define name="editorialgroup"> + <a:documentation>A group associated with the production of the standards document, typically within +a standards definition organization</a:documentation> <element name="editorialgroup"> <oneOrMore> - <ref name="technical-committee"/> + <ref name="technical-committee"> + <a:documentation>A technical committee associated with the production of the standards document</a:documentation> + </ref> </oneOrMore> </element> </define> <define name="technical-committee"> + <a:documentation>Technical committee associated with the production of a standards document</a:documentation> <element name="technical-committee"> <ref name="IsoWorkgroup"/> </element> </define> <define name="IsoWorkgroup"> <optional> - <attribute name="number"/> + <attribute name="number"> + <a:documentation>Numeric identifier of the technical committee</a:documentation> + </attribute> </optional> <optional> - <attribute name="type"/> + <attribute name="type"> + <a:documentation>Type of the technical committee, used in identifying the technical committee</a:documentation> + </attribute> </optional> <optional> - <attribute name="identifier"/> + <attribute name="identifier"> + <a:documentation>Non-numeric, complete identifier of the technical committee</a:documentation> + </attribute> </optional> <optional> - <attribute name="prefix"/> + <attribute name="prefix"> + <a:documentation>Disambiguating prefix added to number to form the identifier of the technical committee, +typically indicating its type</a:documentation> + </attribute> </optional> - <text/> + <text> + <a:documentation>Name of the technical committee</a:documentation> + </text> </define> <define name="ics"> + <a:documentation>Classification taken from the International Classification of Standards. +ICS is defined by ISO here -- https://www.iso.org/publication/PUB100033.html</a:documentation> <element name="ics"> <element name="code"> + <a:documentation>Classification code taken from the ICS</a:documentation> <text/> </element> <optional> <element name="text"> + <a:documentation>Text string associated with the classification code</a:documentation> <text/> </element> </optional> </element> </define> <define name="structuredidentifier"> + <a:documentation>Representation of the identifier for a standardisation document, giving its individual semantic components</a:documentation> <element name="structuredidentifier"> <optional> - <attribute name="type"/> + <attribute name="type"> + <a:documentation>Representation in the identifier of the type of standard document, corresponds to bibitem/ext/doctype</a:documentation> + </attribute> </optional> <oneOrMore> <element name="agency"> + <a:documentation>Representation in the identifier of the agency responsible for the standard document</a:documentation> <text/> </element> </oneOrMore> <optional> <element name="class"> + <a:documentation>Representation in the identifier of the class of standard document (as a subclass of the document type), +corresponds to bibitem/item/docsubtype</a:documentation> <text/> </element> </optional> <element name="docnumber"> + <a:documentation>Representation in the identifier of the (typically numeric) component uniquely identifying the document +or standard. If a document includes parts or supplements, the docnumber identifies the document as whole, +and not those document components</a:documentation> <text/> </element> <optional> <element name="partnumber"> + <a:documentation>Representation in the identifier of the document part, if this is a document part. May be compound</a:documentation> <text/> </element> </optional> <optional> <element name="edition"> + <a:documentation>Representation in the identifier of the document edition, if this is a published document</a:documentation> <text/> </element> </optional> <optional> <element name="version"> + <a:documentation>Representation in the identifier of the document version, which can include document drafts</a:documentation> <text/> </element> </optional> <optional> <element name="supplementtype"> + <a:documentation>Representation in the identifier of the type of document supplement, if this is a document supplement</a:documentation> <text/> </element> </optional> <optional> <element name="supplementnumber"> + <a:documentation>Representation in the identifier of the document supplement, if this is a document supplement</a:documentation> <text/> </element> </optional> <optional> <element name="amendment"> + <a:documentation>Representation in the identifier of the document amendment, if this is a document amendment</a:documentation> <text/> </element> </optional> <optional> <element name="corrigendum"> + <a:documentation>Representation in the identifier of the document corrigendum, if this is a document corrigendum</a:documentation> <text/> </element> </optional> <optional> <element name="language"> + <a:documentation>Representation in the identifier of the language of the document</a:documentation> <text/> </element> </optional> <optional> <element name="year"> + <a:documentation>Representation in the identifier of the year of publication or issuance of the document</a:documentation> <text/> </element> </optional> @@ -195,13 +271,17 @@ <define name="StandardBibliographicItem"> <ref name="BibliographicItem"/> <zeroOrMore> - <ref name="amend"/> + <ref name="amend"> + <a:documentation>Description of changes specific to this document</a:documentation> + </ref> </zeroOrMore> </define> <define name="StandardReducedBibliographicItem"> <ref name="ReducedBibliographicItem"/> <zeroOrMore> - <ref name="amend"/> + <ref name="amend"> + <a:documentation>Description of changes specific to this document</a:documentation> + </ref> </zeroOrMore> </define> </grammar> diff --git a/grammars/biblio.rng b/grammars/biblio.rng index f18d67c..2b81353 100644 --- a/grammars/biblio.rng +++ b/grammars/biblio.rng @@ -24,44 +24,62 @@ Somewhat dumbed down for XSD regex: --> <define name="ISO8601DateTime"> + <a:documentation>Date/Time conforming with ISO 8601</a:documentation> <data type="string"> <param name="pattern">([\+\-]?\d{4})((-?)((0[1-9]|1[0-2])((-?)([12]\d|0[1-9]|3[01]))?|W([0-4]\d|5[0-2])(-?[1-7])?|(00[1-9]|0[1-9]\d|[12]\d{2}|3([0-5]\d|6[1-6])))([T\s]((([01]\d|2[0-3])((:?)[0-5]\d)?|24:?00)([\.,]\d+)?)?((:?)[0-5]\d([.,]\d+)?)?([zZ]|([\+\-])([01]\d|2[0-3]):?([0-5]\d)?)?)?)?</param> </data> </define> <define name="ISO8601Date"> + <a:documentation>Date conforming with ISO 8601</a:documentation> <data type="string"> <param name="pattern">([\+\-]?\d{4})((-?)((0[1-9]|1[0-2])((-?)([12]\d|0[1-9]|3[01]))?|W([0-4]\d|5[0-2])(-?[1-7])?|(00[1-9]|0[1-9]\d|[12]\d{2}|3([0-5]\d|6[1-6]))))?</param> </data> </define> - <!-- start = bibitem --> <define name="BibData"> <ref name="BibliographicItem"/> </define> <define name="status"> + <a:documentation>The publication or preparation status of a document</a:documentation> <element name="status"> - <ref name="stage"/> + <ref name="stage"> + <a:documentation>The stage of the document status, e.g. "Published", "Unpublished", "Committee Draft", "Preprint"</a:documentation> + </ref> <optional> - <ref name="substage"/> + <ref name="substage"> + <a:documentation>The substage of the document status. These are used particularly in Standards Defining Organizations</a:documentation> + </ref> </optional> <optional> - <ref name="iteration"/> + <ref name="iteration"> + <a:documentation>The iteration of the given status that the document is currently in (e.g. "3" for a third draft)</a:documentation> + </ref> </optional> </element> </define> <define name="stage"> + <a:documentation>The stage of the document status, e.g. "Published", "Unpublished", "Committee Draft", "Preprint"</a:documentation> <element name="stage"> <optional> - <attribute name="abbreviation"/> + <attribute name="abbreviation"> + <a:documentation>A canonical abbreviation of the document stage</a:documentation> + </attribute> </optional> - <text/> + <text> + <a:documentation>The name of the document stage</a:documentation> + </text> </element> </define> <define name="substage"> + <a:documentation>The substage of the document status. These are used particularly in Standards Defining Organizations</a:documentation> <element name="substage"> <optional> - <attribute name="abbreviation"/> + <attribute name="abbreviation"> + <a:documentation>A canonical abbreviation of the document substage</a:documentation> + </attribute> </optional> - <text/> + <text> + <a:documentation>The name of the documen substage</a:documentation> + </text> </element> </define> <define name="iteration"> @@ -71,87 +89,84 @@ </define> <define name="language"> <element name="language"> - <text/> + <ref name="LanguageType"/> </element> </define> <define name="locale"> - <a:documentation>ISO-639</a:documentation> <element name="locale"> - <text/> + <ref name="LocaleType"/> </element> </define> <define name="script"> - <a:documentation>ISO-3166</a:documentation> <element name="script"> - <text/> + <ref name="ScriptType"/> </element> </define> <define name="edition"> - <a:documentation>ISO-15924: Latn</a:documentation> + <a:documentation>Edition of a bibliographic item</a:documentation> <element name="edition"> <optional> - <attribute name="number"/> + <attribute name="number"> + <a:documentation>Number of edition. +NOTE: The number attribute can be used to represent the numeric equivalent of the edition string</a:documentation> + </attribute> </optional> - <text/> + <text> + <a:documentation>Formatted, human-readable edition string</a:documentation> + </text> </element> </define> - <define name="LocalizedString1"> + <define name="LocalizedStringAttributes"> + <a:documentation>multiple values are comma-delimited</a:documentation> <optional> - <!-- multiple languages and scripts possible: comma delimit them if so --> - <attribute name="language"/> + <attribute name="language"> + <ref name="LanguageType"/> + </attribute> </optional> <optional> - <attribute name="locale"/> + <attribute name="locale"> + <ref name="LocaleType"/> + </attribute> </optional> <optional> - <attribute name="script"/> + <attribute name="script"> + <ref name="ScriptType"/> + </attribute> </optional> - <text/> </define> <define name="LocalizedString"> - <choice> - <ref name="LocalizedString1"/> - <oneOrMore> - <element name="variant"> - <ref name="LocalizedString1"/> - </element> - </oneOrMore> - </choice> + <ref name="LocalizedStringAttributes"/> + <text/> </define> + <!-- + LocalizedString = + LocalizedStringAttributes, + text + + LocalizedString = + LocalizedString1 | + element variant { LocalizedString1 }+ + --> + <define name="LocalizedMarkedUpString"> + <ref name="LocalizedStringAttributes"/> + <oneOrMore> + <ref name="PureTextElement"/> + </oneOrMore> + </define> + <!-- + LocalizedMarkedUpString = + LocalizedMarkedUpString1 | + Variants of the string, with the same content, but in different language, script, or format + element variant { LocalizedMarkedUpString1 }+ + --> <!-- Unlike UML, change type to format: type is overloaded Would be need if plain were default value and could omit the attribute Added LocalizedStringOrXsAny --> - <define name="FormattedString"> - <optional> - <!-- attribute format { ( "plain" | "html" | "docbook" | "tei" | "asciidoc" | "markdown" ) }?, --> - <attribute name="format"> - <choice> - <value>text/plain</value> - <value>text/html</value> - <value>application/docbook+xml</value> - <value>application/tei+xml</value> - <value>text/x-asciidoc</value> - <value>text/markdown</value> - <value>application/x-metanorma+xml</value> - <text/> - </choice> - </attribute> - </optional> - <ref name="LocalizedStringOrXsAny"/> - </define> - <define name="LocalizedStringOrXsAny1"> - <optional> - <!-- multiple languages and scripts possible: comma delimit them if so --> - <attribute name="language"/> - </optional> - <optional> - <attribute name="locale"/> - </optional> - <optional> - <attribute name="script"/> - </optional> + <!-- LocalizedStringOrXsAny1 = --> + <define name="LocalizedStringOrXsAny"> + <ref name="LocalizedStringAttributes"/> <oneOrMore> <choice> <text/> @@ -159,27 +174,43 @@ </choice> </oneOrMore> </define> - <define name="LocalizedStringOrXsAny"> - <choice> - <ref name="LocalizedStringOrXsAny1"/> - <oneOrMore> - <element name="variant"> - <ref name="LocalizedStringOrXsAny1"/> - </element> - </oneOrMore> - </choice> - </define> + <!-- + LocalizedStringOrXsAny = + LocalizedStringOrXsAny1 | + element variant { LocalizedStringOrXsAny1 }+ + --> <define name="contributor"> + <a:documentation>String which is formatted according to conventions specified in a named MIME type </a:documentation> + <!-- FormattedString = --> + <a:documentation>MIME type for string (defailts to text/plain). +NOTE: `docbook`, `AsciiDoc`, `Metanorma` are not registered IANA Media Types</a:documentation> + <!-- + attribute format { + "text/plain" | "text/html" | "application/docbook+xml" | + "application/tei+xml" | "text/x-asciidoc" | "text/markdown" | "application/x-metanorma+xml" | text + }?, + --> + <a:documentation>String</a:documentation> + <!-- LocalizedStringOrXsAny --> + <a:documentation>Description of a contributor to the production of the bibliographic item</a:documentation> <element name="contributor"> <oneOrMore> - <ref name="role"/> + <ref name="role"> + <a:documentation>A description of the role of the contributor in the production of the bibliographic item</a:documentation> + </ref> </oneOrMore> - <ref name="ContributorInfo"/> + <ref name="ContributorInfo"> + <a:documentation>The contributor involved in the production of the bibliographic item. +May be either a person or an organization</a:documentation> + </ref> </element> </define> <define name="role"> + <a:documentation>A description of the role of the contributor in the production of a bibliographic item</a:documentation> <element name="role"> <attribute name="type"> + <a:documentation>The broad class of role of the contributor. Mandatory in order to enforce orderly management of contributors. +Detailed in https://www.relaton.org/model/creator/</a:documentation> <choice> <value>author</value> <value>performer</value> @@ -196,7 +227,9 @@ </choice> </attribute> <zeroOrMore> - <ref name="roledescription"/> + <ref name="roledescription"> + <a:documentation>A more detailed description of the role of the contributor</a:documentation> + </ref> </zeroOrMore> </element> </define> @@ -208,29 +241,41 @@ </define> <define name="roledescription"> <element name="description"> - <ref name="FormattedString"/> + <ref name="LocalizedMarkedUpString"/> </element> </define> <define name="person"> + <a:documentation>Person associated with a bibliographic item</a:documentation> <element name="person"> <optional> - <ref name="fullname"/> + <ref name="fullname"> + <a:documentation>The name of the person</a:documentation> + </ref> </optional> <zeroOrMore> - <ref name="credential"/> + <ref name="credential"> + <a:documentation>Credentials given for the person postnominally, e.g. "PhD"</a:documentation> + </ref> </zeroOrMore> <zeroOrMore> - <ref name="affiliation"/> + <ref name="affiliation"> + <a:documentation>The affiliation of the person within an organization</a:documentation> + </ref> </zeroOrMore> <zeroOrMore> - <ref name="person-identifier"/> - </zeroOrMore> - <zeroOrMore> - <ref name="contact"/> + <ref name="person-identifier"> + <a:documentation>An identifier of the person according to an international identifier scheme</a:documentation> + </ref> </zeroOrMore> + <optional> + <ref name="contact"> + <a:documentation>Contact information for the person, including URI, address, phone number, and email</a:documentation> + </ref> + </optional> </element> </define> <define name="fullname"> + <a:documentation>The name of a person</a:documentation> <element name="name"> <ref name="FullNameType"/> </element> @@ -242,31 +287,56 @@ </define> <define name="FullNameType"> <optional> - <ref name="name_abbreviation"/> + <ref name="name_abbreviation"> + <a:documentation>The initials of the person, used as an abbreviation for the person, and including the +surname. Can be used instead of the complete name. Distinct from formatted-initials, +which are the initials only of the forenames of the person</a:documentation> + </ref> </optional> - <choice> - <group> - <zeroOrMore> - <ref name="prefix"/> - </zeroOrMore> - <zeroOrMore> - <ref name="forename"/> - </zeroOrMore> - <optional> - <ref name="formatted-initials"/> - </optional> - <ref name="surname"/> - <zeroOrMore> - <ref name="addition"/> - </zeroOrMore> - </group> - <ref name="completeName"/> - </choice> + <group> + <zeroOrMore> + <ref name="prefix"> + <a:documentation>A prefixed addition to the name of the person, such as "Dr"</a:documentation> + </ref> + </zeroOrMore> + <zeroOrMore> + <ref name="forename"> + <a:documentation>A forename or given name of the person. Includes middle names</a:documentation> + </ref> + </zeroOrMore> + <optional> + <ref name="formatted-initials"> + <a:documentation>The initials of the person, as a formatted string, including punctuation, dropping +punctuation as desired, and including hyphens where necessary. For example, +the initial set for Jean-Paul would be J, P; the formatted initials would be "J.-P." +or "J-P.". Can be used instead of forenames</a:documentation> + </ref> + </optional> + <optional> + <ref name="surname"> + <a:documentation>The surname, family name, or equivalent of the person</a:documentation> + </ref> + </optional> + <zeroOrMore> + <ref name="addition"> + <a:documentation>A suffixed addition to the name of the person, such as "Jr"</a:documentation> + </ref> + </zeroOrMore> + <optional> + <ref name="completeName"> + <a:documentation>A preformatted version of the name of the person, not broken down into its component parts</a:documentation> + </ref> + </optional> + </group> <zeroOrMore> - <ref name="biblionote"/> + <ref name="biblionote"> + <a:documentation>An additional note about the name of the person</a:documentation> + </ref> </zeroOrMore> <zeroOrMore> - <ref name="variantname"/> + <ref name="variantname"> + <a:documentation>A variant name of the person</a:documentation> + </ref> </zeroOrMore> </define> <define name="name_abbreviation"> @@ -295,11 +365,19 @@ </element> </define> <define name="forename"> + <a:documentation>A forename of a person</a:documentation> <element name="forename"> <optional> - <attribute name="initial"/> + <attribute name="initial"> + <a:documentation>An individual initial of the person, corresponding to the given forename. +Does not include final punctuation, but can include hyphens. +Can be used instead of forenames, if formatted-initials are not provided +(in which case each initial will be punctuated following local practice).</a:documentation> + </attribute> </optional> - <ref name="LocalizedString"/> + <ref name="LocalizedString"> + <a:documentation>A forename or given name of the person. Includes middle names</a:documentation> + </ref> </element> </define> <define name="completeName"> @@ -308,21 +386,34 @@ </element> </define> <define name="variantname"> + <a:documentation>A variant name of a person</a:documentation> <element name="variant"> - <attribute name="type"/> - <ref name="FullNameType"/> + <attribute name="type"> + <a:documentation>The type of variant name for the person. Examples include pseudonyms; user names (online); +real names (if the person is named with a pseudonym or user name); previous legal names</a:documentation> + </attribute> + <ref name="FullNameType"> + <a:documentation>The variant name itself</a:documentation> + </ref> </element> </define> <define name="affiliation"> + <a:documentation>The affiliation of a person with an organization</a:documentation> <element name="affiliation"> <optional> - <ref name="affiliationname"/> + <ref name="affiliationname"> + <a:documentation>The name of the affiliation of the person with the organization; typically a position title</a:documentation> + </ref> </optional> <zeroOrMore> - <ref name="affiliationdescription"/> + <ref name="affiliationdescription"> + <a:documentation>A more detailed description of the affiliation of the person</a:documentation> + </ref> </zeroOrMore> <optional> - <ref name="organization"/> + <ref name="organization"> + <a:documentation>The organization with which the person is affiliated</a:documentation> + </ref> </optional> </element> </define> @@ -333,140 +424,188 @@ </define> <define name="affiliationdescription"> <element name="description"> - <ref name="FormattedString"/> + <ref name="LocalizedMarkedUpString"/> </element> </define> <define name="organization"> + <a:documentation>Organization associated with a bibliographic item</a:documentation> <element name="organization"> - <oneOrMore> - <ref name="orgname"/> - </oneOrMore> - <zeroOrMore> - <ref name="subdivision"/> - </zeroOrMore> - <optional> - <ref name="abbreviation"/> - </optional> - <zeroOrMore> - <ref name="uri"/> - </zeroOrMore> - <zeroOrMore> - <ref name="org-identifier"/> - </zeroOrMore> - <zeroOrMore> - <ref name="contact"/> - </zeroOrMore> - <optional> - <ref name="logo"/> - </optional> + <ref name="OrganizationType"/> </element> </define> + <define name="OrganizationType"> + <oneOrMore> + <ref name="orgname"> + <a:documentation>The name of the organization</a:documentation> + </ref> + </oneOrMore> + <zeroOrMore> + <ref name="subdivision"> + <a:documentation>The subdivision of the organization directly involved with the production of the bibliographic item</a:documentation> + </ref> + </zeroOrMore> + <optional> + <ref name="abbreviation"> + <a:documentation>Abbreviation under which the organization is known</a:documentation> + </ref> + </optional> + <zeroOrMore> + <ref name="org-identifier"> + <a:documentation>An identifier of the organization according to an international identifier scheme</a:documentation> + </ref> + </zeroOrMore> + <optional> + <ref name="contact"> + <a:documentation>Contact information for the organization, including address, phone number, and email</a:documentation> + </ref> + </optional> + <optional> + <ref name="logo"> + <a:documentation>A logo for the organization</a:documentation> + </ref> + </optional> + </define> <define name="orgname"> <element name="name"> - <choice> - <ref name="LocalizedString"/> - <ref name="NameWithVariants"/> - </choice> + <optional> + <attribute name="type"> + <a:documentation>Type of organisation name, to differentiate variant names</a:documentation> + </attribute> + </optional> + <ref name="LocalizedString"/> </element> </define> <define name="subdivision"> + <a:documentation>Subdivision of organization associated with a bibliographic item</a:documentation> <element name="subdivision"> - <choice> - <ref name="LocalizedString"/> - <ref name="NameWithVariants"/> - </choice> + <optional> + <attribute name="type"> + <a:documentation>The type of subdivision</a:documentation> + </attribute> + </optional> + <ref name="OrganizationType"> + <a:documentation>The subdivision, modelled recursively as an organization</a:documentation> + </ref> </element> </define> <define name="logo"> <element name="logo"> - <ref name="image"/> + <ref name="image-no-id"/> </element> </define> <define name="depiction"> + <a:documentation>Depiction of the bibliographic item</a:documentation> <element name="depiction"> <optional> - <attribute name="scope"/> + <attribute name="scope"> + <a:documentation>Description of what is being depicted</a:documentation> + </attribute> </optional> <zeroOrMore> - <ref name="image"/> + <ref name="image-no-id"> + <a:documentation>A visual depiction of the bibliographic item</a:documentation> + </ref> </zeroOrMore> </element> </define> - <define name="NameWithVariants"> - <element name="primary"> - <ref name="LocalizedString"/> - </element> - <zeroOrMore> - <element name="variant"> - <ref name="NameWithVariants1"/> - </element> - </zeroOrMore> - </define> - <define name="NameWithVariants1"> - <attribute name="type"/> - <element name="primary"> - <ref name="LocalizedString"/> - </element> - <zeroOrMore> - <element name="variant"> - <ref name="NameWithVariants1"/> - </element> - </zeroOrMore> - </define> + <!-- + NameWithVariants = + element primary { LocalizedString }, + element variant { NameWithVariants1 }* + + NameWithVariants1 = + attribute type { text }, + element primary { LocalizedString }, + element variant { NameWithVariants1 }* + --> <define name="abbreviation"> <element name="abbreviation"> <ref name="LocalizedString"/> </element> </define> <define name="uri"> + <a:documentation>URI associated with a type</a:documentation> <element name="uri"> <optional> - <attribute name="type"/> + <attribute name="type"> + <a:documentation>The types of URI are open-ended, but include the IANA link relations specified in RFC 8288</a:documentation> + </attribute> </optional> - <data type="anyURI"/> + <ref name="LocalizedStringAttributes"/> + <data type="anyURI"> + <a:documentation>URI content</a:documentation> + </data> </element> </define> <!-- TODO may change --> <define name="contact"> - <choice> + <a:documentation>Contact information for a person or organization</a:documentation> + <zeroOrMore> <ref name="address"/> + </zeroOrMore> + <zeroOrMore> <ref name="phone"/> + </zeroOrMore> + <zeroOrMore> <ref name="email"/> + </zeroOrMore> + <zeroOrMore> <ref name="uri"/> - </choice> + </zeroOrMore> </define> <define name="phone"> + <a:documentation>The phone number associated with a person or organization</a:documentation> <element name="phone"> <optional> - <attribute name="type"/> + <attribute name="type"> + <a:documentation>The type of phone number; can include "Fax" and "Mobile"</a:documentation> + </attribute> </optional> - <text/> + <text> + <a:documentation>The phone number itself</a:documentation> + </text> </element> </define> <define name="email"> + <a:documentation>Email address</a:documentation> <element name="email"> <text/> </element> </define> <define name="address"> + <a:documentation>An address for a person or organization</a:documentation> <element name="address"> - <choice> + <zeroOrMore> <!-- iso191606 TODO --> - <group> - <zeroOrMore> - <ref name="street"/> - </zeroOrMore> - <ref name="city"/> - <optional> - <ref name="state"/> - </optional> - <ref name="country"/> - <optional> - <ref name="postcode"/> - </optional> - </group> - <ref name="formattedAddress"/> - </choice> + <ref name="street"> + <a:documentation>The street and street number or equivalent in the address, as one or more lines of text</a:documentation> + </ref> + </zeroOrMore> + <optional> + <ref name="city"> + <a:documentation>The settlement or municipality in the address</a:documentation> + </ref> + </optional> + <optional> + <ref name="state"> + <a:documentation>The region of the country in the address</a:documentation> + </ref> + </optional> + <optional> + <ref name="country"> + <a:documentation>The country in the address</a:documentation> + </ref> + </optional> + <optional> + <ref name="postcode"> + <a:documentation>The postal code or equivalent in the address</a:documentation> + </ref> + </optional> + <optional> + <ref name="formattedAddress"> + <a:documentation>Preformatted version of the address, not decomposed into its component parts</a:documentation> + </ref> + </optional> </element> </define> <define name="street"> @@ -496,48 +635,77 @@ </define> <define name="formattedAddress"> <element name="formattedAddress"> - <text/> + <oneOrMore> + <choice> + <text/> + <ref name="br"/> + </choice> + </oneOrMore> </element> </define> <define name="person-identifier"> + <a:documentation>An identifier of a person according to an international identifier scheme</a:documentation> <element name="identifier"> <attribute name="type"> - <choice> - <value>isni</value> - <value>orcid</value> - <value>uri</value> - </choice> + <a:documentation>The international identifier scheme for the identifier of the person. +Examples include "isni", "orcid", "uri"</a:documentation> </attribute> - <text/> + <text> + <a:documentation>The identifier value</a:documentation> + </text> </element> </define> <define name="org-identifier"> + <a:documentation>An identifier of an organization according to an international identifier scheme</a:documentation> <element name="identifier"> - <attribute name="type"> - <data type="string" datatypeLibrary=""/> - </attribute> - <text/> + <optional> + <attribute name="type"> + <a:documentation>The international identifier scheme for the identifier of the organization. +Examples include GRID, LEI, CrossRef, and Ringgold</a:documentation> + </attribute> + </optional> + <text> + <a:documentation>The identifier value</a:documentation> + </text> </element> </define> <define name="citation"> + <a:documentation>Representation of a citation of a bibliographic item, typically within a document</a:documentation> <element name="citation"> <ref name="CitationType"/> </element> </define> <define name="CitationType"> <attribute name="bibitemid"> + <a:documentation>Bibliographic item that the citation applies to, referenced as the anchor of a bibliographic description</a:documentation> <data type="IDREF"/> </attribute> <choice> <zeroOrMore> - <ref name="locality"/> + <ref name="locality"> + <a:documentation>Describes the location of the cited information resource within the subject of the bibliographic item. +Multiple ``bibLocality``s are interpreted as discontinuous references.</a:documentation> + </ref> </zeroOrMore> <zeroOrMore> - <ref name="localityStack"/> + <ref name="localityStack"> + <a:documentation>Describes the location of the cited information resource within the subject of the bibliographic item in a multi-level manner. +For example, the hierarchical specification "Part IV, Chapter 3, Paragraphs 22-24" +is represented as a single `bibLocalityStack`, composed of those three localities +(as opposed to three `bibLocality` references, which would be treated as three discontinuous references). +Multiple ``bibLocalityStack``s are themselves interpreted as discontinuous references</a:documentation> + </ref> </zeroOrMore> </choice> <optional> - <ref name="date"/> + <ref name="date"> + <a:documentation>Date of the citation, typically date of publication. +A combination of the date time elements year, month and day should be specified. +Specification of month and day are optional. +This date is not intended for disambiguation, since `bibitemid` +already identifies the source unambiguously; it is added for ease of processing, in case author-date +citations cannot straightforwardly extract the date from the bibliographic source</a:documentation> + </ref> </optional> </define> <define name="date"> @@ -546,14 +714,20 @@ </element> </define> <define name="locality"> + <a:documentation>The extent or location of a bibliographic item being referred to. +A sequence of locality elements is meant to indicate hierarchical ordering, from greater to smaller. +e.g. Chapter, then page, then paragraph. +A discontinuous range can be represented by using two adjacent localities with the same type</a:documentation> <element name="locality"> <ref name="BibItemLocality"/> </element> </define> <define name="localityStack"> + <a:documentation>Hierarchical arrangement of bibliographic localities, to refer to a single span of text in a bibliographic item</a:documentation> <element name="localityStack"> <optional> <attribute name="connective"> + <a:documentation>Logical connective linking localities. If not supplied, "and" is understood</a:documentation> <choice> <value>and</value> <value>or</value> @@ -564,16 +738,23 @@ </attribute> </optional> <zeroOrMore> - <ref name="locality"/> + <ref name="locality"> + <a:documentation>Component bibliographic localities which group together to designate a single span of text. +Earlier localities are assumed to include later localities, and be of different types; +e.g. "Chapter 7, paragraph 9–11"</a:documentation> + </ref> </zeroOrMore> </element> </define> <define name="sourceLocality"> + <a:documentation>The extent or location of a source bibliographic item being related to a target bibliographic item</a:documentation> <element name="sourceLocality"> <ref name="BibItemLocality"/> </element> </define> <define name="sourceLocalityStack"> + <a:documentation>Hierarchical arrangement of bibliographic localities, to refer to a single span of text in a source bibliographic item, +being related to a target bibliographic item</a:documentation> <element name="sourceLocalityStack"> <optional> <attribute name="connective"> @@ -593,16 +774,30 @@ </define> <define name="BibItemLocality"> <attribute name="type"> + <a:documentation>The type of extent of a locality (e.g. section, clause, page)</a:documentation> <ref name="LocalityType"/> </attribute> <optional> - <ref name="referenceFrom"/> + <ref name="referenceFrom"> + <a:documentation>The starting value of the extent, or point location</a:documentation> + </ref> </optional> <optional> - <ref name="referenceTo"/> + <ref name="referenceTo"> + <a:documentation>The end value of the extent as a range, if applicable</a:documentation> + </ref> </optional> </define> <define name="LocalityType"> + <a:documentation>Type of indicator of a location or extent within a bibliographic item. +When the value `whole` or `title` is used, the corresponding `BibItemLocality` +attribute `identifier` should be empty +`whole` refers to the entire document. +`list` is used for ordered lists in standards documents +`time` is used for timestamps in audio and visual media +`anchor` is used for locations within web pages +`line` is a line number, dependent on printed form of document +`locality:...` is an extension point: it allows a free-form text string that is human-readable</a:documentation> <data type="string"> <param name="pattern">section|clause|part|paragraph|chapter|page|title|line|whole|table|annex|figure|note|list|example|volume|issue|time|anchor|locality:[a-zA-Z0-9_]+</param> </data> @@ -619,6 +814,7 @@ </define> <!-- unlike UML, has id attribute; that results from including bibitem in a docmodel --> <define name="bibitem"> + <a:documentation>Description of a bibliographic item</a:documentation> <element name="bibitem"> <attribute name="id"> <data type="ID"/> @@ -627,162 +823,312 @@ </element> </define> <define name="bibitem_no_id"> + <a:documentation>Description of a bibliographic item: no ID attribute (for use in Relaton, metadata)</a:documentation> <element name="bibitem"> <ref name="BibliographicItem"/> </element> </define> <define name="relaton_collection"> + <a:documentation>Used to present a group of bibliographic items as a single group; +e.g. when summarising the collection of standards created by a standards body. +A collection may be used for bibliographic exchange but is typically not necesary for citation purposes</a:documentation> <element name="relaton-collection"> <optional> - <attribute name="type"/> + <attribute name="type"> + <a:documentation>The type of grouping of bibliographic items</a:documentation> + </attribute> </optional> - <ref name="btitle"/> + <ref name="btitle"> + <a:documentation>The title given to the grouping of bibliographic items</a:documentation> + </ref> <zeroOrMore> - <ref name="contributor"/> + <ref name="contributor"> + <a:documentation>Contributors to the production of the bibliographic items as a grouping, +with corporate responsibility for all the items in the group +(e.g. as compilers of a collection or corporate authors)</a:documentation> + </ref> </zeroOrMore> <zeroOrMore> - <ref name="docrelation"/> + <ref name="docrelation"> + <a:documentation>The individual items which constitute the group, expressed as relations to the +document group. The `type` attribute of each relation is expected to be either `includes` or `hasPart`, +depending on whether the items exist as independent documents, or are parts of a multi-part document</a:documentation> + </ref> </zeroOrMore> </element> </define> <define name="BibItemType" combine="choice"> + <a:documentation>Type of bibliographic item. +The value list complies with the types provided in ISO 690:2021. +NOTE: These values represent a strict superset to BibTeX +publication types, and therefore any BibTeX type value can be +mapped to these values. Some values here do not have a corresponding +entry in BibTeX, for instance, "standard" and "website".</a:documentation> <choice> <value>article</value> + <a:documentation>An article from a journal or magazine</a:documentation> <value>book</value> + <a:documentation>A monograph</a:documentation> <value>booklet</value> + <a:documentation>A booklet or pamphlet. The distinction between book and booklet is not made frequently</a:documentation> <value>manual</value> + <a:documentation>A manual</a:documentation> <value>proceedings</value> + <a:documentation>A conference proceedings</a:documentation> <value>presentation</value> + <a:documentation>A presentation given in a formal meeting</a:documentation> <value>thesis</value> + <a:documentation>A dissertation given in an academic institution, as a summation of research</a:documentation> <value>techreport</value> + <a:documentation>A technical report</a:documentation> <value>standard</value> + <a:documentation>A standard, a document issued by a Standards Defining Organization</a:documentation> <value>unpublished</value> + <a:documentation>An intellectual creation which has not been published, e.g. a manuscript. +NOTE: Properly this does not represent a distinct bibliographic type, and it +should be avoided in favour of using the `status` element of `BibliographicItem`</a:documentation> <value>map</value> + <a:documentation>A map or other cartographic resource</a:documentation> <value>electronic resource</value> + <a:documentation>A resource avaiulable in digital form +NOTE: The overloaded type `electronicResource` should be avoided where possible, particularly if the +resource corresponds closely to a paper bibliographic type, such as `book` or `article`. +The distinction between offline and online resources should be made through `medium` (electronic vs physical). +Specialisations of `electronicResource` include `dataset`, `webResource`, `website`, +`socialMedia`, and `software`.</a:documentation> <value>audiovisual</value> + <a:documentation>An audiovisual resource. Is a superclass of other types such as `video` and `music`</a:documentation> <value>film</value> + <a:documentation>A film</a:documentation> <value>video</value> + <a:documentation>A video</a:documentation> <value>broadcast</value> + <a:documentation>A broadcast made through mass media, including radio and television</a:documentation> <value>software</value> + <a:documentation>Computer executable code, not itself human-readable text (though it may generate such text)</a:documentation> <value>graphic_work</value> + <a:documentation>A graphic work, a work with two-dimensional or three-dimensional content</a:documentation> <value>music</value> + <a:documentation>A musical work. Includes both notated music and music performances: +The two are differentiated through `BibliographicItem/medium/content` as "notated music" vs "performed music"</a:documentation> <value>patent</value> + <a:documentation>A patent</a:documentation> <value>inbook</value> + <a:documentation>A (typically untitled) part of a book. May be a chapter (or section, etc.) and/or a range of pages</a:documentation> <value>incollection</value> + <a:documentation>A part of a book having its own title, and typically having distinct authorship</a:documentation> <value>inproceedings</value> + <a:documentation>An article in a conference proceedings</a:documentation> <value>journal</value> + <a:documentation>A journal or periodical publication</a:documentation> <value>website</value> + <a:documentation>A collection of web resources, presented under the same URL domain and under the same (individual or corporate) authorship</a:documentation> <value>webresource</value> + <a:documentation>A human-readable or consumable web resource, a single item accessible online via a web browser, +which is not composed of components all of which can be accessed in the same way. +Includes media files, as well as individual web pages</a:documentation> <value>dataset</value> + <a:documentation>An electronic dataset, a collection of data that is not meant to be human-readable, and which is typically only machine readable</a:documentation> <value>archival</value> + <a:documentation>A instance of a resource curated and preserved in an archive, which mediates any access to it. +Typically it is physical, unique, and unpublished. + NOTE: The content of the resource may be published separately, + but that makes it a distinct bibliographic item, as access to it is no longer mediated through the archive</a:documentation> <value>social_media</value> + <a:documentation>One or more resources within a collection that is typically collectively authored by member users. +Includes blog posts, forum posts, social media posts, tweets. Is usually a `webResource`, +but not always (e.g. blogs on WeChat are only accessible within the WeChat app.)</a:documentation> <value>alert</value> + <a:documentation>A single communication intended for multiple persons, and publicly accessible. +May be electronic (e.g. Facebook status update) or voice (e.g. evacuation alert), but is typically not print</a:documentation> <value>message</value> + <a:documentation>A single communication intended for a restricted number of authorised persons (typically one). +May be electronic (e.g. Twitter direct message, email) or voice (e.g. a remark made to someone, +typically cited as "personal communication")</a:documentation> <value>conversation</value> + <a:documentation>An exchange of messages between two or more persons. May be electronic (e.g. web chat) or voice (e.g. phone call)</a:documentation> + <value>collection</value> + <a:documentation>A compound resource consisting of other resources, which are themselves presupposed to have their type specified..</a:documentation> <value>misc</value> + <a:documentation>Bibliographic type not adequately described in the foregoing</a:documentation> </choice> </define> <define name="BibliographicItem"> + <a:documentation>Description of a bibliographic resource</a:documentation> <optional> <attribute name="type"> + <a:documentation>The type of the bibliographic item</a:documentation> <ref name="BibItemType"/> </attribute> </optional> <optional> - <attribute name="schema-version"/> + <attribute name="schema-version"> + <a:documentation>The version of the Relaton schema that this description conforms to</a:documentation> + </attribute> </optional> <optional> - <ref name="fetched"/> + <ref name="fetched"> + <a:documentation>The date at which the bibliographic item was last updated</a:documentation> + </ref> </optional> <optional> - <ref name="formattedref"/> + <ref name="formattedref"> + <a:documentation>A pre-formatted version of the full bibliographic item reference, +rendered for human reading, and used to sidestep the rendering of the reference out of its component parts</a:documentation> + </ref> </optional> <oneOrMore> - <ref name="btitle"/> + <ref name="btitle"> + <a:documentation>The title(s) of the bibliographic item</a:documentation> + </ref> </oneOrMore> <zeroOrMore> - <ref name="bsource"/> + <ref name="bsource"> + <a:documentation>The URI(s) associated with the bibliographic item</a:documentation> + </ref> </zeroOrMore> <oneOrMore> - <ref name="docidentifier"/> + <ref name="docidentifier"> + <a:documentation>The identifier(s) of the bibliographic item in an international standard scheme</a:documentation> + </ref> </oneOrMore> <optional> - <ref name="docnumber"/> + <ref name="docnumber"> + <a:documentation>Unprefixed, preferably numeric version of an identifier of the bibliographic item, intended for sorting of bibliography</a:documentation> + </ref> </optional> <zeroOrMore> - <ref name="bdate"/> + <ref name="bdate"> + <a:documentation>One or more date-times associated with the production of or access to the bibliographic item</a:documentation> + </ref> </zeroOrMore> <zeroOrMore> - <ref name="contributor"/> + <ref name="contributor"> + <a:documentation>Contributors to the production of the bibliographic item</a:documentation> + </ref> </zeroOrMore> <optional> - <ref name="edition"/> + <ref name="edition"> + <a:documentation>The edition of the bibliographic item</a:documentation> + </ref> </optional> <zeroOrMore> - <ref name="version"/> + <ref name="version"> + <a:documentation>The version of the bibliographic item (within an edition). Can be used for drafts. +Can be more than one, in case of multiple versioning schemes</a:documentation> + </ref> </zeroOrMore> <zeroOrMore> - <ref name="biblionote"/> + <ref name="biblionote"> + <a:documentation>Note(s) associated with the bibliographic item</a:documentation> + </ref> </zeroOrMore> <zeroOrMore> - <ref name="language"/> + <ref name="language"> + <a:documentation>The language(s) in which the bibliographic item is expressed</a:documentation> + </ref> </zeroOrMore> <zeroOrMore> - <ref name="locale"/> + <ref name="locale"> + <a:documentation>The locale(s) in which the bibliographic item is expressed</a:documentation> + </ref> </zeroOrMore> <zeroOrMore> - <ref name="script"/> + <ref name="script"> + <a:documentation>The script(s) in which the bibliographic item is written</a:documentation> + </ref> </zeroOrMore> <zeroOrMore> - <ref name="bibabstract"/> + <ref name="bibabstract"> + <a:documentation>The abstract of the bibliographic item</a:documentation> + </ref> </zeroOrMore> <optional> - <ref name="status"/> + <ref name="status"> + <a:documentation>The publication or preparation status of the bibliographic item</a:documentation> + </ref> </optional> <zeroOrMore> - <ref name="copyright"/> + <ref name="copyright"> + <a:documentation>The copyright status of the bibliographic item</a:documentation> + </ref> </zeroOrMore> <zeroOrMore> - <ref name="docrelation"/> + <ref name="docrelation"> + <a:documentation>The relation(s) of the bibliographic item to other bibliographic items</a:documentation> + </ref> </zeroOrMore> <zeroOrMore> - <ref name="series"/> + <ref name="series"> + <a:documentation>The series of the bibliographic item</a:documentation> + </ref> </zeroOrMore> <optional> - <ref name="medium"/> + <ref name="medium"> + <a:documentation>The medium the subject is realized on. +Medium can be used to differentiate between "electronic" and "physical" manifestations of an information resource.</a:documentation> + </ref> </optional> <zeroOrMore> - <ref name="bplace"/> + <ref name="bplace"> + <a:documentation>The geographic location associated with the production of the bibliographic item</a:documentation> + </ref> </zeroOrMore> <zeroOrMore> - <ref name="bprice"/> + <ref name="bprice"> + <a:documentation>The price set on accessing the bibliographic item. +The price should be treated as nominal, rather than capturing all possible pricings at a given time</a:documentation> + </ref> </zeroOrMore> <zeroOrMore> - <ref name="extent"/> + <ref name="extent"> + <a:documentation>The extent of the bibliographic item, if reference is not being made to the entirety of the item described. +Repeats for different levels of granularity (e.g. volume number, page number), or for discontinuous ranges +(e.g. multiple page ranges, pages plus plates)</a:documentation> + </ref> </zeroOrMore> <optional> - <ref name="bibliographic_size"/> + <ref name="bibliographic_size"> + <a:documentation>The bibliographic size of the bibliographic item, measured in the same units as extent (i.e. pages, volumes, +megabytes, hours, rather than cm^2.) Distinct from the physical size of the bibliographic item, captured in medium/size</a:documentation> + </ref> </optional> <zeroOrMore> - <ref name="accesslocation"/> + <ref name="accesslocation"> + <a:documentation>The location where the bibliographic item may be accessed. +Used for archival resources. Also used for pathways to access digital resources, where a URI is not practical</a:documentation> + </ref> </zeroOrMore> <zeroOrMore> - <ref name="license"/> + <ref name="license"> + <a:documentation>A license under which the bibliographic item has been issued. +NOTE: This should preferably be encoded as a URI or short identifier, rather than descriptive text</a:documentation> + </ref> </zeroOrMore> <zeroOrMore> - <ref name="bclassification"/> + <ref name="bclassification"> + <a:documentation>The classification of the bibliographic item according to a standard classification scheme</a:documentation> + </ref> </zeroOrMore> <zeroOrMore> - <ref name="bkeyword"/> + <ref name="bkeyword"> + <a:documentation>Keyword(s) for the bibliographic item</a:documentation> + </ref> </zeroOrMore> <optional> - <ref name="validity"/> + <ref name="validity"> + <a:documentation>Information about how long the current description of the bibliographic item is valid for</a:documentation> + </ref> </optional> <optional> - <ref name="depiction"/> + <ref name="depiction"> + <a:documentation>Depiction of the bibliographic item, typically an image</a:documentation> + </ref> </optional> </define> <define name="ReducedBibliographicItem"> + <a:documentation>Reduced description of a bibliographic resource, without mandatory title and docidentifier, used for document relations +Refer to `BibliographicItem` for definitions</a:documentation> <optional> <attribute name="type"> <ref name="BibItemType"/> @@ -883,6 +1229,7 @@ </optional> </define> <define name="btitle"> + <a:documentation>A title of a bibliographic item, associated with a type of title</a:documentation> <element name="title"> <ref name="TypedTitleString"/> </element> @@ -894,7 +1241,9 @@ </define> <define name="formattedref"> <element name="formattedref"> - <ref name="FormattedString"/> + <oneOrMore> + <ref name="TextElement"/> + </oneOrMore> </element> </define> <define name="license"> @@ -908,140 +1257,205 @@ </element> </define> <define name="validity"> + <a:documentation>The time interval for which a bibliographic item is determined valid, and the associated revision date</a:documentation> <element name="validity"> <optional> - <ref name="validityBegins"/> + <ref name="validityBegins"> + <a:documentation>The date and time when this bibliographic item becomes valid</a:documentation> + </ref> </optional> <optional> - <ref name="validityEnds"/> + <ref name="validityEnds"> + <a:documentation>The date and time when this bibliographic item becomes invalid</a:documentation> + </ref> </optional> <optional> - <ref name="validityRevision"/> + <ref name="validityRevision"> + <a:documentation>The date and time of issuance of the version of the document +for which this claim of validity is made, if applicable</a:documentation> + </ref> </optional> </element> </define> <define name="validityBegins"> <element name="validityBegins"> - <ref name="ISO8601DateTime"/> + <ref name="ISO8601Date"/> </element> </define> <define name="validityEnds"> <element name="validityEnds"> - <ref name="ISO8601DateTime"/> + <ref name="ISO8601Date"/> </element> </define> <define name="validityRevision"> <element name="revision"> - <ref name="ISO8601DateTime"/> + <ref name="ISO8601Date"/> </element> </define> <define name="TypedTitleString"> <optional> - <attribute name="type"/> + <attribute name="type"> + <a:documentation>Type of title given to a bibliographic item. Indicative values include: +"alternative": alternate title for the item +"original": The original title of the item. Includes the source language title of a translated item +"unofficial": A title that has become prevalent but has never been the official or intended title of the item +"subtitle": Subsidiary title of the item +"main": The default title of the item, privileged in citation</a:documentation> + </attribute> </optional> - <ref name="FormattedString"/> + <optional> + <attribute name="format"> + <a:documentation>(legacy attribute) format; can have value text/plain</a:documentation> + </attribute> + </optional> + <ref name="LocalizedMarkedUpString"> + <a:documentation>Content of title</a:documentation> + </ref> </define> <!-- TitleType = ( "alternative" | "original" | "unofficial" | "subtitle" | "main" ) --> <define name="TypedUri"> + <a:documentation>URI with type</a:documentation> <optional> - <attribute name="type"/> - </optional> - <optional> - <attribute name="language"/> - </optional> - <optional> - <attribute name="locale"/> - </optional> - <optional> - <attribute name="script"/> + <attribute name="type"> + <a:documentation>Type of URI</a:documentation> + </attribute> </optional> + <ref name="LocalizedStringAttributes"/> <data type="anyURI"/> </define> <define name="DateType"> + <a:documentation>Type which allows date and time to be specified as either a Gregorian +date and time, as specified in ISO 8601, as text, or as both</a:documentation> <optional> - <attribute name="text"/> + <attribute name="text"> + <a:documentation>Date and time, as specified in text</a:documentation> + </attribute> </optional> <optional> - <ref name="ISO8601Date"/> + <group> + <a:documentation>Gregorian date and time, as specified in ISO 8601. Can be used +as a canonical interpretation of the date and time given in `text`</a:documentation> + <ref name="ISO8601Date"/> + </group> </optional> </define> <define name="BibliographicDateType"> + <a:documentation>Indicates type of date within a bibliographic lifecycle. +NOTE: Typically only the `published` date is of interest</a:documentation> <choice> <value>published</value> + <a:documentation>The date on which the document was published (distributed by the publisher)</a:documentation> <value>accessed</value> + <a:documentation>Date a document was last accessed by the compiler of the bibliographic record; routinely used for online publications. +NOTE: Unlike in ISO 690:2021, no distinction is made between +"viewed" and "accessed" based on whether the resource is human-readable or machine-readable.)</a:documentation> <value>created</value> + <a:documentation>The date on which the first version of the document was created</a:documentation> <value>implemented</value> + <a:documentation>The date on which the document takes effect. Applies to normative documents</a:documentation> <value>obsoleted</value> + <a:documentation>The date on which the document was obsoleted/</a:documentation> <value>confirmed</value> + <a:documentation>The date on which the document was reviewed and approved by the issuing authority</a:documentation> <value>updated</value> + <a:documentation>The date on which the current version of the document was updated</a:documentation> <value>corrected</value> + <a:documentation>The date on which the current version of the document was corrected, without that correction considered to amount to a full document update</a:documentation> <value>issued</value> + <a:documentation>The date on which the document was issued (authorised for publication by the issuing authority). +Is typically differentiated from `published` for normative documents, such as standards and legislation</a:documentation> <value>transmitted</value> + <a:documentation>The date on which the document was broadcast</a:documentation> <value>copied</value> + <a:documentation>The date on which the document physically copied, or recreated without any substantial change in content (allowing for change in medium)</a:documentation> <value>unchanged</value> + <a:documentation>The date on which the document was last renewed or reprinted without any changes in content</a:documentation> <value>circulated</value> + <a:documentation>The date on which the unpublished document was last circulated officially as a preprint. +For standards, this is associated with the latest transition to a formally defined preparation stage, +such as Working Draft or Committee Draft</a:documentation> <value>adapted</value> + <a:documentation>The date on which a document adapted for a new purpose or audience, with some change in content (includes translation)</a:documentation> <value>vote-started</value> + <a:documentation>The date on which a formal process for approval of a document was initiated. Typically applies to standards documents in draft</a:documentation> <value>vote-ended</value> + <a:documentation>The date on which a formal process for approval of a document was closed. Typically applies to standards documents in draft</a:documentation> <value>announced</value> + <a:documentation>The date on which the existence of a document is made public. +Applies whether the resource has already been created or not, and whether it is to be published or not</a:documentation> <value>stable-until</value> + <a:documentation>The document is guaranteed not to be changed or updated until this date</a:documentation> </choice> </define> <define name="bdate"> + <a:documentation>Significant date in the lifecycle of the bibliographic item, including its production and its access</a:documentation> <element name="date"> - <attribute name="type"> - <choice> - <ref name="BibliographicDateType"/> - <text/> - </choice> - </attribute> - <optional> - <attribute name="text"/> - </optional> + <ref name="bDateAttributes"/> <optional> <choice> <group> <element name="from"> + <a:documentation>The start of the date range described</a:documentation> <ref name="ISO8601Date"/> </element> <optional> <element name="to"> + <a:documentation>The end of the date range described</a:documentation> <ref name="ISO8601Date"/> </element> </optional> </group> <element name="on"> + <a:documentation>The point date described</a:documentation> <ref name="ISO8601Date"/> </element> </choice> </optional> </element> </define> + <define name="bDateAttributes"> + <attribute name="type"> + <a:documentation>The phase of the production of or access to a bibliographic item</a:documentation> + <choice> + <ref name="BibliographicDateType"/> + <text/> + </choice> + </attribute> + <optional> + <attribute name="text"> + <a:documentation>An optional textual description of the date, especially when a Gregorian date is not applicable</a:documentation> + </attribute> + </optional> + </define> <define name="docidentifier"> + <a:documentation>An identifier of a bibliographic item in an international standard scheme</a:documentation> <element name="docidentifier"> - <optional> - <attribute name="type"/> - </optional> - <optional> - <attribute name="scope"/> - </optional> - <optional> - <attribute name="primary"> - <data type="boolean"/> - </attribute> - </optional> - <optional> - <attribute name="language"/> - </optional> - <optional> - <attribute name="locale"/> - </optional> - <optional> - <attribute name="script"/> - </optional> - <text/> + <ref name="DocIdentifierType"/> </element> </define> + <define name="DocIdentifierType"> + <optional> + <attribute name="type"> + <a:documentation>The scheme or namespace of the identifier</a:documentation> + </attribute> + </optional> + <optional> + <attribute name="scope"> + <a:documentation>The scope of the identifier, in case the identifier does not apply to the document +but to a superset or subset of entities; or in case the identifier +is for a particular instance of the document, e.g. for a particular format or edition of the document</a:documentation> + </attribute> + </optional> + <optional> + <attribute name="primary"> + <a:documentation>This is a primary identifier for the item, to be used in citation</a:documentation> + <data type="boolean"/> + </attribute> + </optional> + <ref name="LocalizedMarkedUpString"> + <a:documentation>The identifier string</a:documentation> + </ref> + </define> <define name="docnumber"> <element name="docnumber"> <text/> @@ -1049,26 +1463,37 @@ </define> <define name="bclassification"> <element name="classification"> - <optional> - <attribute name="type"/> - </optional> - <text/> + <ref name="DocIdentifierType"/> </element> </define> <define name="bplace"> + <a:documentation>Place associated with the production of a bibliographic item</a:documentation> <element name="place"> - <choice> - <text/> - <group> - <ref name="bibliocity"/> - <zeroOrMore> - <ref name="biblioregion"/> - </zeroOrMore> - <zeroOrMore> - <ref name="bibliocountry"/> - </zeroOrMore> - </group> - </choice> + <optional> + <ref name="bibliocity"> + <a:documentation>City</a:documentation> + </ref> + </optional> + <zeroOrMore> + <ref name="biblioregion"> + <a:documentation>Region that city is located in, given for disambiguation purposes.</a:documentation> + </ref> + </zeroOrMore> + <zeroOrMore> + <ref name="bibliocountry"> + <a:documentation>Country that city is located in, given for disambiguation purposes.</a:documentation> + </ref> + </zeroOrMore> + <optional> + <ref name="formattedPlace"> + <a:documentation>Name of the place, not broken down semantically</a:documentation> + </ref> + </optional> + <optional> + <ref name="uri"> + <a:documentation>URI in a geographical registry identifying the place</a:documentation> + </ref> + </optional> </element> </define> <define name="bibliocity"> @@ -1076,6 +1501,11 @@ <text/> </element> </define> + <define name="formattedPlace"> + <element name="formattedPlace"> + <text/> + </element> + </define> <define name="biblioregion"> <element name="region"> <ref name="RegionType"/> @@ -1087,41 +1517,90 @@ </element> </define> <define name="RegionType"> + <a:documentation>Encoding of region in bibliographic `place`. ISO 3166 encoding is recommended</a:documentation> <optional> - <attribute name="iso"/> + <attribute name="iso"> + <a:documentation>ISO 3166 encoding</a:documentation> + </attribute> </optional> <optional> <attribute name="recommended"> + <a:documentation>Whether the region should be included in rendering of the place, for disambiguation</a:documentation> <data type="boolean"/> </attribute> </optional> + <optional> + <text> + <a:documentation>Name of the region</a:documentation> + </text> + </optional> + </define> + <define name="CurrencyType"> + <a:documentation>Code for currencies, taken from ISO 4217</a:documentation> <text/> </define> <define name="bprice"> + <a:documentation>The price set on accessing the bibliographic item</a:documentation> <element name="price"> - <attribute name="currency"/> - <text/> + <attribute name="currency"> + <a:documentation>The currency denomination for the price</a:documentation> + <ref name="CurrencyType"/> + </attribute> + <text> + <a:documentation>The currency amount for the price</a:documentation> + </text> </element> </define> <define name="medium"> + <a:documentation>Information about the medium and transmission of a bibliographic item</a:documentation> <element name="medium"> <optional> - <ref name="bcontent"/> + <ref name="bcontent"> + <a:documentation>The content type of the bibliographic item, reflecting the form of +communication with which it is expressed and perceived. For example, +`text`, `video`, `audio`.</a:documentation> + <a:documentation>NOTE: This field is intended to convey the +Content attribute of the MARC and Resource Description and Access +standards, although its values are not restricted to that +vocabulary; see http://www.loc.gov/standards/valuelist/rdacontent.html</a:documentation> + </ref> </optional> <optional> - <ref name="genre"/> + <ref name="genre"> + <a:documentation>The genre of the bibliographic item, as a classification of the +type of communication it represents that is more specific than `content` or `BibliographicItem/type`. +For example, "statistical dataset"</a:documentation> + </ref> </optional> <optional> - <ref name="form"/> + <ref name="form"> + <a:documentation>The media type of the bibliographic item, used to access the content +of the item, including file format for electronic media.</a:documentation> + <a:documentation>NOTE: This field is intended to convey the +Media attribute of the MARC and Resource Description and Access +standards, although its values are not restricted to that +vocabulary; see http://www.loc.gov/standards/valuelist/rdamedia.html +IANA Media Types are recommended for electronic resources</a:documentation> + </ref> </optional> <optional> - <ref name="carrier"/> + <ref name="carrier"> + <a:documentation>The storage medium of the physical representation of the bibliographic item.</a:documentation> + <a:documentation>NOTE: This field is intended to convey the +Carrier attribute of the MARC and Resource Description and Access +standards, although its values are not restricted to that +vocabulary; see https://www.loc.gov/standards/valuelist/rdacarrier.html</a:documentation> + </ref> </optional> <optional> - <ref name="size"/> + <ref name="size"> + <a:documentation>The size of the physical representation of the bibliographic item</a:documentation> + </ref> </optional> <optional> - <ref name="scale"/> + <ref name="scale"> + <a:documentation>The scale of the cartographic material in the bibliographic item</a:documentation> + </ref> </optional> </element> </define> @@ -1161,9 +1640,19 @@ </element> </define> <define name="sizevalue"> + <a:documentation>The size of a bibliographic item being referred to. +A sequence of sizes can be used to indicate different numberings, e.g. xii + 40 pp., +or different kinds of measures, e.g. pages + plates</a:documentation> <element name="value"> - <attribute name="type"/> - <text/> + <attribute name="type"> + <a:documentation>The type of size. Recommended values: page, volume, time (in ISO 8601 duration values), +data (including unit), value (free-form string)</a:documentation> + </attribute> + <optional> + <text> + <a:documentation>The quantity of the size</a:documentation> + </text> + </optional> </element> </define> <define name="bibliographic_size"> @@ -1186,46 +1675,80 @@ </element> </define> <define name="series"> + <a:documentation>Series to which a bibliographic item belongs. Series is to be understood broadly, +and it includes monograph series, journals, newspapers, and report series within +which the bibliographic item has appeared</a:documentation> <element name="series"> <optional> <attribute name="type"> + <a:documentation>The type of series description expressed in this container</a:documentation> <ref name="SeriesType"/> </attribute> </optional> <optional> - <ref name="formattedref"/> + <ref name="formattedref"> + <a:documentation>A pre-formatted version of the series description, incorporating +all needed disambiguating information in human-readable format</a:documentation> + </ref> </optional> - <ref name="btitle"/> + <oneOrMore> + <ref name="btitle"> + <a:documentation>The title of the series</a:documentation> + </ref> + </oneOrMore> <optional> - <ref name="bplace"/> + <ref name="bplace"> + <a:documentation>The place where the series is issued; used for disambiguation</a:documentation> + </ref> </optional> <optional> - <ref name="seriesorganization"/> + <ref name="seriesorganization"> + <a:documentation>The organization issuing the series; used for disambiguation</a:documentation> + </ref> </optional> <optional> - <ref name="abbreviation"/> + <ref name="abbreviation"> + <a:documentation>The abbreviation under which the series is known</a:documentation> + </ref> </optional> <optional> - <ref name="seriesfrom"/> + <ref name="seriesfrom"> + <a:documentation>The start of the date range when the series has been known under the given title</a:documentation> + </ref> </optional> <optional> - <ref name="seriesto"/> + <ref name="seriesto"> + <a:documentation>The end of the date range when the series has been known under the given title</a:documentation> + </ref> </optional> <optional> - <ref name="seriesnumber"/> + <ref name="seriesnumber"> + <a:documentation>The number of the bibliographic item within the series</a:documentation> + </ref> </optional> <optional> - <ref name="seriespartnumber"/> + <ref name="seriespartnumber"> + <a:documentation>The part-number of the bibliographic item within the series. For example, +if the series is a journal, the number is the volume number, and the partnumber is the issue number</a:documentation> + </ref> </optional> <optional> - <ref name="seriesrun"/> + <ref name="seriesrun"> + <a:documentation>An iteration of numbering of the series, if the series has restarted numbering +(as occurs in some journals); referred to as "series" in the context of journals. +For example, "n.s." (new series) or "2" indicates +that the `number` given for the series applies to the second iteration of numbering</a:documentation> + </ref> </optional> </element> </define> <define name="SeriesType"> + <a:documentation>The type of series description given</a:documentation> <choice> <value>main</value> + <a:documentation>Default type: The current, authoritative series description</a:documentation> <value>alt</value> + <a:documentation>An alternative, potentially historical series description</a:documentation> <text/> </choice> </define> @@ -1260,32 +1783,75 @@ </element> </define> <define name="biblionote"> + <a:documentation>A note associated with the bibliographic item</a:documentation> <element name="note"> <optional> - <attribute name="type"/> + <attribute name="type"> + <a:documentation>The class of the note associated with the bibliographic item. +May be used to differentiate rendering of notes in bibliographies</a:documentation> + </attribute> </optional> - <ref name="FormattedString"/> + <ref name="LocalizedStringAttributes"> + <a:documentation>The content of the note</a:documentation> + </ref> + <choice> + <oneOrMore> + <ref name="BasicBlockNoId"> + <a:documentation>Multiple blocks of content</a:documentation> + </ref> + </oneOrMore> + <oneOrMore> + <ref name="TextElement"> + <a:documentation>Single block of content</a:documentation> + </ref> + </oneOrMore> + </choice> </element> </define> <define name="bibabstract"> + <a:documentation>Abstract of bibliographic item</a:documentation> <element name="abstract"> - <ref name="FormattedString"/> + <ref name="LocalizedStringAttributes"/> + <choice> + <oneOrMore> + <ref name="BasicBlockNoId"> + <a:documentation>Multiple blocks of content</a:documentation> + </ref> + </oneOrMore> + <oneOrMore> + <ref name="TextElement"> + <a:documentation>Single block of content</a:documentation> + </ref> + </oneOrMore> + </choice> </element> </define> <define name="copyright"> + <a:documentation>The copyright status of a bibliographic item.</a:documentation> <element name="copyright"> - <ref name="from"/> + <ref name="from"> + <a:documentation>The copyright date of the bibliographic item</a:documentation> + </ref> <optional> - <ref name="to"/> + <ref name="to"> + <a:documentation>The date when the copyright of the bibliographic item expires</a:documentation> + </ref> </optional> <oneOrMore> - <ref name="owner"/> + <ref name="owner"> + <a:documentation>The copyright owner for the bibliographic item.</a:documentation> + </ref> </oneOrMore> <optional> - <ref name="copyright_scope"/> + <ref name="copyright_scope"> + <a:documentation>The extent of the bibliographic item, or contexts of use, for which this +assertion of copyright applies. For example, this description may only apply +to the preface of a book</a:documentation> + </ref> </optional> </element> </define> + <!-- TODO potentially should be locality | localityStack --> <define name="copyright_scope"> <element name="scope"> <text/> @@ -1302,11 +1868,14 @@ </element> </define> <define name="owner"> + <a:documentation>Copyright owner</a:documentation> <element name="owner"> <ref name="ContributorInfo"/> </element> </define> <define name="DocRelationType"> + <a:documentation>Type of the relationship between a main document (described in `BibliographicItem`) and a target document +Detailed in https://www.relaton.org/model/relations/</a:documentation> <choice> <value>includes</value> <value>includedIn</value> @@ -1338,6 +1907,10 @@ <value>hasAnnotation</value> <value>draftOf</value> <value>hasDraft</value> + <value>preliminaryDraftOf</value> + <value>hasPreliminaryDraft</value> + <value>revisionDraftOf</value> + <value>hasRevisionDraft</value> <value>editionOf</value> <value>hasEdition</value> <value>updates</value> @@ -1368,19 +1941,25 @@ </choice> </define> <define name="docrelation"> + <a:documentation>Relation between a bibliographic item and another bibliographic item</a:documentation> <element name="relation"> <attribute name="type"> + <a:documentation>The type of document relation described, using a controlled vocabulary</a:documentation> <ref name="DocRelationType"/> </attribute> <optional> <element name="description"> - <ref name="FormattedString"/> + <a:documentation>A more complete description of the type of document relation described</a:documentation> + <ref name="LocalizedMarkedUpString"/> </element> </optional> <element name="bibitem"> + <a:documentation>The target bibliographic item to which this bibliographic item is described as related to</a:documentation> <ref name="ReducedBibliographicItem"/> </element> <choice> + <a:documentation>The extent of the target bibliographic item which is related to this bibliographic item, +provided that it is not the entire bibliographic item that is so related</a:documentation> <zeroOrMore> <ref name="locality"/> </zeroOrMore> @@ -1389,6 +1968,8 @@ </zeroOrMore> </choice> <choice> + <a:documentation>The extent of this bibliographic item which is related to the target bibliographic item, +provided that it is not the entire bibliographic item that is so related</a:documentation> <zeroOrMore> <ref name="sourceLocality"/> </zeroOrMore> @@ -1399,12 +1980,17 @@ </element> </define> <define name="version"> + <a:documentation>A version of the bibliographic item (within an edition). Can be used for drafts</a:documentation> <element name="version"> <optional> - <ref name="revision-date"/> + <ref name="revision-date"> + <a:documentation>The date at which the current version of the bibliographic item was produced</a:documentation> + </ref> </optional> <optional> - <ref name="draft"/> + <ref name="draft"> + <a:documentation>The identifier for the current draft of the bibliographic item</a:documentation> + </ref> </optional> </element> </define> @@ -1423,46 +2009,63 @@ <text/> </element> </define> + <!-- + bkeyword = element keyword { + LocalizedString | + ( + element vocab { LocalizedString }, + vocabid+ + ) | + ( + element taxon { LocalizedString }+, + vocabid+ + ) + } + --> <define name="bkeyword"> + <a:documentation>Keyword for a bibliographic item</a:documentation> <element name="keyword"> - <choice> - <ref name="LocalizedString"/> - <group> - <element name="vocab"> - <ref name="LocalizedString"/> - </element> - <oneOrMore> - <ref name="vocabid"/> - </oneOrMore> - </group> - <group> - <oneOrMore> - <element name="taxon"> - <ref name="LocalizedString"/> - </element> - </oneOrMore> - <oneOrMore> - <ref name="vocabid"/> - </oneOrMore> - </group> - </choice> + <optional> + <element name="vocab"> + <a:documentation>The keyword as a single, controlled or uncontrolled vocabulary item</a:documentation> + <ref name="LocalizedString"/> + </element> + </optional> + <oneOrMore> + <element name="taxon"> + <a:documentation>The keywords as a hierarchical taxonomy. For example, the sequence of `taxon` elements +`pump`, `centrifugal pump`, `line shaft pump` represents a taxonomic classification</a:documentation> + <ref name="LocalizedString"/> + </element> + </oneOrMore> + <zeroOrMore> + <ref name="vocabid"> + <a:documentation>Identifiers for the keyword as a controlled vocabulary</a:documentation> + </ref> + </zeroOrMore> </element> </define> <define name="vocabid"> + <a:documentation>Item in a controlled vocabulary</a:documentation> <element name="vocabid"> - <attribute name="type"/> + <attribute name="type"> + <a:documentation>A label for the controlled vocabulary</a:documentation> + </attribute> <optional> <attribute name="uri"> + <a:documentation>A URI for the controlled vocabulary item</a:documentation> <data type="anyURI"/> </attribute> </optional> <optional> <element name="code"> + <a:documentation>The code or identifier for the controlled vocabulary item</a:documentation> <text/> </element> </optional> <optional> <element name="term"> + <a:documentation>The term itself for the controlled vocabulary item</a:documentation> <text/> </element> </optional> diff --git a/grammars/versions.json b/grammars/versions.json index 442360e..6b5279f 100644 --- a/grammars/versions.json +++ b/grammars/versions.json @@ -1,21 +1,21 @@ { -"relaton-models": "v1.2.9", -"basicdoc-models": "v1.1.3", -"metanorma-requirements-models": "v1.0.1", +"relaton-models": "v1.4.1", +"basicdoc-models": "v1.2.2", +"metanorma-requirements-models": "v1.0.2", "relaton-model-ieee": "v1.0.1", -"relaton-model-iso": "v1.0.3", +"relaton-model-iso": "v1.0.5", "relaton-model-iec": "v1.0.0", -"relaton-model-bsi": "v1.0.2", +"relaton-model-bsi": "v1.0.3", "relaton-model-gb": "v1.0.0", "relaton-model-mpfa": "v1.0.0", -"relaton-model-bipm": "v1.0.0", +"relaton-model-bipm": "v1.0.1", "relaton-model-w3c": "v1.0.0", "relaton-model-3gpp": "v1.0.1", "relaton-model-csa": "v1.0.0", "relaton-model-cc": "v1.0.0", "relaton-model-ietf": "v1.0.1", "relaton-model-iho": "v1.0.0", -"relaton-model-itu": "v1.0.0", +"relaton-model-itu": "v1.0.2", "relaton-model-m3aawg": "v1.0.0", "relaton-model-nist": "v1.0.0", "relaton-model-ribose": "v1.0.0", @@ -29,7 +29,7 @@ "relaton-model-oasis": "v1.0.1", "relaton-model-jis": "v0.0.1", "relaton-model-etsi": "v0.0.3", -"relaton-model-plateau": "v0.0.1", -"metanorma-model": "v1.3.0", -"date": "2024-02-21T18:15:14Z" +"relaton-model-plateau": "v0.0.2", +"metanorma-model": "v1.4.1", +"date": "2024-12-03T03:33:24Z" } diff --git a/lib/relaton_bib.rb b/lib/relaton/bib.rb similarity index 62% rename from lib/relaton_bib.rb rename to lib/relaton/bib.rb index 2602b32..aeaeb58 100644 --- a/lib/relaton_bib.rb +++ b/lib/relaton/bib.rb @@ -2,24 +2,28 @@ require "forwardable" require "yaml" require "htmlentities" -require "relaton_bib/version" -require "relaton_bib/deep_dup" -require "relaton_bib/util" -require "relaton_bib/localized_string" -require "relaton_bib/forename" -require "relaton_bib/full_name" -require "relaton_bib/contributor" -require "relaton_bib/document_type" -require "relaton_bib/image" -require "relaton_bib/bibliographic_item" -require "relaton_bib/hit_collection" -require "relaton_bib/hit" -require "relaton_bib/bibxml_parser" -require "relaton_bib/renderer/bibtex_builder" -require "relaton_bib/renderer/bibxml" +require "bibtex" +require "iso639" +# require_relative "deep_dup" +# require_relative "bib/config" +require_relative "bib/util" +# require_relative "workers_pool" +require_relative "bib/item" +# require_relative "xml_parser" +require_relative "bib/item_data" +require_relative "bib/item_base" +require_relative "bib/bibitem" +require_relative "bib/bibdata" +# require_relative "hit_collection" +# require_relative "hit" +require_relative "bibxml_parser" +require_relative "renderer/bibtex_builder" +require_relative "renderer/bibxml" +require_relative "bib/relation" +# require_relative "hash_converter" -module RelatonBib - class Error < StandardError; end +module Relaton + # class Error < StandardError; end class RequestError < StandardError; end @@ -27,7 +31,7 @@ class << self # @param date [String, Integer, Date] date # @param str [Boolean] return string or Date # @return [Date, String, nil] date - def parse_date(date, str = true) # rubocop:disable Metrics/CyclomaticComplexity,Metrics/MethodLength,Metrics/PerceivedComplexity,Metrics/AbcSize + def parse_date(date, str: true) # rubocop:disable Metrics/CyclomaticComplexity,Metrics/MethodLength return date if date.is_a?(Date) case date.to_s @@ -58,7 +62,7 @@ def format_date(date, format, str, outformat = nil) date = Date.strptime(date, format) str ? date.strftime(outformat || format) : date rescue Date::Error => e - Util.warn "#{date} #{e.message}" + Bib::Util.warn "#{date} #{e.message}" date end @@ -90,22 +94,24 @@ def parse_yaml(yaml, classes = [], symbolize_names: false) end end - def self.grammar_hash - # gem_path = File.expand_path "..", __dir__ - # grammars_path = File.join gem_path, "grammars", "*" - # grammars = Dir[grammars_path].sort.map { |gp| File.read gp }.join - Digest::MD5.hexdigest RelatonBib::VERSION # grammars + module Bib + def self.grammar_hash + # gem_path = File.expand_path "..", __dir__ + # grammars_path = File.join gem_path, "grammars", "*" + # grammars = Dir[grammars_path].sort.map { |gp| File.read gp }.join + Digest::MD5.hexdigest Relaton::Bib::VERSION # grammars + end end - private + # private - # @param array [Array] - # @return [Array<String>, String] - def single_element_array(array) - # if array.size > 1 - array.map { |e| e.is_a?(String) ? e : e.to_hash } - # else - # array.first.is_a?(String) ? array[0] : array.first&.to_hash - # end - end + # # @param array [Array] + # # @return [Array<String>, String] + # def single_element_array(array) + # # if array.size > 1 + # array.map { |e| e.is_a?(String) ? e : e.to_hash } + # # else + # # array.first.is_a?(String) ? array[0] : array.first&.to_hash + # # end + # end end diff --git a/lib/relaton/bib/address.rb b/lib/relaton/bib/address.rb new file mode 100644 index 0000000..df7e581 --- /dev/null +++ b/lib/relaton/bib/address.rb @@ -0,0 +1,22 @@ +module Relaton + module Bib + class Address < Lutaml::Model::Serializable + attribute :street, :string, collection: true + attribute :city, :string + attribute :state, :string + attribute :country, :string + attribute :postcode, :string + attribute :formatted_address, :string, raw: true + + xml do + root "address" + map_element "street", to: :street + map_element "city", to: :city + map_element "state", to: :state + map_element "country", to: :country + map_element "postcode", to: :postcode + map_element "formattedAddress", to: :formatted_address + end + end + end +end diff --git a/lib/relaton/bib/affiliation.rb b/lib/relaton/bib/affiliation.rb new file mode 100644 index 0000000..4e8ca09 --- /dev/null +++ b/lib/relaton/bib/affiliation.rb @@ -0,0 +1,16 @@ +module Relaton + module Bib + class Affiliation < Lutaml::Model::Serializable + attribute :name, LocalizedString + attribute :description, LocalizedMarkedUpString, collection: true + attribute :organization, Organization + + xml do + root "affiliation" + map_element "name", to: :name + map_element "description", to: :description + map_element "organization", to: :organization + end + end + end +end diff --git a/lib/relaton/bib/bibdata.rb b/lib/relaton/bib/bibdata.rb new file mode 100644 index 0000000..82ee685 --- /dev/null +++ b/lib/relaton/bib/bibdata.rb @@ -0,0 +1,14 @@ +module Relaton + module Bib + # This class represents a bibliographic item as a bibdata. + class Bibdata < Item + model ItemData + + mappings[:xml].instance_variable_get(:@attributes).delete("id") + + xml do + root "bibdata" + end + end + end +end diff --git a/lib/relaton/bib/bibitem.rb b/lib/relaton/bib/bibitem.rb new file mode 100644 index 0000000..f7856cd --- /dev/null +++ b/lib/relaton/bib/bibitem.rb @@ -0,0 +1,14 @@ +module Relaton + module Bib + # This class represents a bibliographic item as a bibitem. + class Bibitem < Item + model ItemData + + mappings[:xml].instance_variable_get(:@elements).delete("ext") + + xml do + root "bibitem" + end + end + end +end diff --git a/lib/relaton/bib/contact.rb b/lib/relaton/bib/contact.rb new file mode 100644 index 0000000..cc653b0 --- /dev/null +++ b/lib/relaton/bib/contact.rb @@ -0,0 +1,18 @@ +require_relative "address" +require_relative "phone" +require_relative "uri" + +module Relaton + module Bib + module Contact + def self.included(base) + base.instance_eval do + attribute :address, Address, collection: true + attribute :phone, Phone, collection: true + attribute :email, :string, collection: true + attribute :uri, Uri, collection: true + end + end + end + end +end diff --git a/lib/relaton/bib/contribution_info.rb b/lib/relaton/bib/contribution_info.rb new file mode 100644 index 0000000..2d23e2c --- /dev/null +++ b/lib/relaton/bib/contribution_info.rb @@ -0,0 +1,16 @@ +module Relaton + module Bib + class ContributionInfo < Lutaml::Model::Serializable + choice(min: 1, max: 1) do + attribute :person, Person + attribute :organization, Organization + end + + xml do + no_root + map_element "person", to: :person + map_element "organization", to: :organization + end + end + end +end diff --git a/lib/relaton/bib/contributor.rb b/lib/relaton/bib/contributor.rb new file mode 100644 index 0000000..025d7e4 --- /dev/null +++ b/lib/relaton/bib/contributor.rb @@ -0,0 +1,57 @@ +module Relaton + module Bib + class Contributor < Lutaml::Model::Serializable + attribute :role, Role, collection: true + # attribute :entity, ContributionInfo + # @TODO: use `import_model ContributionInfo` for person and organization when Lutaml supports it + choice(min: 1, max: 1) do + attribute :person, Person + attribute :organization, Organization + end + # import_model_attributes ContributionInfo + + xml do + root "contributor" + + map_element "role", to: :role + # map_content to: :entity, with: { from: :entity_from_xml, to: :entity_to_xml } + map_element "person", to: :person + map_element "organization", to: :organization # , with: { from: :organization_from_xml, to: :organization_to_xml } + end + + # def entity + # person || organization + # end + + # def entity=(value) + # if value.is_a? Person + # self.person = value + # self.organization = nil + # elsif value.is_a? Organization + # self.organization = value + # self.person = nil + # else + # raise ArgumentError, "value must be a Person or Organization" + # end + # end + + # def organization_from_xml(model, node) + # model.entity = Organization.of_xml node + # end + + # def organization_to_xml(model, parent, _doc) + # parent << model.entity.to_xml + # end + + # def entity_from_xml(model, node) + # n = node.instance_variable_get(:@node) || node + # model.content = ContributionInfo.of_xml n + # rescue StandardError + # end + + # def entity_to_xml(model, parent, _doc) + # parent << model.content.to_xml + # end + end + end +end diff --git a/lib/relaton/bib/copyright.rb b/lib/relaton/bib/copyright.rb new file mode 100644 index 0000000..429bf49 --- /dev/null +++ b/lib/relaton/bib/copyright.rb @@ -0,0 +1,27 @@ +module Relaton + module Bib + class Copyright < Lutaml::Model::Serializable + attribute :from, :string + attribute :to, :string + attribute :owner, ContributionInfo, collection: true + attribute :scope, :string + + xml do + root "copyright" + + map_element "from", to: :from + map_element "to", to: :to + map_element "owner", to: :owner # , with: { from: :owner_from_xml, to: :owner_to_xml } + map_element "scope", to: :scope + end + + # def owner_from_xml(model, node) + # model.owner = ContributionInfo.from_xml node + # end + + # def owner_to_xml(model, parent, _doc) + # model.owner.to_xml parent + # end + end + end +end diff --git a/lib/relaton/bib/date.rb b/lib/relaton/bib/date.rb new file mode 100644 index 0000000..b18557d --- /dev/null +++ b/lib/relaton/bib/date.rb @@ -0,0 +1,25 @@ +module Relaton + module Bib + class Date < Lutaml::Model::Serializable + attribute :type, :string + attribute :text, :string + choice(min: 1, max: 2) do + choice(min: 1, max: 2) do + attribute :from, :string + attribute :to, :string + end + # `on` is reserved word in YAML, so use `at` instead to avoid remapping key-value formats + attribute :at, :string + end + + xml do + root "date" + map_attribute "type", to: :type + map_attribute "text", to: :text + map_element "from", to: :from + map_element "to", to: :to + map_element "on", to: :at + end + end + end +end diff --git a/lib/relaton/bib/depiction.rb b/lib/relaton/bib/depiction.rb new file mode 100644 index 0000000..ed62f4c --- /dev/null +++ b/lib/relaton/bib/depiction.rb @@ -0,0 +1,14 @@ +module Relaton + module Bib + class Depiction < Lutaml::Model::Serializable + attribute :scope, :string + attribute :image, Image, collection: true + + xml do + root "depiction" + map_attribute "scope", to: :scope + map_element "image", to: :image + end + end + end +end diff --git a/lib/relaton/bib/docidentifier.rb b/lib/relaton/bib/docidentifier.rb new file mode 100644 index 0000000..3ec4752 --- /dev/null +++ b/lib/relaton/bib/docidentifier.rb @@ -0,0 +1,15 @@ +module Relaton + module Bib + class Docidentifier < LocalizedMarkedUpString + attribute :type, :string + attribute :scope, :string + attribute :primary, :boolean + + xml do + map_attribute "type", to: :type + map_attribute "scope", to: :scope + map_attribute "primary", to: :primary + end + end + end +end diff --git a/lib/relaton/bib/doctype.rb b/lib/relaton/bib/doctype.rb new file mode 100644 index 0000000..74e2a42 --- /dev/null +++ b/lib/relaton/bib/doctype.rb @@ -0,0 +1,14 @@ +module Relaton + module Bib + class Doctype < Lutaml::Model::Serializable + attribute :abbreviation, :string + attribute :content, :string + + xml do + root "doctype" + map_attribute "abbreviation", to: :abbreviation + map_content to: :content + end + end + end +end diff --git a/lib/relaton/bib/edition.rb b/lib/relaton/bib/edition.rb new file mode 100644 index 0000000..c070a2c --- /dev/null +++ b/lib/relaton/bib/edition.rb @@ -0,0 +1,14 @@ +module Relaton + module Bib + class Edition < Lutaml::Model::Serializable + attribute :number, :string + attribute :content, :string + + xml do + root "edition" + map_attribute "number", to: :number + map_content to: :content + end + end + end +end diff --git a/lib/relaton/bib/editorial_group.rb b/lib/relaton/bib/editorial_group.rb new file mode 100644 index 0000000..b150839 --- /dev/null +++ b/lib/relaton/bib/editorial_group.rb @@ -0,0 +1,14 @@ +require_relative "workgroup" + +module Relaton + module Bib + class EditorialGroup < Lutaml::Model::Serializable + attribute :technical_committee, WorkGroup, collection: true + + xml do + root "editorialgroup" + map_element "technical-committee", to: :technical_committee + end + end + end +end diff --git a/lib/relaton/bib/ext.rb b/lib/relaton/bib/ext.rb new file mode 100644 index 0000000..8e3429c --- /dev/null +++ b/lib/relaton/bib/ext.rb @@ -0,0 +1,29 @@ +require_relative "doctype" +require_relative "editorial_group" +require_relative "ics" +require_relative "structured_identifier" + +module Relaton + module Bib + class Ext < Lutaml::Model::Serializable + attribute :schema_version, :string + attribute :doctype, Doctype + attribute :subdoctype, :string + attribute :flavor, :string + attribute :editorialgroup, EditorialGroup + attribute :ics, ICS, collection: true + attribute :structuredidentifier, StructuredIdentifier, collection: true + + xml do + root "ext" + map_attribute "schema-version", to: :schema_version + map_element "doctype", to: :doctype + map_element "subdoctype", to: :subdoctype + map_element "flavor", to: :flavor + map_element "editorialgroup", to: :editorialgroup + map_element "ics", to: :ics + map_element "structuredidentifier", to: :structuredidentifier + end + end + end +end diff --git a/lib/relaton/bib/extent.rb b/lib/relaton/bib/extent.rb new file mode 100644 index 0000000..01fa4a5 --- /dev/null +++ b/lib/relaton/bib/extent.rb @@ -0,0 +1,16 @@ +module Relaton + module Bib + class Extent < Lutaml::Model::Serializable + choice(min: 1, max: 1) do + attribute :locality, Locality, collection: true + attribute :locality_stack, LocalityStack, collection: true + end + + xml do + root "extent" + map_element "locality", to: :locality + map_element "localityStack", to: :locality_stack + end + end + end +end diff --git a/lib/relaton/bib/full_name_type.rb b/lib/relaton/bib/full_name_type.rb new file mode 100644 index 0000000..6918d84 --- /dev/null +++ b/lib/relaton/bib/full_name_type.rb @@ -0,0 +1,60 @@ +module Relaton + module Bib + module FullNameType + class Forename < LocalizedString + attribute :initial, :string + + xml do + map_attribute "initial", to: :initial + end + end + + def self.included(base) # rubocop:disable Metrics/AbcSize,Metrics/MethodLength + base.instance_eval do + attribute :abbreviation, LocalizedString + attribute :prefix, LocalizedString, collection: true + attribute :forename, Forename, collection: true + attribute :formatted_initials, LocalizedString + attribute :surname, LocalizedString + attribute :addition, LocalizedString, collection: true + attribute :completename, LocalizedString + attribute :note, Note, collection: true + attribute :variant, Variant, collection: true + + xml do + map_element "abbreviation", to: :abbreviation + map_element "prefix", to: :prefix + map_element "forename", to: :forename + map_element "formatted-initials", to: :formatted_initials + map_element "surname", to: :surname + map_element "addition", to: :addition + map_element "completename", to: :completename + map_element "note", to: :note + map_element "variant", to: :variant + end + end + end + + # def content_from_xml(model, node) + # model.content = Content.of_xml node.instance_variable_get(:@node) || node + # end + + # def content_to_xml(model, parent, _doc) + # model.content.add_to_xml parent + # end + end + + module FullNameType + class Variant < Lutaml::Model::Serializable + include FullNameType + + attribute :type, :string + + xml do + root "variant" + map_attribute "type", to: :type + end + end + end + end +end diff --git a/lib/relaton/bib/fullname.rb b/lib/relaton/bib/fullname.rb new file mode 100644 index 0000000..1294545 --- /dev/null +++ b/lib/relaton/bib/fullname.rb @@ -0,0 +1,11 @@ +module Relaton + module Bib + class FullName < Lutaml::Model::Serializable + include FullNameType + + xml do + root "name" + end + end + end +end diff --git a/lib/relaton/bib/gem_version.rb b/lib/relaton/bib/gem_version.rb new file mode 100644 index 0000000..f9e6ad5 --- /dev/null +++ b/lib/relaton/bib/gem_version.rb @@ -0,0 +1,5 @@ +module Relaton + module Bib + VERSION = "2.0.0-alpha.1".freeze + end +end diff --git a/lib/relaton/bib/ics.rb b/lib/relaton/bib/ics.rb new file mode 100644 index 0000000..5826dd4 --- /dev/null +++ b/lib/relaton/bib/ics.rb @@ -0,0 +1,14 @@ +module Relaton + module Bib + class ICS < Lutaml::Model::Serializable + attribute :code, :string + attribute :text, :string + + xml do + root "ics" + map_element "code", to: :code + map_element "text", to: :text + end + end + end +end diff --git a/lib/relaton/bib/image.rb b/lib/relaton/bib/image.rb new file mode 100644 index 0000000..605571d --- /dev/null +++ b/lib/relaton/bib/image.rb @@ -0,0 +1,28 @@ +module Relaton + module Bib + class Image < Lutaml::Model::Serializable + attribute :id, :string + attribute :src, :string # anyURI + attribute :mimetype, :string + attribute :filename, :string + attribute :width, :string + attribute :height, :string + attribute :alt, :string + attribute :title, :string + attribute :longdesc, :string # anyURI + + xml do + root "image" + map_attribute "id", to: :id + map_attribute "src", to: :src + map_attribute "mimetype", to: :mimetype + map_attribute "filename", to: :filename + map_attribute "width", to: :width + map_attribute "height", to: :height + map_attribute "alt", to: :alt + map_attribute "title", to: :title + map_attribute "longdesc", to: :longdesc + end + end + end +end diff --git a/lib/relaton/bib/item.rb b/lib/relaton/bib/item.rb new file mode 100644 index 0000000..9c68df9 --- /dev/null +++ b/lib/relaton/bib/item.rb @@ -0,0 +1,128 @@ +require "lutaml/model" +require "lutaml/model/xml_adapter/nokogiri_adapter" +require_relative "localized_string_attrs" +require_relative "localized_string" +require_relative "date" +require_relative "locality" +require_relative "locality_stack" +require_relative "image" +require_relative "title" +require_relative "docidentifier" +require_relative "note" +require_relative "full_name_type" +require_relative "fullname" +require_relative "contact" +require_relative "logo" +require_relative "organization" +require_relative "affiliation" +require_relative "person" +require_relative "contribution_info" +require_relative "role" +require_relative "contributor" +require_relative "edition" +require_relative "version" +require_relative "status" +require_relative "copyright" +require_relative "place" +require_relative "series" +require_relative "medium" +require_relative "uri" +require_relative "price" +require_relative "extent" +require_relative "size" +require_relative "keyword" +require_relative "validity" +require_relative "depiction" +require_relative "source_locality_stack" +require_relative "ext" + +Lutaml::Model::Config.configure do |config| + config.xml_adapter = Lutaml::Model::XmlAdapter::NokogiriAdapter +end + +module Relaton + module Bib + class Relation < Lutaml::Model::Serializable + end + + # Item class repesents bibliographic item metadata. + class Item < Lutaml::Model::Serializable + attribute :id, :string + attribute :type, :string, values: %W[ + article book booklet manual proceedings presentation thesis techreport standard + unpublished map electronic\sresource audiovisual film video boradcast software + graphic_work music patent inbook incollection inproceedings journal website + webresource dataset archival social_media alert message convesation misc + ] + attribute :schema_version, :string + attribute :fetched, :date + attribute :formattedref, :string, raw: true + attribute :title, Title, collection: true + attribute :source, Uri, collection: true + attribute :docidentifier, Docidentifier, collection: true + attribute :docnumber, :string + attribute :date, Date, collection: true + attribute :contributor, Contributor, collection: true + attribute :edition, Edition + attribute :version, Version, collection: true + attribute :note, Note, collection: true + attribute :language, :string, collection: true + attribute :locale, :string, collection: true + attribute :script, :string, collection: true + attribute :abstract, LocalizedMarkedUpString, collection: true + attribute :status, Status + attribute :copyright, Copyright, collection: true + attribute :relation, Relation, collection: true + attribute :series, Series, collection: true + attribute :medium, Medium + attribute :place, Place, collection: true + attribute :price, Price, collection: true + attribute :extent, Extent, collection: true + attribute :size, Size + attribute :accesslocation, :string, collection: true + attribute :license, :string, collection: true + attribute :classification, Docidentifier, collection: true + attribute :keyword, Keyword, collection: true + attribute :validity, Validity + attribute :depiction, Depiction + attribute :ext, Ext + + xml do # rubocop:disable Metrics/BlockLength + map_attribute "id", to: :id + map_attribute "type", to: :type + map_attribute "schema-version", to: :schema_version + map_element "fetched", to: :fetched + map_element "formattedref", to: :formattedref + map_element "title", to: :title # , with: { from: :title_from_xml, to: :title_to_xml } + map_element "uri", to: :source + map_element "docidentifier", to: :docidentifier + map_element "docnumber", to: :docnumber + map_element "date", to: :date + map_element "contributor", to: :contributor + map_element "edition", to: :edition + map_element "version", to: :version + map_element "note", to: :note + map_element "language", to: :language + map_element "locale", to: :locale + map_element "script", to: :script + map_element "abstract", to: :abstract + map_element "status", to: :status + map_element "copyright", to: :copyright + map_element "relation", to: :relation # , with: { from: :relation_from_xml, to: :relation_to_xml } + map_element "series", to: :series + map_element "medium", to: :medium + map_element "place", to: :place + map_element "price", to: :price + map_element "extent", to: :extent + map_element "size", to: :size + map_element "accesslocation", to: :accesslocation + map_element "license", to: :license + map_element "classification", to: :classification + map_element "keyword", to: :keyword + map_element "validity", to: :validity + map_element "depiction", to: :depiction + map_element "ext", to: :ext + end + end + end +end diff --git a/lib/relaton/bib/item_base.rb b/lib/relaton/bib/item_base.rb new file mode 100644 index 0000000..322396b --- /dev/null +++ b/lib/relaton/bib/item_base.rb @@ -0,0 +1,13 @@ +module Relaton + autoload :Item, "relaton/bib/item" + + module Bib + # The class is for relaton bibitem instances. + # The in relaton bibitem instances dosn't have schema-version & fetched attributes. + class ItemBase < Item + # we don't need schema-version & fetched attributes in reation/bibitem + mappings[:xml].instance_variable_get(:@attributes).delete("schema-version") + mappings[:xml].instance_variable_get(:@elements).delete("fetched") + end + end +end diff --git a/lib/relaton/bib/item_data.rb b/lib/relaton/bib/item_data.rb new file mode 100644 index 0000000..c4f21b3 --- /dev/null +++ b/lib/relaton/bib/item_data.rb @@ -0,0 +1,15 @@ +module Relaton + module Bib + # This class represents the data of a bibliographic item. + # It needed to keep data fot different types of representations (bibitem, bibdata ...). + # @TODO: remove this class when Lutaml Model will support transformation between different types of models. + class ItemData + attr_accessor :id, :type, :schema_version, :fetched, :formattedref, :title, + :source, :docidentifier, :docnumber, :date, :contributor, + :edition, :version, :note, :language, :locale, :script, + :abstract, :status, :copyright, :relation, :series, :medium, + :place, :price, :extent, :size, :accesslocation, :license, + :classification, :keyword, :validity, :depiction, :ext + end + end +end diff --git a/lib/relaton/bib/keyword.rb b/lib/relaton/bib/keyword.rb new file mode 100644 index 0000000..5a12311 --- /dev/null +++ b/lib/relaton/bib/keyword.rb @@ -0,0 +1,30 @@ +module Relaton + module Bib + class Keyword < Lutaml::Model::Serializable + class Vocabid < Lutaml::Model::Serializable + attribute :type, :string + attribute :uri, :string + attribute :code, :string + attribute :term, :string + + xml do + map_attribute "type", to: :type + map_attribute "uri", to: :uri + map_element "code", to: :code + map_element "term", to: :term + end + end + + attribute :vocab, LocalizedString, collection: true + attribute :taxon, LocalizedString, collection: (1..) + attribute :vocabid, Vocabid + + xml do + root "keyword" + map_element "vocab", to: :vocab + map_element "taxon", to: :taxon + map_element "vocabid", to: :vocabid + end + end + end +end diff --git a/lib/relaton/bib/locality.rb b/lib/relaton/bib/locality.rb new file mode 100644 index 0000000..97aabb9 --- /dev/null +++ b/lib/relaton/bib/locality.rb @@ -0,0 +1,18 @@ +module Relaton + module Bib + class Locality < Lutaml::Model::Serializable + attribute :type, :string, pattern: %r{ + section|clause|part|paragraph|chapter|page|title|line|whole|table|annex| + figure|note|list|example|volume|issue|time|anchor|locality:[a-zA-Z0-9_]+ + }x + attribute :reference_from, :string + attribute :reference_to, :string + + xml do + map_attribute "type", to: :type + map_element "referenceFrom", to: :reference_from + map_element "referenceTo", to: :reference_to + end + end + end +end diff --git a/lib/relaton/bib/locality_stack.rb b/lib/relaton/bib/locality_stack.rb new file mode 100644 index 0000000..e4fd05c --- /dev/null +++ b/lib/relaton/bib/locality_stack.rb @@ -0,0 +1,14 @@ +module Relaton + module Bib + class LocalityStack < Lutaml::Model::Serializable + attribute :connective, :string, values: %w[and or from to] + attribute :locality, Locality, collection: true + + xml do + root "localityStack" + map_attribute "connective", to: :connective + map_element "locality", to: :locality + end + end + end +end diff --git a/lib/relaton/bib/localized_string.rb b/lib/relaton/bib/localized_string.rb new file mode 100644 index 0000000..a4be2f4 --- /dev/null +++ b/lib/relaton/bib/localized_string.rb @@ -0,0 +1,27 @@ +module Relaton + module Bib + class LocalizedString < LocalizedStringAttrs + attribute :content, :string + + xml do + map_content to: :content + end + end + + class TypedLocalizedString < LocalizedString + attribute :type, :string + + xml do + map_attribute "type", to: :type + end + end + + class LocalizedMarkedUpString < LocalizedStringAttrs + attribute :content, :string + + xml do + map_all to: :content + end + end + end +end diff --git a/lib/relaton/bib/localized_string_attrs.rb b/lib/relaton/bib/localized_string_attrs.rb new file mode 100644 index 0000000..87a3557 --- /dev/null +++ b/lib/relaton/bib/localized_string_attrs.rb @@ -0,0 +1,20 @@ +module Relaton + module Bib + class LocalizedStringAttrs < Lutaml::Model::Serializable + attribute :language, :string + attribute :locale, :string + attribute :script, :string + + # def self.inherited(base) + # super + # base.class_eval do + xml do + map_attribute "language", to: :language + map_attribute "locale", to: :locale + map_attribute "script", to: :script + end + # end + # end + end + end +end diff --git a/lib/relaton/bib/logo.rb b/lib/relaton/bib/logo.rb new file mode 100644 index 0000000..7120bb4 --- /dev/null +++ b/lib/relaton/bib/logo.rb @@ -0,0 +1,12 @@ +module Relaton + module Bib + class Logo < Lutaml::Model::Serializable + attribute :image, Image + + xml do + root "logo" + map_element "image", to: :image + end + end + end +end diff --git a/lib/relaton/bib/medium.rb b/lib/relaton/bib/medium.rb new file mode 100644 index 0000000..82b8aa6 --- /dev/null +++ b/lib/relaton/bib/medium.rb @@ -0,0 +1,22 @@ +module Relaton + module Bib + class Medium < Lutaml::Model::Serializable + attribute :content, :string + attribute :genre, :string + attribute :form, :string + attribute :carrier, :string + attribute :size, :string + attribute :scale, :string + + xml do + root "medium" + map_element "content", to: :content + map_element "genre", to: :genre + map_element "form", to: :form + map_element "carrier", to: :carrier + map_element "size", to: :size + map_element "scale", to: :scale + end + end + end +end diff --git a/lib/relaton/bib/note.rb b/lib/relaton/bib/note.rb new file mode 100644 index 0000000..515956d --- /dev/null +++ b/lib/relaton/bib/note.rb @@ -0,0 +1,14 @@ +module Relaton + module Bib + class Note < LocalizedStringAttrs + attribute :type, :string + attribute :content, :string + + xml do + root "note" + map_attribute "type", to: :type + map_all to: :content + end + end + end +end diff --git a/lib/relaton/bib/organization.rb b/lib/relaton/bib/organization.rb new file mode 100644 index 0000000..6b06f69 --- /dev/null +++ b/lib/relaton/bib/organization.rb @@ -0,0 +1,13 @@ +require_relative "organization_type" + +module Relaton + module Bib + class Organization < Lutaml::Model::Serializable + include OrganizationType + + xml do + root "organization" + end + end + end +end diff --git a/lib/relaton/bib/organization_type.rb b/lib/relaton/bib/organization_type.rb new file mode 100644 index 0000000..72860c8 --- /dev/null +++ b/lib/relaton/bib/organization_type.rb @@ -0,0 +1,42 @@ +module Relaton + module Bib + module OrganizationType + class Identifier < Lutaml::Model::Serializable + attribute :type, :string + attribute :content, :string + + xml do + root "identifier" + map_attribute "type", to: :type + map_content to: :content + end + end + + def self.included(base) # rubocop:disable Metrics/AbcSize,Metrics/MethodLength + require_relative "subdivision" + + base.instance_eval do + include Contact + + attribute :name, TypedLocalizedString, collection: true + attribute :subdivision, Subdivision, collection: true + attribute :abbreviation, LocalizedString + attribute :identifier, Identifier, collection: true + attribute :logo, Logo + + xml do + map_element "name", to: :name + map_element "subdivision", to: :subdivision + map_element "abbreviation", to: :abbreviation + map_element "identifier", to: :identifier + map_element "address", to: :address + map_element "phone", to: :phone + map_element "email", to: :email + map_element "uri", to: :uri + map_element "logo", to: :logo + end + end + end + end + end +end diff --git a/lib/relaton/bib/person.rb b/lib/relaton/bib/person.rb new file mode 100644 index 0000000..75a7194 --- /dev/null +++ b/lib/relaton/bib/person.rb @@ -0,0 +1,36 @@ +module Relaton + module Bib + class Person < Lutaml::Model::Serializable + class Identifier < Lutaml::Model::Serializable + attribute :type, :string + attribute :content, :string + + xml do + root "identifier" + map_attribute "type", to: :type + map_content to: :content + end + end + + include Contact + + attribute :name, FullName + attribute :credential, :string, collection: true + attribute :affiliation, Affiliation, collection: true + attribute :identifier, Identifier, collection: true + + xml do + root "person" + + map_element "name", to: :name + map_element "credential", to: :credential + map_element "affiliation", to: :affiliation + map_element "identifier", to: :identifier + map_element "address", to: :address + map_element "phone", to: :phone + map_element "email", to: :email + map_element "uri", to: :uri + end + end + end +end diff --git a/lib/relaton/bib/phone.rb b/lib/relaton/bib/phone.rb new file mode 100644 index 0000000..8f932c6 --- /dev/null +++ b/lib/relaton/bib/phone.rb @@ -0,0 +1,14 @@ +module Relaton + module Bib + class Phone < Lutaml::Model::Serializable + attribute :type, :string + attribute :content, :string + + xml do + root "phone" + map_attribute "type", to: :type + map_content to: :content + end + end + end +end diff --git a/lib/relaton/bib/place.rb b/lib/relaton/bib/place.rb new file mode 100644 index 0000000..fcdb3a8 --- /dev/null +++ b/lib/relaton/bib/place.rb @@ -0,0 +1,33 @@ +module Relaton + module Bib + class Place < Lutaml::Model::Serializable + class RegionType < Lutaml::Model::Serializable + attribute :iso, :string + attribute :recommended, :boolean + attribute :content, :string + + xml do + root "region" + map_attribute "iso", to: :iso + map_attribute "recommended", to: :recommended + map_content to: :content + end + end + + attribute :city, :string + attribute :region, RegionType, collection: true + attribute :country, RegionType, collection: true + attribute :formatted_place, :string + attribute :uri, Uri + + xml do + root "place" + map_element "city", to: :city + map_element "region", to: :region + map_element "country", to: :country + map_element "formattedPlace", to: :formatted_place + map_element "uri", to: :uri + end + end + end +end diff --git a/lib/relaton/bib/price.rb b/lib/relaton/bib/price.rb new file mode 100644 index 0000000..8f6a8d8 --- /dev/null +++ b/lib/relaton/bib/price.rb @@ -0,0 +1,14 @@ +module Relaton + module Bib + class Price < Lutaml::Model::Serializable + attribute :currency, :string + attribute :content, :string + + xml do + root "price" + map_attribute "currency", to: :currency + map_content to: :content + end + end + end +end diff --git a/lib/relaton/bib/relation.rb b/lib/relaton/bib/relation.rb new file mode 100644 index 0000000..3683025 --- /dev/null +++ b/lib/relaton/bib/relation.rb @@ -0,0 +1,31 @@ +require_relative "item_base" + +module Relaton + module Bib + class Relation + attribute :type, :string + attribute :description, LocalizedMarkedUpString + attribute :bibitem, ItemBase + choice(min: 1, max: 1) do + attribute :locality, Locality, collection: true + attribute :locality_stack, LocalityStack, collection: true + end + choice(min: 1, max: 1) do + attribute :source_locality, Locality, collection: true + attribute :source_locality_stack, SourceLocalityStack, collection: true + end + + xml do + root "relation" + + map_attribute "type", to: :type + map_element "description", to: :description + map_element "bibitem", to: :bibitem + map_element "locality", to: :locality + map_element "localityStack", to: :locality_stack + map_element "sourceLocality", to: :source_locality + map_element "sourceLocalityStack", to: :source_locality_stack + end + end + end +end diff --git a/lib/relaton/bib/role.rb b/lib/relaton/bib/role.rb new file mode 100644 index 0000000..c051245 --- /dev/null +++ b/lib/relaton/bib/role.rb @@ -0,0 +1,17 @@ +module Relaton + module Bib + class Role < Lutaml::Model::Serializable + attribute :type, :string, values: %w[ + author performer publisher editor adapter translator distributor reazer + owner authorizer enabler subject + ] + attribute :description, LocalizedMarkedUpString, collection: true + + xml do + root "role" + map_attribute "type", to: :type + map_element "description", to: :description + end + end + end +end diff --git a/lib/relaton/bib/series.rb b/lib/relaton/bib/series.rb new file mode 100644 index 0000000..11b3dac --- /dev/null +++ b/lib/relaton/bib/series.rb @@ -0,0 +1,32 @@ +module Relaton + module Bib + class Series < Lutaml::Model::Serializable + attribute :type, :string, values: %w[main alt] + attribute :formattedref, :string, raw: true + attribute :title, Title, collection: (1..) + attribute :place, Place + attribute :organization, :string + attribute :abbreviation, LocalizedString + attribute :from, :date + attribute :to, :date + attribute :number, :string + attribute :partnumber, :string + attribute :run, :string + + xml do + root "series" + map_attribute "type", to: :type + map_element "formattedref", to: :formattedref + map_element "title", to: :title + map_element "place", to: :place + map_element "organization", to: :organization + map_element "abbreviation", to: :abbreviation + map_element "from", to: :from + map_element "to", to: :to + map_element "number", to: :number + map_element "partnumber", to: :partnumber + map_element "run", to: :run + end + end + end +end diff --git a/lib/relaton/bib/size.rb b/lib/relaton/bib/size.rb new file mode 100644 index 0000000..71caaab --- /dev/null +++ b/lib/relaton/bib/size.rb @@ -0,0 +1,23 @@ +module Relaton + module Bib + class Size < Lutaml::Model::Serializable + class Value < Lutaml::Model::Serializable + attribute :type, :string + attribute :content, :string + + xml do + root "value" + map_attribute "type", to: :type + map_content to: :content + end + end + + attribute :value, Value, collection: (1..) + + xml do + root "size" + map_element "value", to: :value + end + end + end +end diff --git a/lib/relaton/bib/source_locality_stack.rb b/lib/relaton/bib/source_locality_stack.rb new file mode 100644 index 0000000..6205e10 --- /dev/null +++ b/lib/relaton/bib/source_locality_stack.rb @@ -0,0 +1,14 @@ +module Relaton + module Bib + class SourceLocalityStack < Lutaml::Model::Serializable + attribute :connective, :string, values: %w[and or from to] + attribute :source_locality, Locality, collection: true + + xml do + root "sourceLocalityStack" + map_attribute "connective", to: :connective + map_element "sourceLocality", to: :source_locality + end + end + end +end diff --git a/lib/relaton/bib/status.rb b/lib/relaton/bib/status.rb new file mode 100644 index 0000000..91f6c46 --- /dev/null +++ b/lib/relaton/bib/status.rb @@ -0,0 +1,27 @@ +module Relaton + module Bib + class Status < Lutaml::Model::Serializable + class Stage < Lutaml::Model::Serializable + attribute :abbreviation, :string + attribute :content, :string + + xml do + root "stage" + map_attribute "abbreviation", to: :abbreviation + map_content to: :content + end + end + + attribute :stage, Stage + attribute :substage, Stage + attribute :iteration, :string + + xml do + root "status" + map_element "stage", to: :stage + map_element "substage", to: :substage + map_element "iteration", to: :iteration + end + end + end +end diff --git a/lib/relaton/bib/structured_identifier.rb b/lib/relaton/bib/structured_identifier.rb new file mode 100644 index 0000000..ed1f546 --- /dev/null +++ b/lib/relaton/bib/structured_identifier.rb @@ -0,0 +1,36 @@ +module Relaton + module Bib + class StructuredIdentifier < Lutaml::Model::Serializable + attribute :type, :string + attribute :agency, :string, collection: (1..) + attribute :klass, :string + attribute :docnumber, :string + attribute :partnumber, :string + attribute :edition, :string + attribute :version, :string + attribute :supplementtype, :string + attribute :supplementnumber, :string + attribute :amendment, :string + attribute :corrigendum, :string + attribute :language, :string + attribute :year, :string + + xml do + root "structuredidentifier" + map_attribute "type", to: :type + map_element "agency", to: :agency + map_element "class", to: :klass + map_element "docnumber", to: :docnumber + map_element "partnumber", to: :partnumber + map_element "edition", to: :edition + map_element "version", to: :version + map_element "supplementtype", to: :supplementtype + map_element "supplementnumber", to: :supplementnumber + map_element "amendment", to: :amendment + map_element "corrigendum", to: :corrigendum + map_element "language", to: :language + map_element "year", to: :year + end + end + end +end diff --git a/lib/relaton/bib/subdivision.rb b/lib/relaton/bib/subdivision.rb new file mode 100644 index 0000000..7535d25 --- /dev/null +++ b/lib/relaton/bib/subdivision.rb @@ -0,0 +1,14 @@ +module Relaton + module Bib + class Subdivision < Lutaml::Model::Serializable + include OrganizationType + + attribute :type, :string + + xml do + root "subdivision" + map_attribute "type", to: :type + end + end + end +end diff --git a/lib/relaton/bib/technical_committee.rb b/lib/relaton/bib/technical_committee.rb new file mode 100644 index 0000000..4488117 --- /dev/null +++ b/lib/relaton/bib/technical_committee.rb @@ -0,0 +1,14 @@ +require_relative "workgroup" + +module Relaton + module Bib + class TechnicalCommittee < Lutaml::Model::Serializable + attribute :workgroup, WorkGroup + + xml do + root "technical-committee" + map_content to: :workgroup + end + end + end +end diff --git a/lib/relaton/bib/title.rb b/lib/relaton/bib/title.rb new file mode 100644 index 0000000..f86f9fe --- /dev/null +++ b/lib/relaton/bib/title.rb @@ -0,0 +1,13 @@ +module Relaton + module Bib + class Title < LocalizedMarkedUpString + attribute :type, :string + attribute :format, :string # @DEPRECATED + + xml do + map_attribute "type", to: :type + map_attribute "format", to: :format + end + end + end +end diff --git a/lib/relaton/bib/uri.rb b/lib/relaton/bib/uri.rb new file mode 100644 index 0000000..ea48e56 --- /dev/null +++ b/lib/relaton/bib/uri.rb @@ -0,0 +1,13 @@ +module Relaton + module Bib + class Uri < LocalizedStringAttrs + attribute :type, :string + attribute :content, :string + + xml do + map_attribute "type", to: :type + map_content to: :content + end + end + end +end diff --git a/lib/relaton/bib/util.rb b/lib/relaton/bib/util.rb new file mode 100644 index 0000000..abd7048 --- /dev/null +++ b/lib/relaton/bib/util.rb @@ -0,0 +1,18 @@ +module Relaton + module Bib + module Util + extend self + + PROGNAME = "relaton-bib".freeze + + def method_missing(method_name, msg = nil, prog = nil, **opts, &block) + prog ||= self::PROGNAME + Relaton.logger_pool.send method_name, msg, prog, **opts, &block + end + + def respond_to_missing?(method_name, include_private = false) + Relaton.logger_pool.respond_to?(method_name) || super + end + end + end +end diff --git a/lib/relaton/bib/validity.rb b/lib/relaton/bib/validity.rb new file mode 100644 index 0000000..324da81 --- /dev/null +++ b/lib/relaton/bib/validity.rb @@ -0,0 +1,16 @@ +module Relaton + module Bib + class Validity < Lutaml::Model::Serializable + attribute :begins, :date + attribute :ends, :date + attribute :revision, :date + + xml do + root "validity" + map_element "validityBegins", to: :begins + map_element "validityEnds", to: :ends + map_element "revision", to: :revision + end + end + end +end diff --git a/lib/relaton/bib/version.rb b/lib/relaton/bib/version.rb new file mode 100644 index 0000000..549cdc2 --- /dev/null +++ b/lib/relaton/bib/version.rb @@ -0,0 +1,14 @@ +module Relaton + module Bib + class Version < Lutaml::Model::Serializable + attribute :revision_date, :date + attribute :draft, :string + + xml do + root "version" + map_element "revision-date", to: :revision_date + map_element "draft", to: :draft + end + end + end +end diff --git a/lib/relaton/bib/workgroup.rb b/lib/relaton/bib/workgroup.rb new file mode 100644 index 0000000..f31f538 --- /dev/null +++ b/lib/relaton/bib/workgroup.rb @@ -0,0 +1,20 @@ +module Relaton + module Bib + class WorkGroup < Lutaml::Model::Serializable + attribute :number, :string + attribute :type, :string + attribute :identifier, :string + attribute :prefix, :string + attribute :content, :string + + xml do + root "workgroup" + map_attribute "number", to: :number + map_attribute "type", to: :type + map_attribute "identifier", to: :identifier + map_attribute "prefix", to: :prefix + map_content to: :content + end + end + end +end diff --git a/lib/relaton_bib/bibtex_parser.rb b/lib/relaton/bibtex_parser.rb similarity index 82% rename from lib/relaton_bib/bibtex_parser.rb rename to lib/relaton/bibtex_parser.rb index 6159265..6d9ee63 100644 --- a/lib/relaton_bib/bibtex_parser.rb +++ b/lib/relaton/bibtex_parser.rb @@ -1,15 +1,12 @@ -require "bibtex" -require "iso639" - -module RelatonBib - # @todo: move this class to the RelatonBib::Bibtex module +module Relaton + # @todo: move this class to the Relaton::Bib::Bibtex module class BibtexParser class << self # @param bibtex [String] - # @return [Hash{String=>RelatonBib::BibliographicItem}] + # @return [Hash{String=>Relaton::Bib::Item}] def from_bibtex(bibtex) # rubocop:disable Metrics/AbcSize,Metrics/MethodLength BibTeX.parse(bibtex).reduce({}) do |h, bt| - h[bt.key] = BibliographicItem.new( + h[bt.key] = Item.new( id: bt.key, docid: fetch_docid(bt), fetched: fetch_fetched(bt), @@ -35,12 +32,12 @@ def from_bibtex(bibtex) # rubocop:disable Metrics/AbcSize,Metrics/MethodLength private # @param bibtex [BibTeX::Entry] - # @return [Array<RelatonBib::DocumentIdentifier>] + # @return [Array<Relaton::Bib::Docidentifier>] def fetch_docid(bibtex) # rubocop:disable Metrics/AbcSize docid = [] - docid << DocumentIdentifier.new(id: bibtex.isbn.to_s, type: "isbn") if bibtex["isbn"] - docid << DocumentIdentifier.new(id: bibtex.lccn.to_s, type: "lccn") if bibtex["lccn"] - docid << DocumentIdentifier.new(id: bibtex.issn.to_s, type: "issn") if bibtex["issn"] + docid << Docidentifier.new(id: bibtex.isbn.to_s, type: "isbn") if bibtex["isbn"] + docid << Docidentifier.new(id: bibtex.lccn.to_s, type: "lccn") if bibtex["lccn"] + docid << Docidentifier.new(id: bibtex.issn.to_s, type: "issn") if bibtex["issn"] docid end @@ -68,12 +65,12 @@ def fetch_place(bibtex) end # @param bibtex [BibTeX::Entry] - # @return [RelatonBib::TypedTitleStringCollection] + # @return [Relaton::Bib::TitleCollection] def fetch_title(bibtex) title = [] title << { type: "main", content: bibtex.convert(:latex).title.to_s } if bibtex["title"] title << { type: "main", content: bibtex.convert(:latex).subtitle.to_s } if bibtex["subtitle"] - TypedTitleStringCollection.new title + TitleCollection.new title end # @param bibtex [BibTeX::Entry] @@ -113,7 +110,7 @@ def fetch_org(org, type, desc = nil, &_) end # @param bibtex [BibTeX::Entry] - # @return [Array<RelatonBib::Person>] + # @return [Array<Relaton::Bib::Person>] def fetch_person(bibtex, role, &_) # rubocop:disable Metrics/AbcSize bibtex[role]&.each do |name| parts = name.split ", " @@ -142,7 +139,7 @@ def fetch_date(bibtex) end # @param bibtex [BibTeX::Entry] - # @return [RelatonBib::BiblioNoteCollection] + # @return [Relaton::Bib::BiblioNoteCollection] def fetch_note(bibtex) # rubocop:disable Metrics/AbcSize,Metrics/CyclomaticComplexity,Metrics/MethodLength bibtex.select do |k, _v| %i[annote howpublished comment note content].include? k @@ -163,9 +160,9 @@ def fetch_note(bibtex) # rubocop:disable Metrics/AbcSize,Metrics/CyclomaticCompl def fetch_relation(bibtex) return [] unless bibtex["booktitle"] - ttl = TypedTitleString.new(type: "main", content: bibtex.booktitle.to_s) - title = TypedTitleStringCollection.new [ttl] - [{ type: "partOf", bibitem: BibliographicItem.new(title: title) }] + ttl = Title.new(type: "main", content: bibtex.booktitle.to_s) + title = TitleCollection.new [ttl] + [{ type: "partOf", bibitem: Item.new(title: title) }] end # @param bibtex [BibTeX::Entry] @@ -188,31 +185,31 @@ def fetch_extent(bibtex) # rubocop:disable Metrics/MethodLength,Metrics/AbcSize end # @param bibtex [BibTeX::Entry] - # @return [Array<RelatonBib::Series>] + # @return [Array<Relaton::Bib::Series>] def fetch_series(bibtex) # rubocop:disable Metrics/MethodLength series = [] if bibtex["journal"] series << Series.new( type: "journal", - title: TypedTitleString.new(content: bibtex.journal.to_s), - number: bibtex["number"]&.to_s + title: Title.new(content: bibtex.journal.to_s), + number: bibtex["number"]&.to_s, ) end if bibtex["series"] - title = TypedTitleString.new content: bibtex.series.to_s + title = Title.new content: bibtex.series.to_s series << Series.new(title: title) end series end # @param bibtex [BibTeX::Entry] - # @return [Array<RelatonBib::TypedUri>] + # @return [Array<Relaton::Bib::Bsource>] def fetch_link(bibtex) # rubocop:disable Metrics/AbcSize link = [] - link << TypedUri.new(type: "src", content: bibtex.url.to_s) if bibtex["url"] - link << TypedUri.new(type: "doi", content: bibtex.doi.to_s) if bibtex["doi"] - link << TypedUri.new(type: "file", content: bibtex.file2.to_s) if bibtex["file2"] + link << Bsource.new(type: "src", content: bibtex.url.to_s) if bibtex["url"] + link << Bsource.new(type: "doi", content: bibtex.doi.to_s) if bibtex["doi"] + link << Bsource.new(type: "file", content: bibtex.file2.to_s) if bibtex["file2"] link end @@ -225,7 +222,7 @@ def fetch_language(bibtex) end # @param bibtex [BibTeX::Entry] - # @return [RelatonBib::Classification, nil] + # @return [Relaton::Bib::Classification, nil] def fetch_classification(bibtex) cls = [] cls << Classification.new(type: "type", value: bibtex["type"].to_s) if bibtex["type"] diff --git a/lib/relaton_bib/bibxml_parser.rb b/lib/relaton/bibxml_parser.rb similarity index 83% rename from lib/relaton_bib/bibxml_parser.rb rename to lib/relaton/bibxml_parser.rb index 4713593..848c008 100644 --- a/lib/relaton_bib/bibxml_parser.rb +++ b/lib/relaton/bibxml_parser.rb @@ -1,4 +1,4 @@ -module RelatonBib +module Relaton module BibXMLParser # SeriesInfo what should be saved as docidentifiers in the Relaton model. SERIESINFONAMES = ["DOI"].freeze @@ -31,7 +31,7 @@ def parse(bibxml, url: nil, is_relation: false, ver: nil) # @param is_relation [Boolean] don't add fetched date for relation if true # @param url [String, nil] # @param ver [String, nil] Internet Draft version - # @return [RelatonBib::BibliographicItem] + # @return [Relaton::Bib::Item] def fetch_rfc(reference, is_relation: false, url: nil, ver: nil) # rubocop:disable Metrics/AbcSize,Metrics/MethodLength return unless reference @@ -64,10 +64,10 @@ def docnumber(reference) end # @param attrs [Hash] - # @return [RelatonBib::BibliographicItem] + # @return [Relaton::Bib::Item] def bib_item(**attrs) # attrs[:place] = ["Fremont, CA"] - BibliographicItem.new(**attrs) + Item.new(**attrs) end # @param reference [Nokogiri::XML::Element] @@ -82,7 +82,7 @@ def language(reference) # @param reference [Nokogiri::XML::Element] # @param ver [String, nil] Internet Draft version # - # @return [Array<RelatonBib::DocumentIdentifier>] + # @return [Array<Relaton::Bib::Docidentifier>] # def docids(reference, ver) # rubocop:disable Metrics/MethodLength,Metrics/CyclomaticComplexity,Metrics/PerceivedComplexity,Metrics/AbcSize ret = [] @@ -91,7 +91,7 @@ def docids(reference, ver) # rubocop:disable Metrics/MethodLength,Metrics/Cyclom if si id = si[:value] id.sub!(/(?<=-)\d{2}$/, ver) if ver - ret << DocumentIdentifier.new(type: "Internet-Draft", id: id, primary: true) + ret << Bib::Docidentifier.new(type: "Internet-Draft", id: id, primary: true) else id = reference[:anchor] || reference[:docName] || reference[:number] ret << create_docid(id, ver) if id @@ -106,7 +106,7 @@ def docids(reference, ver) # rubocop:disable Metrics/MethodLength,Metrics/Cyclom reference[atr] end type = pubid_type id - ret << DocumentIdentifier.new(id: atrid, type: type, scope: atr) + ret << Bib::Docidentifier.new(id: atrid, type: type, scope: atr) end end @@ -115,7 +115,7 @@ def docids(reference, ver) # rubocop:disable Metrics/MethodLength,Metrics/Cyclom id = si[:value] # id.sub!(/(?<=-)\d{2}$/, ver) if ver && si[:name] == "Internet-Draft" - DocumentIdentifier.new(id: id, type: si[:name]) + Bib::Docidentifier.new(id: id, type: si[:name]) end.compact end @@ -132,7 +132,7 @@ def create_docid(id, ver) # rubocop:disable Metrics/MethodLength pid = pref ? "#{pref} #{num}" : id type = pubid_type id end - DocumentIdentifier.new(type: type, id: pid, primary: true) + Docidentifier.new(type: type, id: pid, primary: true) end def id_to_pref_num(id) @@ -155,7 +155,7 @@ def pubid_type(id) # extract status # @param reference [Nokogiri::XML::Element] # - # @return [RelatonBib::DocumentStatus] + # @return [Relaton::Bib::DocumentStatus] # def status(reference) st = reference.at("./seriesinfo[@status]") @@ -188,26 +188,24 @@ def titles(reference) end # @param reference [Nokogiri::XML::Element] - # @return [RelatonBib::FormattedRef, nil] + # @return [Relaton::Bib::Formattedref, nil] def formattedref(reference) return if reference.at "./front/title" - cont = (reference[:anchor] || reference[:docName] || reference[:number]) + cont = reference[:anchor] || reference[:docName] || reference[:number] if cont - FormattedRef.new( + Formattedref.new( content: cont, language: language(reference), script: "Latn", ) end end # @param reference [Nokogiri::XML::Element] - # @return [Array<RelatonBib::FormattedString>] + # @return [Array<Relaton::Bib::FormattedString>] def abstracts(ref) ref.xpath("./front/abstract").map do |a| - c = a.inner_html.gsub(/\s*(<\/?)t(>)\s*/, '\1p\2') - .gsub(/[\t\n]/, " ").squeeze " " - FormattedString.new(content: c, language: language(ref), script: "Latn", - format: "text/html") + c = a.inner_html.gsub(/\s*(<\/?)t(>)\s*/, '\1p\2').gsub(/[\t\n]/, " ").squeeze " " + Bib::FormattedString.new(content: c, language: language(ref), script: "Latn", format: "text/html") end end @@ -225,17 +223,16 @@ def contributors(reference) # @param author [Nokogiri::XML::Element] # @param lang [String] - # @return [RelatonBib::Person, nil] + # @return [Relaton::Bib::Person, nil] def person(author, lang) return unless author[:fullname] || author[:surname] name = full_name(author[:fullname], author[:surname], author[:initials], lang) - Person.new(name: name, affiliation: affiliation(author), - contact: contacts(author.at("./address"))) + Bib::Person.new(name: name, affiliation: affiliation(author), contact: contacts(author.at("./address"))) end # @param contrib [Nokogiri::XML::Element] - # @return [RelatonBib::Organization, nil] + # @return [Relaton::Bib::Organization, nil] def organization(contrib) org = contrib.at("./organization") return unless org @@ -251,10 +248,10 @@ def organization(contrib) # @param sname [String] surname # @param inits [String] initials # @param lang [String] language - # @return [RelatonBib::FullName] + # @return [Relaton::Bib::FullName] def full_name(fname, sname, inits, lang) initials = localized_string(inits, lang) if inits - FullName.new( + Bib::FullName.new( completename: localized_string(fname, lang), initials: initials, forename: forename(inits, lang), surname: localized_string(sname, lang) ) @@ -266,43 +263,43 @@ def full_name(fname, sname, inits, lang) # @param [String] initials initials # @param [String] lang language # - # @return [Array<RelatonBib::Forename>] forenames + # @return [Array<Relaton::Bib::Forename>] forenames # def forename(initials, lang = nil, script = nil) return [] unless initials initials.split(/\.-?\s?|\s/).map do |i| - Forename.new(initial: i, language: lang, script: script) + Bib::Forename.new(initial: i, language: lang, script: script) end end # @param author [Nokogiri::XML::Element] - # @return [Array<RelatonBib::Affiliation>] + # @return [Array<Relaton::Bib::Affiliation>] def affiliation(author) o = author.at("./organization") return [] if o.nil? || o.text.empty? org = new_org o.text, o[:abbrev] - [Affiliation.new(organization: org)] + [Bib::Affiliation.new(organization: org)] end # @param name [String] # @param abbr [String, nil] - # @return [RelatonBib::Organization] + # @return [Relaton::Bib::Organization] def new_org(name, abbr = nil) - Organization.new name: name, abbreviation: abbr + Bib::Organization.new name: name, abbreviation: abbr end # @param content [String, nil] # @param lang [String, nil] # @param script [String, nil] - # @return [RelatonBib::LocalizedString, nil] + # @return [Relaton::Bib::LocalizedString, nil] def localized_string(content, lang, script = nil) - LocalizedString.new(content, lang, script) if content + Bib::LocalizedString.new(content: content, laguage: lang, script: script) if content end # @param postal [Nokogiri::XML::Element] - # @return [Array<RelatonBib::Address, RelatonBib::Phone>] + # @return [Array<Relaton::Bib::Address, Relaton::Bib::Phone>] def contacts(addr) conts = [] return conts unless addr @@ -316,10 +313,10 @@ def contacts(addr) end # @param postal [Nokogiri::XML::Element] - # @rerurn [RelatonBib::Address] + # @return [Relaton::Bib::Address] def address(postal) # rubocop:disable Metrics/CyclomaticComplexity street = [postal.at("./postalLine | ./street")&.text].compact - Address.new( + Bib::Address.new( street: street, city: postal.at("./city")&.text, postcode: postal.at("./code")&.text, @@ -328,11 +325,11 @@ def address(postal) # rubocop:disable Metrics/CyclomaticComplexity ) end - # @param conts [Array<RelatonBib::Address, RelatonBib::Contact>] + # @param conts [Array<Relaton::Bib::Address, Relaton::Bib::Contact>] # @param type [String] allowed "phone", "email" or "uri" # @param value [String] def add_contact(conts, type, value) - conts << Contact.new(type: type, value: value.text) if value + conts << Bib::Contact.new(type: type, value: value.text) if value end # @param author [Nokogiri::XML::Document] @@ -353,7 +350,7 @@ def relations(reference) # Extract date from reference. # # @param reference [Nokogiri::XML::Element] - # @return [Array<RelatonBib::BibliographicDate>] published data. + # @return [Array<Relaton::Bib::Bdate>] published data. # def dates(reference) # rubocop:disable Metrics/CyclomaticComplexity, Metrics/AbcSize date = reference.at "./front/date" @@ -363,23 +360,23 @@ def dates(reference) # rubocop:disable Metrics/CyclomaticComplexity, Metrics/Abc d += "-#{month(date[:month])}" if date[:month] && !date[:month].empty? d += "-#{date[:day]}" if date[:day] # date = Time.parse(d).strftime "%Y-%m-%d" - [BibliographicDate.new(type: "published", on: d)] + [Bib::Date.new(type: "published", on: d)] end # @param reference [Nokogiri::XML::Element] - # @return [RelatonBib::EditorialGroup, nil] + # @return [Relaton::Bib::EditorialGroup, nil] def editorialgroup(reference) tc = reference.xpath("./front/workgroup").map do |ed| - wg = WorkGroup.new name: ed.text + wg = Bib::WorkGroup.new name: ed.text committee wg end EditorialGroup.new tc if tc.any? end - # @param [RelatonBib::WorkGroup] - # @return [RelatonBib::TechnicalCommittee] + # @param [Relaton::Bib::WorkGroup] + # @return [Relaton::Bib::TechnicalCommittee] def committee(wgr) - TechnicalCommittee.new wgr + Bib::TechnicalCommittee.new wgr end def month(mon) @@ -393,13 +390,13 @@ def month(mon) # Extract series form reference # @param reference [Nokogiri::XML::Element] # - # @return [Array<RelatonBib::Series>] + # @return [Array<Relaton::Bib::Series>] # def series(reference) reference.xpath("./seriesInfo", "./front/seriesInfo").map do |si| next if SERIESINFONAMES.include?(si[:name]) || si[:stream] || si[:status] - t = TypedTitleString.new( + t = Title.new( content: si[:name], language: language(reference), script: "Latn", ) Series.new(title: t, number: si[:value], type: "main") diff --git a/lib/relaton_bib/deep_dup.rb b/lib/relaton/deep_dup.rb similarity index 100% rename from lib/relaton_bib/deep_dup.rb rename to lib/relaton/deep_dup.rb diff --git a/lib/relaton_bib/renderer/bibtex_builder.rb b/lib/relaton/renderer/bibtex_builder.rb similarity index 86% rename from lib/relaton_bib/renderer/bibtex_builder.rb rename to lib/relaton/renderer/bibtex_builder.rb index 4581395..309fa35 100644 --- a/lib/relaton_bib/renderer/bibtex_builder.rb +++ b/lib/relaton/renderer/bibtex_builder.rb @@ -15,7 +15,7 @@ def to_s(options = {}) # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComp end end -module RelatonBib +module Relaton # BibTeX builder. module Renderer class BibtexBuilder @@ -28,7 +28,7 @@ class BibtexBuilder # # Build BibTeX bibliography. # - # @param bib [RelatonBib::BibliographicItem] + # @param bib [Relaton::Bib::Item] # @param bibtex [BibTeX::Bibliography, nil] BibTeX bibliography # # @return [BibTeX::Bibliography] BibTeX bibliography @@ -40,7 +40,7 @@ def self.build(bib, bibtex = nil) # # Initialize BibTeX builder. # - # @param bib [RelatonBib::BibliographicItem] + # @param bib [Relaton::Bib::Item] def initialize(bib) @bib = bib end @@ -122,7 +122,7 @@ def add_editor # def add_author_editor(type) contribs = @bib.contributor.select do |c| - c.entity.is_a?(Person) && c.role.any? { |e| e.type == type } + c.entity.is_a?(Bib::Person) && c.role.any? { |e| e.type == type } end.map &:entity return unless contribs.any? @@ -133,7 +133,7 @@ def add_author_editor(type) # # Concatenate names of contributors # - # @param [Array<RelatonBib::Person>] contribs contributors + # @param [Array<Relaton::Bib::Person>] contribs contributors # # @return [String] concatenated names # @@ -150,13 +150,13 @@ def concat_names(contribs) # # Add series to BibTeX item # - def add_series + def add_series # rubocop:disable Metrics/AbcSize @bib.series.each do |s| case s.type when "journal" - @item.journal = s.title.title + @item.journal = s.title.first.content @item.number = s.number if s.number - when nil then @item.series = s.title.title + when nil then @item.series = s.title.first.content end end end @@ -169,7 +169,7 @@ def add_number did = @bib.docidentifier.detect { |i| i.primary == true } did ||= @bib.docidentifier.first - @item.number = did.id if did + @item.number = did.content if did end # @@ -219,7 +219,7 @@ def add_address # rubocop:disable Metrics/AbcSize return unless @bib.place.any? reg = @bib.place[0].region[0].name if @bib.place[0].region.any? - addr = [@bib.place[0].name, @bib.place[0].city, reg] + addr = [@bib.place[0].formatted_place, @bib.place[0].city, reg] @item.address = addr.compact.join(", ") end @@ -227,7 +227,7 @@ def add_address # rubocop:disable Metrics/AbcSize # Add note to BibTeX item # def add_note # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity - @bib.biblionote.each do |n| + @bib.note.each do |n| case n.type when "annote" then @item.annote = n.content when "howpublished" then @item.howpublished = n.content @@ -245,7 +245,7 @@ def add_relation rel = @bib.relation.detect { |r| r.type == "partOf" } if rel title_main = rel.bibitem.title.detect { |t| t.type == "main" } - @item.booktitle = title_main.title.content + @item.booktitle = title_main.content end end @@ -262,8 +262,8 @@ def add_extent def add_classification @bib.classification.each do |c| case c.type - when "type" then @item["type"] = c.value - when "mendeley" then @item["mendeley-tags"] = c.value + when "type" then @item["type"] = c.content + when "mendeley" then @item["mendeley-tags"] = c.content end end end @@ -272,7 +272,9 @@ def add_classification # Add keywords to BibTeX item # def add_keyword - @item.keywords = @bib.keyword.map(&:content).join(", ") if @bib.keyword.any? + if @bib.keyword.any? + @item.keywords = @bib.keyword.reduce([]) { |m, kw| m + kw.taxon.map(&:content) }.join(", ") + end end # @@ -281,9 +283,9 @@ def add_keyword def add_docidentifier @bib.docidentifier.each do |i| case i.type - when "isbn" then @item.isbn = i.id - when "lccn" then @item.lccn = i.id - when "issn" then @item.issn = i.id + when "isbn" then @item.isbn = i.content + when "lccn" then @item.lccn = i.content + when "issn" then @item.issn = i.content end end end @@ -299,12 +301,12 @@ def add_timestamp # Add link to BibTeX item # def add_link - @bib.link.each do |l| + @bib.source.each do |l| case l.type&.downcase when "doi" then @item.doi = l.content when "file" then @item.file2 = l.content when "src" then @item.url = l.content - end + end.to_s end end end diff --git a/lib/relaton_bib/renderer/bibxml.rb b/lib/relaton/renderer/bibxml.rb similarity index 66% rename from lib/relaton_bib/renderer/bibxml.rb rename to lib/relaton/renderer/bibxml.rb index 10ae959..a142fe8 100644 --- a/lib/relaton_bib/renderer/bibxml.rb +++ b/lib/relaton/renderer/bibxml.rb @@ -1,4 +1,4 @@ -module RelatonBib +module Relaton module Renderer class BibXML def initialize(bib) @@ -30,10 +30,10 @@ def render(builder: nil, include_keywords: true) # @param [Boolean] include_bibdata # def render_bibxml(builder, include_keywords) # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity - target = @bib.link.detect { |l| l.type.casecmp("src").zero? } || - @bib.link.detect { |l| l.type.casecmp("doi").zero? } - bxml = if @bib.docnumber&.match(/^BCP/) || (@bib.docidentifier.detect(&:primary)&.id || - @bib.docidentifier[0].id).include?("BCP") + target = @bib.source.detect { |l| l.type.casecmp("src").zero? } || + @bib.source.detect { |l| l.type.casecmp("doi").zero? } + bxml = if @bib.docnumber&.match(/^BCP/) || + (@bib.docidentifier.detect(&:primary) || @bib.docidentifier[0])&.content&.include?("BCP") render_bibxml_refgroup(builder, include_keywords) else render_bibxml_ref(builder, include_keywords) @@ -64,10 +64,10 @@ def render_bibxml_refgroup(builder, include_keywords) def render_bibxml_ref(builder, include_keywords) # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/PerceivedComplexity builder.reference(**ref_attrs) do |xml| if @bib.title.any? || @bib.contributor.any? || @bib.date.any? || @bib.abstract.any? || - @bib.editorialgroup&.technical_committee&.any? || + @bib.ext&.editorialgroup&.technical_committee&.any? || (include_keywords && @bib.keyword.any?) xml.front do - xml.title @bib.title[0].title.content if @bib.title.any? + xml.title @bib.title[0].content if @bib.title.any? render_authors xml render_date xml render_workgroup xml @@ -90,13 +90,13 @@ def ref_attrs # rubocop:disable Metrics/AbcSize attrs = @bib.docidentifier.each_with_object({}) do |di, h| next unless discopes.include?(di.scope) - h[di.scope.to_sym] = di.id + h[di.scope.to_sym] = di.content end return attrs if attrs.any? @bib.docidentifier.first&.tap do |di| - anchor = di.type == "IANA" ? di.id.split[1..].join(" ").upcase : di.id - return { anchor: anchor.gsub(" ", ".") } + anchor = di.type == "IANA" ? di.content.split[1..].join(" ").upcase : di.content + return { anchor: anchor.tr(" ", ".") } end end @@ -109,10 +109,10 @@ def render_authors(builder) # rubocop:disable Metrics/AbcSize @bib.contributor.each do |c| builder.author do |xml| xml.parent[:role] = "editor" if c.role.detect { |r| r.type == "editor" } - if c.entity.is_a?(Person) then render_person xml, c.entity + if c.entity.is_a?(Bib::Person) then render_person xml, c.entity else render_organization xml, c.entity, c.role end - render_address xml, c + render_address xml, c.entity end end end @@ -121,53 +121,82 @@ def render_authors(builder) # rubocop:disable Metrics/AbcSize # Render address # # @param [Nokogiri::XML::Builder] builder xml builder - # @param [RelatonBib::ContributionInfo] contrib contributor - # - def render_address(builder, contrib) # rubocop:disable Metrics/AbcSize, Metrics/MethodLength, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity - address, contact = address_contact contrib.entity.contact - if address || contact.any? - builder.address do |xml| - # address = contrib.entity.contact.detect { |cn| cn.is_a? Address } - if address - xml.postal do - xml.city address.city if address.city - xml.code address.postcode if address.postcode - xml.country address.country if address.country - xml.region address.state if address.state - xml.street address.street[0] if address.street.any? - end - end - render_contact xml, contact - end + # @param [Relaton::Bib::ContributionInfo] contrib contributor + # + def render_contacts(builder, contrib) + # address, contact = address_contact contrib.entity.contact + # if address || contact.any? + # contrib.entity.address.each { |address| render_address builder, address } + # render_contact builder, contrib.entity + render_address builder, contrib.entity + end + + def render_address(builder, entity) # rubocop:disable Metrics/AbcSize + return unless entity.address.any? || entity.phone.any? || entity.email.any? || entity.uri.any? + + builder.address do |xml| + render_postal xml, entity.address + render_contact xml, entity.phone.first, "phone" + xml.email entity.email.first if entity.email.any? + render_contact xml, entity.uri.first, "uri" end end - def address_contact(contact) # rubocop:disable Metrics/CyclomaticComplexity,Metrics/PerceivedComplexity - addr = contact.detect do |c| - c.is_a?(Address) && (c.city || c.postcode || c.country || c.state || c.street.any?) + def render_postal(builder, address) # rubocop:disable Metrics/AbcSize,Metrics/CyclomaticComplexity,Metrics/MethodLength,Metrics/PerceivedComplexity + addr = address.find do |a| + a.city || a.postcode || a.country || a.state || a.street.any? + end + + if addr + builder.postal do |xml| + xml.city addr.city if addr.city + xml.code addr.postcode if addr.postcode + xml.country addr.country if addr.country + xml.region addr.state if addr.state + xml.street addr.street[0] if addr.street.any? + end + return + end + + address.select(&:formatted_address).each do |a| + builder.postalLine a.formatted_address end - cont = contact.select { |c| c.is_a?(Contact) } - [addr, cont] end + def render_contact(builder, contact, type) + return unless contact + + builder.send type, contact.content + end + + # def address_contact(contact) # rubocop:disable Metrics/CyclomaticComplexity,Metrics/PerceivedComplexity + # addr = contact.detect do |c| + # c.is_a?(Address) && (c.city || c.postcode || c.country || c.state || c.street.any?) + # end + # cont = contact.select { |c| c.is_a?(Contact) } + # [addr, cont] + # end + # # Render contact # # @param [Nokogiri::XML::Builder] builder xml builder - # @param [Array<RelatonBib::Address, RelatonBib::Contact>] addr contact - # - def render_contact(builder, addr) - %w[phone email uri].each do |type| - cont = addr.detect { |cn| cn.is_a?(Contact) && cn.type == type } - builder.send type, cont.value if cont - end - end + # @param [Array<Relaton::Bib::Address, Relaton::Bib::Contact>] addr contact + # + # def render_contact(builder, entity) + # %w[phone email uri].each do |type| + # entity.send(type).each do |cont| + # # cont = addr.detect { |cn| cn.is_a?(Contact) && cn.type == type } + # builder.send type, cont.value # if cont + # end + # end + # end # # Render person # # @param [Nokogiri::XML::Builder] builder xml builder - # @param [RelatonBib::Person] person person + # @param [Relaton::Bib::Person] person person # def render_person(builder, person) # rubocop:disable Metrics/AbcSize, Metrics/MethodLength, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity render_organization builder, person.affiliation.first&.organization @@ -197,7 +226,7 @@ def render_person(builder, person) # rubocop:disable Metrics/AbcSize, Metrics/Me # Render organization # # @param [Nokogiri::XML::Builder] builder xml builder - # @param [RelatonBib::Organization] org organization + # @param [Relaton::Bib::Organization] org organization # def render_organization(builder, org, _role = []) # rubocop:disable Metrics/PerceivedComplexity, Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/AbcSize abbrev = org&.abbreviation&.content @@ -240,8 +269,8 @@ def render_date(builder) # rubocop:disable Metrics/AbcSize, Metrics/MethodLength # @param [Nokogiri::XML::Builder] builder xml builder # def render_workgroup(builder) - @bib.editorialgroup&.technical_committee&.each do |tc| - builder.workgroup tc.workgroup.name + @bib.ext&.editorialgroup&.technical_committee&.each do |tc| + builder.workgroup tc.content end end @@ -273,21 +302,23 @@ def render_abstract(builder) def render_seriesinfo(builder) # rubocop:disable Metrics/AbcSize, Metrics/MethodLength, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity @bib.docidentifier.each do |di| if BibXMLParser::SERIESINFONAMES.include?(di.type) && di.scope != "trademark" - builder.seriesInfo(name: di.type, value: di.id) + builder.seriesInfo(name: di.type, value: di.content) end end - # di_types = docidentifier.map(&:type) + @bib.series.select do |s| - s.title && # !di_types.include?(s.title.title.to_s) && - !BibXMLParser::SERIESINFONAMES.include?(s.title.title.to_s) - end.uniq { |s| s.title.title.to_s }.each do |s| - si = builder.seriesInfo(name: s.title.title.to_s) + s.title.reject { |t| BibXMLParser::SERIESINFONAMES.include?(t.content) }.any? + end.uniq do |s| + s.title.find { |t| !BibXMLParser::SERIESINFONAMES.include?(t.content)}.content + end.each do |s| + title = s.title.find { |t| !BibXMLParser::SERIESINFONAMES.include?(t.content) } + si = builder.seriesInfo(name: title.content) si[:value] = s.number if s.number end end def render_format(builder) - @bib.link.select { |l| l.type == "TXT" }.each do |l| + @bib.source.select { |l| l.type == "TXT" }.each do |l| builder.format type: l.type, target: l.content end end diff --git a/lib/relaton_bib/bib_item_locality.rb b/lib/relaton_bib/bib_item_locality.rb deleted file mode 100644 index 4ec9db0..0000000 --- a/lib/relaton_bib/bib_item_locality.rb +++ /dev/null @@ -1,175 +0,0 @@ -module RelatonBib - # Bibliographic item locality. - class BibItemLocality - # @return [String] - attr_reader :type - - # @return [String] - attr_reader :reference_from - - # @return [String, nil] - attr_reader :reference_to - - # @param type [String] - # @param referenceFrom [String] - # @param referenceTo [String, nil] - def initialize(type, reference_from, reference_to = nil) - type_ptrn = %r{section|clause|part|paragraph|chapter|page|title|line| - whole|table|annex|figure|note|list|example|volume|issue|time|anchor| - locality:[a-zA-Z0-9_]+}x - unless type&.match? type_ptrn - Util.warn "Invalid locality type: `#{type}`" - end - - @type = type - @reference_from = reference_from - @reference_to = reference_to - end - - # @param builder [Nokogiri::XML::Builder] - def to_xml(builder) - builder.parent[:type] = type - builder.referenceFrom reference_from # { reference_from.to_xml(builder) } - builder.referenceTo reference_to if reference_to - end - - # @return [Hash] - def to_hash - hash = { "type" => type, "reference_from" => reference_from } - hash["reference_to"] = reference_to if reference_to - hash - end - - # @param prefix [String] - # @param count [Integeg] number of localities - # @return [String] - def to_asciibib(prefix = "", count = 1) - pref = prefix.empty? ? prefix : "#{prefix}." - out = count > 1 ? "#{prefix}::\n" : "" - out += "#{pref}type:: #{type}\n" - out += "#{pref}reference_from:: #{reference_from}\n" - out += "#{pref}reference_to:: #{reference_to}\n" if reference_to - out - end - - # - # Render locality as BibTeX. - # - # @param [BibTeX::Entry] item BibTeX entry. - # - def to_bibtex(item) - case type - when "chapter" then item.chapter = reference_from - when "page" - value = reference_from - value += "--#{reference_to}" if reference_to - item.pages = value - when "volume" then item.volume = reference_from - when "issue" then item.number = reference_from - end - end - end - - class Locality < BibItemLocality - # @param builder [Nokogiri::XML::Builder] - def to_xml(builder) - builder.locality { |b| super(b) } - end - - # - # Render locality as hash. - # - # @return [Hash] locality as hash. - # - def to_hash - { "locality" => super } - end - - # - # Render locality as AsciiBib. - # - # @param [String] prefix prefix of locality - # @param [Integer] count number of localities - # - # @return [String] AsciiBib. - # - def to_asciibib(prefix = "", count = 1) - pref = prefix.empty? ? "locality" : "#{prefix}.locality" - super(pref, count) - end - end - - class LocalityStack - include RelatonBib - - # @return [Array<RelatonBib::Locality>] - attr_reader :locality - - # @param locality [Array<RelatonBib::Locality>] - def initialize(locality) - @locality = locality - end - - # @param builder [Nokogiri::XML::Builder] - def to_xml(builder) - builder.localityStack do |b| - locality.each { |l| l.to_xml(b) } - end - end - - # @returnt [Hash] - def to_hash - hash = Hash.new { |h, k| h[k] = [] } - locality.each_with_object(hash) do |l, obj| - k, v = l.to_hash.first - obj[k] << v - end - { "locality_stack" => hash } - end - - # - # Render locality stack as AsciiBib. - # - # @param [String] prefix <description> - # @param [Integer] size size of locality stack - # - # @return [String] AsciiBib. - # - def to_asciibib(prefix = "", size = 1) - pref = prefix.empty? ? "locality_stack" : "#{prefix}.locality_stack" - out = "" - out << "#{pref}::\n" if size > 1 - out << locality.map { |l| l.to_asciibib(pref, locality.size) }.join - end - - # - # Render locality stack as BibTeX. - # - # @param [BibTeX::Entry] item BibTeX entry. - # - def to_bibtex(item) - locality.each { |l| l.to_bibtex(item) } - end - end - - class SourceLocality < BibItemLocality - # @param builder [Nokogiri::XML::Builder] - def to_xml(builder) - builder.sourceLocality { |b| super(b) } - end - end - - class SourceLocalityStack < LocalityStack - # @param builder [Nokogiri::XML::Builder] - def to_xml(builder) - builder.sourceLocalityStack do |b| - locality.each { |l| l.to_xml(b) } - end - end - - # @returnt [Hash] - def to_hash - { "source_locality_stack" => single_element_array(locality) } - end - end -end diff --git a/lib/relaton_bib/biblio_note.rb b/lib/relaton_bib/biblio_note.rb deleted file mode 100644 index 4eb642d..0000000 --- a/lib/relaton_bib/biblio_note.rb +++ /dev/null @@ -1,72 +0,0 @@ -module RelatonBib - class BiblioNoteCollection - extend Forwardable - - def_delegators :@array, :[], :first, :last, :empty?, :any?, :size, - :each, :map, :reduce, :detect, :length - - def initialize(notes) - @array = notes - end - - # @param bibnote [RelatonBib::BiblioNote] - # @return [self] - def <<(bibnote) - @array << bibnote - self - end - - # @param opts [Hash] - # @option opts [Nokogiri::XML::Builder] XML builder - # @option opts [String] :lang language - def to_xml(**opts) - bnc = @array.select { |bn| bn.language&.include? opts[:lang] } - bnc = @array unless bnc.any? - bnc.each { |bn| bn.to_xml opts[:builder] } - end - end - - class BiblioNote < FormattedString - # @return [String, nil] - attr_reader :type - - # @param content [String] - # @param type [String, nil] - # @param language [String, nil] language code Iso639 - # @param script [String, nil] script code Iso15924 - # @param format [String, nil] the content format - def initialize(content:, type: nil, language: nil, script: nil, format: nil) - @type = type - super content: content, language: language, script: script, format: format - end - - # @param builder [Nokogiri::XML::Builder] - def to_xml(builder) - xml = builder.note { super } - xml[:type] = type if type - xml - end - - # @return [Hash] - def to_hash - hash = super - return hash unless type - - hash = { "content" => hash } if hash.is_a? String - hash["type"] = type - hash - end - - # @param prefix [String] - # @param count [Integer] number of notes - # @return [String] - def to_asciibib(prefix = "", count = 1) - pref = prefix.empty? ? prefix : prefix + "." - has_attrs = !(type.nil? || type.empty?) - out = count > 1 && has_attrs ? "#{pref}biblionote::\n" : "" - out += "#{pref}biblionote.type:: #{type}\n" if type - out += super "#{pref}biblionote", 1, has_attrs - out - end - end -end diff --git a/lib/relaton_bib/biblio_version.rb b/lib/relaton_bib/biblio_version.rb deleted file mode 100644 index dfc23b8..0000000 --- a/lib/relaton_bib/biblio_version.rb +++ /dev/null @@ -1,46 +0,0 @@ -module RelatonBib - # Version - class BibliographicItem - class Version - include RelatonBib - - # @return [String, nil] - attr_reader :revision_date, :draft - - # @param revision_date [String, nil] - # @param draft [String, nil] - def initialize(revision_date = nil, draft = nil) - @revision_date = revision_date - @draft = draft - end - - # @param builder [Nokogiri::XML::Builder] - def to_xml(builder) - builder.version do - builder.send(:"revision-date", revision_date) if revision_date - builder.draft draft if draft - end - end - - # @return [Hash] - def to_hash - hash = {} - hash["revision_date"] = revision_date if revision_date - hash["draft"] = draft if draft - hash - end - - # @param prefix [String] - # @return [String] - def to_asciibib(prefix = "", count = 1) - pref = prefix.empty? ? prefix : "#{prefix}." - out = count > 1 ? "#{prefix}version::\n" : "" - if revision_date - out += "#{pref}version.revision_date:: #{revision_date}\n" - end - out += "#{pref}version.draft:: #{draft}\n" if draft - out - end - end - end -end diff --git a/lib/relaton_bib/bibliographic_date.rb b/lib/relaton_bib/bibliographic_date.rb deleted file mode 100644 index 3ea3608..0000000 --- a/lib/relaton_bib/bibliographic_date.rb +++ /dev/null @@ -1,119 +0,0 @@ -# frozen_string_literal: true - -require "time" - -module RelatonBib - # Bibliographic date. - class BibliographicDate - TYPES = %w[published accessed created implemented obsoleted confirmed - updated corrected issued transmitted copied unchanged circulated adapted - vote-started vote-ended announced stable-until].freeze - - # @return [String] - attr_reader :type - - # @param type [String] "published", "accessed", "created", "activated" - # @param on [String] - # @param from [String] - # @param to [String] - def initialize(type:, on: nil, from: nil, to: nil) - raise ArgumentError, "expected :on or :from argument" unless on || from - - # raise ArgumentError, "invalid type: #{type}" unless TYPES.include? type - - @type = type - @on = RelatonBib.parse_date on - @from = RelatonBib.parse_date from - @to = RelatonBib.parse_date to - end - - # @param part [Symbol] :year, :month, :day, :date - # @return [String, Date, nil] - def from(part = nil) # rubocop:disable Metrics/MethodLength, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity - d = instance_variable_get "@#{__callee__}".to_sym - return d unless part && d - - # date = parse_date(d) - # return date if part == :date - - parts = d.split "-" - case part - when :year then parts[0]&.to_i - when :month then parts[1]&.to_i - when :day then parts[2]&.to_i - when :date then parse_date(d) - else d - end - - # date.is_a?(Date) ? date.send(part) : date - end - - alias_method :to, :from - alias_method :on, :from - - # rubocop:disable Metrics/AbcSize - - # @param builder [Nokogiri::XML::Builder] - # @return [Nokogiri::XML::Builder] - def to_xml(builder, **opts) - builder.date(type: type) do - if on - builder.on(opts[:no_year] ? "--" : date_format(on, opts[:date_format])) - elsif from - builder.from(opts[:no_year] ? "--" : date_format(from, opts[:date_format])) - builder.to date_format(to, opts[:date_format]) if to - end - end - end - # rubocop:enable Metrics/AbcSize - - # @return [Hash] - def to_hash - hash = { "type" => type } - hash["value"] = on.to_s if on - hash["from"] = from.to_s if from - hash["to"] = to.to_s if to - hash - end - - # @param prefix [String] - # @param count [Integer] number of dates - # @return [String] - def to_asciibib(prefix = "", count = 1) - pref = prefix.empty? ? prefix : "#{prefix}." - out = count > 1 ? "#{pref}date::\n" : "" - out += "#{pref}date.type:: #{type}\n" - out += "#{pref}date.on:: #{on}\n" if on - out += "#{pref}date.from:: #{from}\n" if from - out += "#{pref}date.to:: #{to}\n" if to - out - end - - private - - # Formats date - # @param date [String] - # @param format [Symbol, nil] :full (yyyy-mm-dd), :short (yyyy-mm) or nil - # @return [String] - def date_format(date, format = nil) - tmplt = case format - when :short then "%Y-%m" - when :full then "%Y-%m-%d" - else return date - end - d = parse_date(date) - d.is_a?(Date) ? d.strftime(tmplt) : d - end - - # @param date [String] - # @return [Date] - def parse_date(date) - case date - when /^\d{4}-\d{1,2}-\d{1,2}/ then Date.parse(date) # 2012-02-11 - when /^\d{4}-\d{1,2}/ then Date.strptime(date, "%Y-%m") # 2012-02 - when /^\d{4}/ then Date.strptime(date, "%Y") # 2012 - else date - end - end - end -end diff --git a/lib/relaton_bib/bibliographic_item.rb b/lib/relaton_bib/bibliographic_item.rb deleted file mode 100644 index 1cbb837..0000000 --- a/lib/relaton_bib/bibliographic_item.rb +++ /dev/null @@ -1,668 +0,0 @@ -# frozen_string_literal: true - -require "relaton_bib/typed_uri" -require "relaton_bib/document_identifier" -require "relaton_bib/copyright_association" -require "relaton_bib/formatted_string" -require "relaton_bib/contribution_info" -require "relaton_bib/bibliographic_date" -require "relaton_bib/series" -require "relaton_bib/document_status" -require "relaton_bib/organization" -require "relaton_bib/document_relation_collection" -require "relaton_bib/typed_title_string" -require "relaton_bib/formatted_ref" -require "relaton_bib/medium" -require "relaton_bib/classification" -require "relaton_bib/validity" -require "relaton_bib/document_relation" -require "relaton_bib/bib_item_locality" -require_relative "extent" -require "relaton_bib/xml_parser" -require "relaton_bib/bibtex_parser" -require "relaton_bib/biblio_note" -require "relaton_bib/biblio_version" -require "relaton_bib/workers_pool" -require "relaton_bib/hash_converter" -require "relaton_bib/place" -require "relaton_bib/structured_identifier" -require "relaton_bib/editorial_group" -require "relaton_bib/ics" -require "relaton_bib/bibliographic_size" -require "relaton_bib/edition" - -module RelatonBib - # Bibliographic item - class BibliographicItem - include RelatonBib - - TYPES = %W[article book booklet manual proceedings presentation - thesis techreport standard unpublished map electronic\sresource - audiovisual film video broadcast software graphic_work music - patent inbook incollection inproceedings journal website - webresource dataset archival social_media alert message - conversation collection misc internal].freeze # internal is defined in isodoc grammar - - # @return [Boolean, nil] - attr_accessor :all_parts - - # @return [String, nil] - attr_reader :id, :type, :docnumber, :subdoctype - - # @return [RelatonBib::DocumentType] document type - attr_reader :doctype - - # @return [RelatonBib::Edition, nil] edition - attr_reader :edition - - # @!attribute [r] title - # @return [RelatonBib::TypedTitleStringCollection] - - # @return [Array<RelatonBib::TypedUri>] - attr_reader :link - - # @return [Array<RelatonBib::DocumentIdentifier>] - attr_reader :docidentifier - - # @return [Array<RelatonBib::BibliographicDate>] - attr_writer :date - - # @return [Array<RelatonBib::ContributionInfo>] - attr_reader :contributor - - # @return [Array<RelatonBib::BibliographicItem::Version>] - attr_reader :version - - # @return [RelatonBib::BiblioNoteCollection] - attr_reader :biblionote - - # @return [Array<String>] language Iso639 code - attr_reader :language - - # @return [Array<String>] script Iso15924 code - attr_reader :script - - # @return [RelatonBib::FormattedRef, nil] - attr_reader :formattedref - - # @!attribute [r] abstract - # @return [Array<RelatonBib::FormattedString>] - - # @return [RelatonBib::DocumentStatus, nil] - attr_reader :status - - # @return [Array<RelatonBib::CopyrightAssociation>] - attr_reader :copyright - - # @return [RelatonBib::DocRelationCollection] - attr_reader :relation - - # @return [Array<RelatonBib::Series>] - attr_reader :series - - # @return [RelatonBib::Medium, nil] - attr_reader :medium - - # @return [Array<RelatonBib::Place>] - attr_reader :place - - # @return [Array<RelatonBib::Extent>] - attr_reader :extent - - # @return [Array<Strig>] - attr_reader :accesslocation, :license - - # @return [Array<Relaton::Classification>] - attr_reader :classification - - # @return [RelatonBib:Validity, nil] - attr_reader :validity - - # @return [Date] - attr_accessor :fetched - - # @return [Array<RelatonBib::LocalizedString>] - attr_reader :keyword - - # @return [RelatonBib::EditorialGroup, nil] - attr_reader :editorialgroup - - # @return [Array<RelatonBib:ICS>] - attr_reader :ics - - # @return [RelatonBib::StructuredIdentifierCollection] - attr_reader :structuredidentifier - - # @return [RelatonBib::BibliographicSize, nil] - attr_reader :size - - # rubocop:disable Metrics/MethodLength, Metrics/AbcSize - # rubocop:disable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity - - # @param id [String, nil] - # @param title [RelatonBib::TypedTitleStringCollection, - # Array<Hash, RelatonBib::TypedTitleString>] - # @param formattedref [RelatonBib::FormattedRef, nil] - # @param type [String, nil] - # @param docid [Array<RelatonBib::DocumentIdentifier>] - # @param docnumber [String, nil] - # @param language [Arra<String>] - # @param script [Array<String>] - # @param docstatus [RelatonBib::DocumentStatus, nil] - # @param edition [RelatonBib::Edition, String, Integer, Float, nil] - # @param version [Array<RelatonBib::BibliographicItem::Version>] - # @param biblionote [RelatonBib::BiblioNoteCollection] - # @param series [Array<RelatonBib::Series>] - # @param medium [RelatonBib::Medium, nil] - # @param place [Array<String, RelatonBib::Place>] - # @param extent [Array<RelatonBib::Extent>] - # @param accesslocation [Array<String>] - # @param classification [Array<RelatonBib::Classification>] - # @param validity [RelatonBib:Validity, nil] - # @param fetched [Date, nil] default nil - # @param keyword [Array<String>] - # @param doctype [RelatonBib::DocumentType] - # @param subdoctype [String] - # @param editorialgroup [RelatonBib::EditorialGroup, nil] - # @param ics [Array<RelatonBib::ICS>] - # @param structuredidentifier [RelatonBib::StructuredIdentifierCollection] - # @param size [RelatonBib::BibliographicSize, nil] - # - # @param copyright [Array<Hash, RelatonBib::CopyrightAssociation>] - # @option copyright [Array<Hash, RelatonBib::ContributionInfo>] :owner - # @option copyright [String] :from - # @option copyright [String, nil] :to - # @option copyright [String, nil] :scope - # - # @param date [Array<Hash, RelatonBib::BibliographicDate>] - # @option date [String] :type - # @option date [String, nil] :from required if :on is nil - # @option date [String, nil] :to - # @option date [String, nil] :on required if :from is nil - # - # @param contributor [Array<Hash, RelatonBib::ContributionInfo>] - # @option contributor [RealtonBib::Organization, RelatonBib::Person] :entity - # @option contributor [String] :type - # @option contributor [String] :from - # @option contributor [String] :to - # @option contributor [String] :abbreviation - # @option contributor [Array<Array<String,Array<String>>>] :role - # - # @param abstract [Array<Hash, RelatonBib::FormattedString>] - # @option abstract [String] :content - # @option abstract [String] :language - # @option abstract [String] :script - # @option abstract [String] :format - # - # @param relation [Array<Hash>] - # @option relation [String] :type - # @option relation [RelatonBib::BibliographicItem, - # RelatonIso::IsoBibliographicItem] :bibitem - # @option relation [Array<RelatonBib::Locality, - # RelatonBib::LocalityStack>] :locality - # @option relation [Array<RelatonBib::SourceLocality, - # RelatonBib::SourceLocalityStack>] :source_locality - # - # @param link [Array<Hash, RelatonBib::TypedUri>] - # @option link [String] :type - # @option link [String] :content - def initialize(**args) - if args[:type] && !TYPES.include?(args[:type]) - Util.warn %{Type `#{args[:type]}` is invalid.} - end - - @title = if args[:title].is_a?(TypedTitleStringCollection) - args[:title] - else - TypedTitleStringCollection.new(args[:title]) - end - - @date = (args[:date] || []).map do |d| - d.is_a?(Hash) ? BibliographicDate.new(**d) : d - end - - @contributor = (args[:contributor] || []).map do |c| - if c.is_a? Hash - e = c[:entity].is_a?(Hash) ? Organization.new(**c[:entity]) : c[:entity] - ContributionInfo.new(entity: e, role: c[:role]) - else c - end - end - - @abstract = (args[:abstract] || []).map do |a| - a.is_a?(Hash) ? FormattedString.new(**a) : a - end - - @copyright = args.fetch(:copyright, []).map do |c| - c.is_a?(Hash) ? CopyrightAssociation.new(**c) : c - end - - @docidentifier = args[:docid] || [] - @formattedref = args[:formattedref] if title.empty? - @id = args[:id] || makeid(nil, false) - @type = args[:type] - @docnumber = args[:docnumber] - @edition = case args[:edition] - when Hash then Edition.new(**args[:edition]) - when String, Integer, Float - Edition.new(content: args[:edition].to_s) - when Edition then args[:edition] - end - @version = args.fetch :version, [] - @biblionote = args.fetch :biblionote, BiblioNoteCollection.new([]) - @language = args.fetch :language, [] - @script = args.fetch :script, [] - @status = args[:docstatus] - @relation = DocRelationCollection.new(args[:relation] || []) - @link = args.fetch(:link, []).map do |s| - case s - when Hash then TypedUri.new(**s) - when String then TypedUri.new(content: s) - else s - end - end - @series = args.fetch :series, [] - @medium = args[:medium] - @place = args.fetch(:place, []).map do |pl| - pl.is_a?(String) ? Place.new(name: pl) : pl - end - @extent = args[:extent] || [] - @size = args[:size] - @accesslocation = args.fetch :accesslocation, [] - @classification = args.fetch :classification, [] - @validity = args[:validity] - # we should pass the fetched arg from scrappers - @fetched = args.fetch :fetched, nil - @keyword = (args[:keyword] || []).map do |kw| - case kw - when Hash then LocalizedString.new(kw[:content], kw[:language], kw[:script]) - when String then LocalizedString.new(kw) - else kw - end - end - @license = args.fetch :license, [] - @doctype = args[:doctype] - @subdoctype = args[:subdoctype] - @editorialgroup = args[:editorialgroup] - @ics = args.fetch :ics, [] - @structuredidentifier = args[:structuredidentifier] - end - # rubocop:enable Metrics/MethodLength, Metrics/AbcSize - # rubocop:enable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity - - # - # Fetch schema version - # - # @return [String] schema version - # - def schema - @schema ||= schema_versions["relaton-models"] - end - - # - # Read schema versions from file - # - # @return [Hash{String=>String}] schema versions - # - def schema_versions - JSON.parse File.read(File.join(__dir__, "../../grammars/versions.json")) - end - - # @param hash [Hash] - # @return [RelatonBipm::BipmBibliographicItem] - def self.from_hash(hash) - item_hash = Object.const_get(name.split("::")[0])::HashConverter.hash_to_bib(hash) - new(**item_hash) - end - - # - # @param [String, nil] type if nil return all dates else return dates with type - # - # @return [Array<RelatonBib::BibliographicDate>] - # - def date(type: nil) - type ? @date.select { |d| d.type == type } : @date - end - - # @param lang [String] language code Iso639 - # @return [RelatonBib::FormattedString, Array<RelatonBib::FormattedString>] - def abstract(lang: nil) - if lang - @abstract.detect { |a| a.language&.include? lang } - else - @abstract - end - end - - # @param identifier [RelatonBib::DocumentIdentifier, nil] - # @param attribute [Boolean, nil] - # @return [String] - def makeid(identifier, attribute) - return nil if attribute && !@id_attribute - - identifier ||= @docidentifier.reject { |i| i.type == "DOI" }[0] - return unless identifier - - idstr = identifier.id.gsub(/[:\/]/, "-").gsub(/[\s\(\)]/, "") - idstr.strip - end - - # @param identifier [RelatonBib::DocumentIdentifier] - # @param options [Hash] - # @option options [boolean, nil] :no_year - # @option options [boolean, nil] :all_parts - # @return [String] - def shortref(identifier, **opts) # rubocop:disable Metrics/CyclomaticComplexity,Metrics/AbcSize,Metrics/PerceivedComplexity - pubdate = date.select { |d| d.type == "published" || d.type == "issued" } - year = if opts[:no_year] || pubdate.empty? then "" - else ":#{pubdate&.first&.on(:year)}" - end - year += ": All Parts" if opts[:all_parts] || @all_parts - - "#{makeid(identifier, false)}#{year}" - end - - # @param opts [Hash] - # @option opts [Nokogiri::XML::Builder] :builder XML builder - # @option opts [Boolean] :bibdata - # @option opts [Symbol, nil] :date_format (:short), :full - # @option opts [String, Symbol] :lang language - # @return [String] XML - def to_xml(**opts, &block) - if opts[:builder] - render_xml(**opts, &block) - else - Nokogiri::XML::Builder.new(encoding: "UTF-8") do |xml| - render_xml builder: xml, **opts, &block - end.doc.root.to_xml - end - end - - # - # Render BibXML (RFC) - # - # @param [Nokogiri::XML::Builder, nil] builder - # @param [Boolean] include_keywords (false) - # - # @return [String, Nokogiri::XML::Builder::NodeBuilder] XML - # - def to_bibxml(builder = nil, include_keywords: false) - Renderer::BibXML.new(self).render builder: builder, include_keywords: include_keywords - end - - # @return [Hash] - def to_hash(embedded: false) # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/PerceivedComplexity - hash = {} - hash["schema-version"] = schema unless embedded - hash["id"] = id if id - hash["title"] = title.to_hash if title&.any? - hash["link"] = single_element_array(link) if link&.any? - hash["type"] = type if type - hash["docid"] = single_element_array(docidentifier) if docidentifier&.any? - hash["docnumber"] = docnumber if docnumber - hash["date"] = single_element_array(date) if date&.any? - if contributor&.any? - hash["contributor"] = single_element_array(contributor) - end - hash["edition"] = edition.to_hash if edition - hash["version"] = version.map &:to_hash if version.any? - hash["revdate"] = revdate if revdate - hash["biblionote"] = single_element_array(biblionote) if biblionote&.any? - hash["language"] = single_element_array(language) if language&.any? - hash["script"] = single_element_array(script) if script&.any? - hash["formattedref"] = formattedref.to_hash if formattedref - hash["abstract"] = single_element_array(abstract) if abstract&.any? - hash["docstatus"] = status.to_hash if status - hash["copyright"] = single_element_array(copyright) if copyright&.any? - hash["relation"] = single_element_array(relation) if relation&.any? - hash["series"] = single_element_array(series) if series&.any? - hash["medium"] = medium.to_hash if medium - hash["place"] = single_element_array(place) if place&.any? - hash["extent"] = extent.map(&:to_hash) if extent&.any? - hash["size"] = size.to_hash if size&.any? - if accesslocation&.any? - hash["accesslocation"] = single_element_array(accesslocation) - end - if classification&.any? - hash["classification"] = single_element_array(classification) - end - hash["validity"] = validity.to_hash if validity - hash["fetched"] = fetched.to_s if fetched - hash["keyword"] = single_element_array(keyword) if keyword&.any? - hash["license"] = single_element_array(license) if license&.any? - if has_ext? - hash["ext"] = {} - hash["ext"]["schema-version"] = ext_schema if !embedded && respond_to?(:ext_schema) && ext_schema - hash["ext"]["doctype"] = doctype.to_hash if doctype - hash["ext"]["subdoctype"] = subdoctype if subdoctype - hash["ext"]["editorialgroup"] = editorialgroup.to_hash if editorialgroup&.presence? - hash["ext"]["ics"] = single_element_array ics if ics.any? - hash["ext"]["structuredidentifier"] = structuredidentifier.to_hash if structuredidentifier&.presence? - end - hash - end - - # - # Reander BibTeX - # - # @param bibtex [BibTeX::Bibliography, nil] - # - # @return [String] - # - def to_bibtex(bibtex = nil) - Renderer::BibtexBuilder.build(self, bibtex).to_s - end - - # - # Render citeproc - # - # @param bibtex [BibTeX::Bibliography, nil] - # - # @return [Hash] citeproc - # - def to_citeproc(bibtex = nil) - Renderer::BibtexBuilder.build(self, bibtex).to_citeproc.map do |cp| - cp.transform_keys(&:to_s) - end - end - - # @param lang [String, nil] language code Iso639 - # @return [RelatonIsoBib::TypedTitleStringCollection] - def title(lang: nil) - @title.lang lang - end - - # @param type [Symbol] type of url, can be :src/:obp/:rss - # @return [String, nil] - def url(type = :src) - @link.detect { |s| s.type == type.to_s }&.content&.to_s - end - - def abstract=(value) - @abstract = value - end - - def deep_clone - dump = Marshal.dump self - Marshal.load dump # rubocop:disable Security/MarshalLoad - end - - def disable_id_attribute - @id_attribute = false - end - - # remove title part components and abstract - def to_all_parts # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength,Metrics/PerceivedComplexity - me = deep_clone - me.disable_id_attribute - me.relation << DocumentRelation.new(type: "instanceOf", bibitem: self) - me.language.each do |l| - me.title.delete_title_part! - ttl = me.title.select do |t| - t.type != "main" && t.title.language&.include?(l) - end - next if ttl.empty? - - tm_en = ttl.map { |t| t.title.content }.join " – " - me.title.detect do |t| - t.type == "main" && t.title.language&.include?(l) - end&.title&.content = tm_en - end - me.abstract = [] - me.docidentifier.each(&:remove_part) - me.docidentifier.each(&:all_parts) - me.structuredidentifier.remove_part - me.structuredidentifier.all_parts - me.docidentifier.each &:remove_date - me.structuredidentifier&.remove_date - me.all_parts = true - me - end - - # convert ISO:yyyy reference to reference to most recent - # instance of reference, removing date-specific infomration: - # date of publication, abstracts. Make dated reference Instance relation - # of the redacated document - def to_most_recent_reference - me = deep_clone - disable_id_attribute - me.relation << DocumentRelation.new(type: "instanceOf", bibitem: self) - me.abstract = [] - me.date = [] - me.docidentifier.each &:remove_date - me.structuredidentifier&.remove_date - me.id&.sub!(/-[12]\d\d\d/, "") - me - end - - # If revision_date exists then returns it else returns published date or nil - # @return [String, nil] - def revdate # rubocop:disable Metrics/CyclomaticComplexity,Metrics/PerceivedComplexity - @revdate ||= if (v = version.detect &:revision_date) - v.revision_date - else - date.detect { |d| d.type == "published" }&.on&.to_s - end - end - - # @param prefix [String] - # @return [String] - def to_asciibib(prefix = "") # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/PerceivedComplexity - pref = prefix.empty? ? prefix : "#{prefix}." - out = prefix.empty? ? "[%bibitem]\n== {blank}\n" : "" - out += "#{pref}id:: #{id}\n" if id - out += "#{pref}fetched:: #{fetched}\n" if fetched - title.each { |t| out += t.to_asciibib(prefix, title.size) } - out += "#{pref}type:: #{type}\n" if type - docidentifier.each do |di| - out += di.to_asciibib prefix, docidentifier.size - end - out += "#{pref}docnumber:: #{docnumber}\n" if docnumber - out += edition.to_asciibib(prefix) if edition - language.each { |l| out += "#{pref}language:: #{l}\n" } - script.each { |s| out += "#{pref}script:: #{s}\n" } - version.each { |v| out += v.to_asciibib prefix, version.size } - biblionote&.each { |b| out += b.to_asciibib prefix, biblionote.size } - out += status.to_asciibib prefix if status - date.each { |d| out += d.to_asciibib prefix, date.size } - abstract.each do |a| - out += a.to_asciibib "#{pref}abstract", abstract.size - end - copyright.each { |c| out += c.to_asciibib prefix, copyright.size } - link.each { |l| out += l.to_asciibib prefix, link.size } - out += medium.to_asciibib prefix if medium - place.each { |pl| out += pl.to_asciibib prefix, place.size } - extent.each { |ex| out += ex.to_asciibib prefix, extent.size } - out += size.to_asciibib pref if size - accesslocation.each { |al| out += "#{pref}accesslocation:: #{al}\n" } - classification.each do |cl| - out += cl.to_asciibib prefix, classification.size - end - out += validity.to_asciibib prefix if validity - contributor.each do |c| - out += c.to_asciibib "contributor.*", contributor.size - end - out += relation.to_asciibib prefix if relation - series.each { |s| out += s.to_asciibib prefix, series.size } - out += doctype.to_asciibib prefix if doctype - out += "#{pref}subdoctype:: #{subdoctype}\n" if subdoctype - out += "#{pref}formattedref:: #{formattedref}\n" if formattedref - keyword.each { |kw| out += kw.to_asciibib "#{pref}keyword", keyword.size } - out += editorialgroup.to_asciibib prefix if editorialgroup - ics.each { |i| out += i.to_asciibib prefix, ics.size } - out += structuredidentifier.to_asciibib prefix if structuredidentifier - out - end - - private - - # @param opts [Hash] - # @option opts [Nokogiri::XML::Builder] :builder XML builder - # @option opts [Boolean] bibdata - # @option opts [Symbol, nil] :date_format (:short), :full - # @option opts [String] :lang language - def render_xml(**opts) # rubocop:disable Metrics/AbcSize,Metrics/MethodLength,Metrics/CyclomaticComplexity,Metrics/PerceivedComplexity - root = opts[:bibdata] ? :bibdata : :bibitem - xml = opts[:builder].send(root) do |builder| # rubocop:disable Metrics/BlockLength - builder.fetched fetched if fetched - title.to_xml(**opts) - formattedref&.to_xml builder - link.each { |s| s.to_xml builder } - docidentifier.each { |di| di.to_xml(**opts) } - builder.docnumber docnumber if docnumber - date.each { |d| d.to_xml builder, **opts } - contributor.each do |c| - builder.contributor do - c.role.each { |r| r.to_xml(**opts) } - c.to_xml(**opts) - end - end - edition&.to_xml builder - version.each { |v| v.to_xml builder } - biblionote.to_xml(**opts) - opts[:note]&.each do |n| - builder.note(n[:text], format: "text/plain", type: n[:type]) - end - language.each { |l| builder.language l } - script.each { |s| builder.script s } - abstr = abstract.select { |ab| ab.language&.include? opts[:lang] } - abstr = abstract unless abstr.any? - abstr.each { |a| builder.abstract { a.to_xml(builder) } } - status&.to_xml builder - copyright&.each { |c| c.to_xml(**opts) } - relation.each { |r| r.to_xml builder, **opts } - series.each { |s| s.to_xml builder } - medium&.to_xml builder - place.each { |pl| pl.to_xml builder } - extent.each { |e| e.to_xml builder } - size&.to_xml builder - accesslocation.each { |al| builder.accesslocation al } - license.each { |l| builder.license l } - classification.each { |cls| cls.to_xml builder } - kwrd = keyword.select { |kw| kw.language&.include? opts[:lang] } - kwrd = keyword unless kwrd.any? - kwrd.each { |kw| builder.keyword { kw.to_xml(builder) } } - validity&.to_xml builder - if block_given? then yield builder - elsif opts[:bibdata] && has_ext? - ext = builder.ext do |b| - doctype&.to_xml b - b.subdoctype subdoctype if subdoctype - editorialgroup&.to_xml b - ics.each { |i| i.to_xml b } - structuredidentifier&.to_xml b - end - ext["schema-version"] = ext_schema if !opts[:embedded] && respond_to?(:ext_schema) && ext_schema - end - end - xml[:id] = id if id && !opts[:bibdata] && !opts[:embedded] - xml[:type] = type if type - xml["schema-version"] = schema unless opts[:embedded] - xml - end - - def has_ext? # rubocop:disable Metrics/CyclomaticComplexity - doctype || subdoctype || editorialgroup || ics&.any? || structuredidentifier&.presence? - end - end -end diff --git a/lib/relaton_bib/bibliographic_size.rb b/lib/relaton_bib/bibliographic_size.rb deleted file mode 100644 index 98d08de..0000000 --- a/lib/relaton_bib/bibliographic_size.rb +++ /dev/null @@ -1,103 +0,0 @@ -module RelatonBib - class BibliographicSize - extend Forwardable - - def_delegators :@size, :any? - - # @return [Array<RelatonBib::BibliographicSize::Value>] - attr_reader :size - - # - # Initialize a BibliographicSize object. - # - # @param [<Type>] size <description> - # - def initialize(size) - @size = size - end - - # - # Render BibliographicSize object to XML. - # - # @param [Nokogiri::XML::Builder] builder the XML builder - # - def to_xml(builder) - return if size.empty? - - builder.size do - size.each { |s| s.to_xml builder } - end - end - - # - # Render BibliographicSize object to AsciiBib. - # - # @param [String] prefix prefix for the size - # - # @return [String] AsciiBib string - # - def to_asciibib(prefix = "") - pref = prefix.empty? ? "size" : "#{prefix}.size" - size.map { |s| s.to_asciibib pref, size.size }.join - end - - # - # Render BibliographicSize object to hash. - # - # @return [<Type>] <description> - # - def to_hash - size.map &:to_hash - end - - class Value - # @return [String] - attr_reader :type, :value - - # - # Initialize a BibliographicSize::Value object. - # - # @param [String] type the type of the size - # @param [String] value size value - # - def initialize(type:, value:) - @type = type - @value = value - end - - # - # Render BibliographicSize::Value object to XML. - # - # @param [Nokogiri::XML::Builder] builder the XML builder - # - def to_xml(builder) - builder.value value, type: type - end - - # - # Render BibliographicSize::Value object to hash. - # - # @return [<Type>] <description> - # - def to_hash - { type: type, value: value } - end - - # - # Render BibliographicSize::Value object to AsciiBib. - # - # @param [String] prefix prefix for the size - # @param [Integer] size size of the array - # - # @return [String] AsciiBib string - # - def to_asciibib(prefix, size) - pref = prefix.empty? ? "" : "#{prefix}." - out = "" - out << "#{prefix}::\n" if size.size > 1 - out << "#{pref}type:: #{type}\n" - out << "#{pref}value:: #{value}\n" - end - end - end -end diff --git a/lib/relaton_bib/classification.rb b/lib/relaton_bib/classification.rb deleted file mode 100644 index 8d51e17..0000000 --- a/lib/relaton_bib/classification.rb +++ /dev/null @@ -1,40 +0,0 @@ -module RelatonBib - class Classification - # @return [String, nil] - attr_reader :type - - # @return [String] - attr_reader :value - - # @param type [String, nil] - # @param value [String] - def initialize(type: nil, value:) - @type = type - @value = value - end - - # @param builder [Nokogiri::XML::Builder] - def to_xml(builder) - xml = builder.classification value - xml[:type] = type if type - end - - # @return [Hash] - def to_hash - hash = { "value" => value } - hash["type"] = type if type - hash - end - - # @param prefix [String] - # @param count [Integer] number of classifications - # @return [String] - def to_asciibib(prefix = "", count = 1) - pref = prefix.empty? ? "classification" : prefix + ".classification" - out = count > 1 ? "#{pref}::\n" : "" - out += "#{pref}.type:: #{type}\n" if type - out += "#{pref}.value:: #{value}\n" - out - end - end -end diff --git a/lib/relaton_bib/config.rb b/lib/relaton_bib/config.rb deleted file mode 100644 index c74ceed..0000000 --- a/lib/relaton_bib/config.rb +++ /dev/null @@ -1,16 +0,0 @@ -module RelatonBib - module Config - def configure - yield configuration if block_given? - end - - def configuration - @configuration ||= self::Configuration.new - end - end - - class Configuration - end - - extend Config -end diff --git a/lib/relaton_bib/contribution_info.rb b/lib/relaton_bib/contribution_info.rb deleted file mode 100644 index f55825d..0000000 --- a/lib/relaton_bib/contribution_info.rb +++ /dev/null @@ -1,117 +0,0 @@ -# frozen_string_literal: true - -require "relaton_bib/person" - -# RelatonBib module -module RelatonBib - # Contributor's role. - class ContributorRole - include RelatonBib - - TYPES = %w[author performer publisher editor adapter translator - distributor realizer owner authorizer enabler subject].freeze - - # @return [Array<RelatonBib::FormattedString>] - attr_reader :description - - # @return [Strig] - attr_reader :type - - # @param type [String] allowed types "author", "editor", - # "cartographer", "publisher" - # @param description [Array<String>] - def initialize(**args) - if args[:type] && !TYPES.include?(args[:type]) - Util.warn %{Contributor's type `#{args[:type]}` is invalid.} - end - - @type = args[:type] - @description = args.fetch(:description, []).map do |d| - FormattedString.new content: d, format: nil - end - end - - # @param opts [Hash] - # @option opts [Nokogiri::XML::Builder] :builder XML builder - # @option opts [String] :lang language - def to_xml(**opts) # rubocop:disable Metrics/AbcSize - opts[:builder].role(type: type) do |builder| - desc = description.select { |d| d.language&.include? opts[:lang] } - desc = description unless desc.any? - desc.each do |d| - builder.description { |b| d.to_xml(b) } - end - end - end - - # @return [Hash, String] - def to_hash - hash = {} - hash["description"] = description.map(&:to_hash) if description&.any? - hash["type"] = type if type - hash - end - - # @param prefix [String] - # @param count [Integer] number of contributors - # 2return [String] - def to_asciibib(prefix = "", count = 1) - pref = prefix.empty? ? prefix : "#{prefix}." - out = count > 1 ? "#{prefix}.role::\n" : "" - description.each do |d| - out += d.to_asciibib "#{pref}role.description", description.size - end - out += "#{pref}role.type:: #{type}\n" if type - out - end - end - - # Contribution info. - class ContributionInfo - include RelatonBib - - # @return [Array<RelatonBib::ContributorRole>] - attr_reader :role - - # @return - # [RelatonBib::Person, RelatonBib::Organization] - attr_reader :entity - - # @param entity [RelatonBib::Person, RelatonBib::Organization] - # @param role [Array<Hash>] - # @option role [String] :type - # @option role [Array<String>] :description - def initialize(entity:, role: []) - if role.empty? - role << { type: entity.is_a?(Person) ? "author" : "publisher" } - end - @entity = entity - @role = role.map { |r| ContributorRole.new(**r) } - end - - # @param opts [Hash] - # @option opts [Nokogiri::XML::Builder] :builder XML builder - # @option opts [String, Symbol] :lang language - def to_xml(**opts) - entity.to_xml(**opts) - end - - # @return [Hash] - def to_hash - hash = entity.to_hash - hash["role"] = single_element_array(role) if role&.any? - hash - end - - # @param prefix [String] - # @param count [Integer] number of contributors - # @return [String] - def to_asciibib(prefix = "", count = 1) - pref = prefix.split(".").first - out = count > 1 ? "#{pref}::\n" : "" - out += entity.to_asciibib prefix - role.each { |r| out += r.to_asciibib pref, role.size } - out - end - end -end diff --git a/lib/relaton_bib/contributor.rb b/lib/relaton_bib/contributor.rb deleted file mode 100644 index 91bf3ac..0000000 --- a/lib/relaton_bib/contributor.rb +++ /dev/null @@ -1,277 +0,0 @@ -# frozen_string_literal: true - -require "uri" - -module RelatonBib - # Address class. - class Address - # @return [Array<String>] - attr_reader :street - - # @return [String, nil] - attr_reader :city, :state, :country, :postcode, :formatted_address - - # @param street [Array<String>] streets - # @param city [String, nil] city, should be present or formatted address provided - # @param state [String, nil] state - # @param country [String, nil] country, should be present or formatted address provided - # @param postcode [String, nil] postcode - # @param formatted_address [String, nil] formatted address, should be present or city and country provided - def initialize(**args) # rubocop:disable Metrics/CyclomaticComplexity - unless args[:formatted_address] || (args[:city] && args[:country]) - raise ArgumentError, "Either formatted address or city and country must be provided" - end - - @street = args[:street] || [] - @city = args[:city] - @state = args[:state] - @country = args[:country] - @postcode = args[:postcode] - @formatted_address = args[:formatted_address] unless args[:city] && args[:country] - end - - def ==(other) - street == other.street && city == other.city && state == other.state && - country == other.country && postcode == other.postcode && - formatted_address == other.formatted_address - end - - # @param doc [Nokogiri::XML::Document] - def to_xml(doc) # rubocop:disable Metrics/AbcSize, Metrics/MethodLength - doc.address do - if formatted_address - doc.formattedAddress formatted_address - else - street.each { |str| doc.street str } - doc.city city - doc.state state if state - doc.country country - doc.postcode postcode if postcode - end - end - end - - # @return [Hash] - def to_hash # rubocop:disable Metrics/AbcSize, Metrics/MethodLength - hash = { "address" => {} } - if formatted_address - hash["address"]["formatted_address"] = formatted_address - else - hash["address"]["street"] = street if street.any? - hash["address"]["city"] = city - hash["address"]["state"] = state if state - hash["address"]["country"] = country - hash["address"]["postcode"] = postcode if postcode - end - hash - end - - # @param prefix [String] - # @param count [Integer] number of addresses - # @return [String] - def to_asciibib(prefix = "", count = 1) # rubocop:disable Metrics/AbcSize, Metrics/MethodLength, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity - pref = prefix.empty? ? "address" : "#{prefix}.address" - if formatted_address - "#{pref}.formatted_address:: #{formatted_address}\n" - else - out = count > 1 ? "#{pref}::\n" : "" - street.each { |st| out += "#{pref}.street:: #{st}\n" } - out += "#{pref}.city:: #{city}\n" - out += "#{pref}.state:: #{state}\n" if state - out += "#{pref}.country:: #{country}\n" - out += "#{pref}.postcode:: #{postcode}\n" if postcode - out - end - end - end - - # Contact class. - class Contact - # @return [String] allowed "phone", "email" or "uri" - attr_reader :type - - # @return [String, nil] - attr_reader :subtype - - # @return [String] - attr_reader :value - - # @param type [String] allowed "phone", "email" or "uri" - # @param subtype [String, nil] i.e. "fax", "mobile", "landline" for "phone" - # or "work", "personal" for "uri" type - # @param value [String] - def initialize(type:, value:, subtype: nil) - @type = type - @subtype = subtype - @value = value - end - - def ==(other) - type == other.type && subtype == other.subtype && value == other.value - end - - # @param builder [Nokogiri::XML::Document] - def to_xml(builder) - node = builder.send type, value - node["type"] = subtype if subtype - end - - # @return [Hash] - def to_hash - hash = { type => value } - hash["type"] = subtype if subtype - hash - end - - # @param prefix [String] - # @param count [Integer] number of contacts - # @return [string] - def to_asciibib(prefix = "", count = 1) - pref = prefix.empty? ? prefix : "#{prefix}." - out = count > 1 ? "#{pref}contact::\n" : "" - out += "#{pref}contact.#{type}:: #{value}\n" - out += "#{pref}contact.type:: #{subtype}\n" if subtype - out - end - end - - # Affiliation. - class Affiliation - include RelatonBib - - # @return [RelatonBib::LocalizedString, nil] - attr_reader :name - - # @return [RelatonBib::Organization] - attr_reader :organization - - # @param organization [RelatonBib::Organization, nil] - # @param name [RelatonBib::LocalizedString, nil] - # @param description [Array<RelatonBib::FormattedString>] - def initialize(organization: nil, name: nil, description: []) - @name = name - @organization = organization - @description = description - end - - def ==(other) - name == other.name && organization == other.organization && description == other.description - end - - # @param opts [Hash] - # @option opts [Nokogiri::XML::Builder] :builder XML builder - # @option opts [String] :lang language - def to_xml(**opts) - return unless organization || name || description&.any? - - opts[:builder].affiliation do |builder| - name_xml builder - description_xml builder - organization&.to_xml(**opts) - end - end - - def name_xml(builder) - builder.name { name.to_xml builder } if name - end - - def description_xml(builder) - description.each { |d| builder.description { d.to_xml builder } } - end - - # - # Get description. - # - # @param [String, nil] lang language if nil return all description - # - # @return return [Array<RelatonBib::FormattedString>] description - # - def description(lang = nil) - return @description unless lang - - @description.select { |d| d.language&.include? lang } - end - - # - # Render affiliation as hash. - # - # @return [Hash] - # - def to_hash - hash = organization&.to_hash || {} - hash["name"] = name.to_hash if name - if description&.any? - hash["description"] = single_element_array(description) - end - hash - end - - # @param prefix [String] - # @param count [Integer] - # @return [String] - def to_asciibib(prefix = "", count = 1) # rubocop:disable Metrics/AbcSize - pref = prefix.empty? ? prefix : "#{prefix}." - out = count > 1 ? "#{pref}affiliation::\n" : "" - out += name.to_asciibib "#{pref}affiliation.name" if name - description.each do |d| - out += d.to_asciibib "#{pref}affiliation.description", description.size - end - out += organization.to_asciibib "#{pref}affiliation.*" if organization - out - end - end - - # Contributor. - class Contributor - include RelatonBib - - # @return [URI] - attr_reader :uri - - # @return [Array<RelatonBib::Address, RelatonBib::Contact>] - attr_reader :contact - - # @param url [String, nil] - # @param contact [Array<RelatonBib::Address, RelatonBib::Contact>] - def initialize(url: nil, contact: []) - @uri = URI url if url - @contact = contact - end - - def ==(other) - uri == other.uri && contact == other.contact - end - - # Returns url. - # @return [String] - def url - @uri.to_s - end - - # @params builder [Nokogiri::XML::Builder] - def to_xml(builder) - contact.each { |contact| contact.to_xml builder } - end - - # @return [Hash] - def to_hash - hash = {} - hash["url"] = uri.to_s if uri - hash["contact"] = single_element_array(contact) if contact&.any? - hash - end - - # @param prefix [String] - # @return [String] - def to_asciibib(prefix = "") # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity - pref = prefix.empty? ? prefix : "#{prefix}." - out = "" - out += "#{pref}url:: #{uri}\n" if uri - addr = contact.select { |c| c.is_a? RelatonBib::Address } - addr.each { |ct| out += ct.to_asciibib prefix, addr.size } - cont = contact.select { |c| c.is_a? RelatonBib::Contact } - cont.each { |ct| out += ct.to_asciibib prefix, cont.size } - out - end - end -end diff --git a/lib/relaton_bib/copyright_association.rb b/lib/relaton_bib/copyright_association.rb deleted file mode 100644 index 06ccbd1..0000000 --- a/lib/relaton_bib/copyright_association.rb +++ /dev/null @@ -1,79 +0,0 @@ -module RelatonBib - # Copyright association. - class CopyrightAssociation - include RelatonBib - - # @return [Date] - attr_reader :from - - # @return [Date, nil] - attr_reader :to - - # @return [String, nil] - attr_reader :scope - - # @return [Array<RelatonBib::ContributionInfo>] - attr_reader :owner - - # rubocop:disable Metrics/AbcSize - - # @param owner [Array<Hash, RelatonBib::ContributionInfo>] contributor - # @option owner [String] :name - # @option owner [String] :abbreviation - # @option owner [String] :url - # @param from [String] date - # @param to [String, nil] date - # @param scope [String, nil] - def initialize(owner:, from:, to: nil, scope: nil) - unless owner.any? - raise ArgumentError, "at least one owner should exist." - end - - @owner = owner.map do |o| - o.is_a?(Hash) ? ContributionInfo.new(entity: Organization.new(**o)) : o - end - - @from = Date.strptime(from.to_s, "%Y") if from.to_s.match?(/\d{4}/) - @to = Date.strptime(to.to_s, "%Y") unless to.to_s.empty? - @scope = scope - end - - # @param opts [Hash] - # @option opts [Nokogiri::XML::Builder] :builder XML builder - # @option opts [String, Symbol] :lang language - def to_xml(**opts) - opts[:builder].copyright do |builder| - builder.from from ? from.year : "unknown" - builder.to to.year if to - owner.each { |o| builder.owner { o.to_xml(**opts) } } - builder.scope scope if scope - end - end - # rubocop:enable Metrics/AbcSize - - # @return [Hash] - def to_hash # rubocop:disable Metrics/AbcSize - owners = single_element_array(owner.map { |o| o.to_hash["organization"] }) - hash = { - "owner" => owners, - "from" => from.year.to_s, - } - hash["to"] = to.year.to_s if to - hash["scope"] = scope if scope - hash - end - - # @param prefix [String] - # @param count [Iteger] number of copyright elements - # @return [String] - def to_asciibib(prefix = "", count = 1) # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity - pref = prefix.empty? ? "copyright" : "#{prefix}.copyright" - out = count > 1 ? "#{pref}::\n" : "" - owner.each { |ow| out += ow.to_asciibib "#{pref}.owner", owner.size } - out += "#{pref}.from:: #{from.year}\n" if from - out += "#{pref}.to:: #{to.year}\n" if to - out += "#{pref}.scope:: #{scope}\n" if scope - out - end - end -end diff --git a/lib/relaton_bib/document_identifier.rb b/lib/relaton_bib/document_identifier.rb deleted file mode 100644 index e8f67a4..0000000 --- a/lib/relaton_bib/document_identifier.rb +++ /dev/null @@ -1,118 +0,0 @@ -module RelatonBib - # Document identifier. - class DocumentIdentifier - # @return [String] - attr_reader :id - - # @return [String, nil] - attr_reader :type, :scope, :language, :script - - # @param type [Boolean, nil] - attr_reader :primary - - # @param id [String] - # @param type [String, nil] - # @param scope [String, nil] - # @param primary [Bolean, nil] - # @param language [String, nil] - def initialize(**args) - @id = args[:id] - @type = args[:type] - @scope = args[:scope] - @primary = args[:primary] - @language = args[:language] - @script = args[:script] - end - - # in docid manipulations, assume ISO as the default: id-part:year - def remove_part - case @type - when "Chinese Standard" then @id.sub!(/\.\d+/, "") - when "URN" then remove_urn_part - else @id.sub!(/-[^:]+/, "") - end - end - - def remove_date - case @type - when "Chinese Standard" then @id.sub!(/-[12]\d\d\d/, "") - when "URN" - @id.sub!(/^(urn:iec:std:[^:]+:[^:]+:)[^:]*/, '\1') - else @id.sub!(/:[12]\d\d\d/, "") - end - end - - def all_parts - if type == "URN" - @id.sub!(%r{^(urn:iec:std(?::[^:]*){4}).*}, '\1:ser') - else - @id += " (all parts)" - end - end - - # - # Add docidentifier xml element - # - # @param opts [Hash] - # @option opts [Nokogiri::XML::Builder] :builder XML builder - # @option opts [String] :lang language - def to_xml(**opts) # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity - lid = if type == "URN" && opts[:lang] - id.sub %r{(?<=:)(?:\w{2},)*?(#{opts[:lang]})(?:,\w{2})*}, '\1' - else id - end - element = opts[:builder].docidentifier { |b| b.parent.inner_html = lid } - element[:type] = type if type - element[:scope] = scope if scope - element[:primary] = primary if primary - element[:language] = language if language - element[:script] = script if script - end - - # @return [Hash] - def to_hash # rubocop:disable Metrics/AbcSize - hash = { "id" => id } - hash["type"] = type if type - hash["scope"] = scope if scope - hash["primary"] = primary if primary - hash["language"] = language if language - hash["script"] = script if script - hash - end - - # @param prefix [String] - # @param count [Integer] number of docids - # @return [String] - def to_asciibib(prefix = "", count = 1) # rubocop:disable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity, Metrics/AbcSize - pref = prefix.empty? ? prefix : "#{prefix}." - return "#{pref}docid:: #{id}\n" unless type || scope - - out = count > 1 ? "#{pref}docid::\n" : "" - out += "#{pref}docid.type:: #{type}\n" if type - out += "#{pref}docid.scope:: #{scope}\n" if scope - out += "#{pref}docid.primary:: #{primary}\n" if primary - out += "#{pref}docid.language:: #{language}\n" if language - out += "#{pref}docid.script:: #{script}\n" if script - out + "#{pref}docid.id:: #{id}\n" - end - - private - - def remove_urn_part # rubocop:disable Metrics/MethodLength - @id.sub!(%r{^ - (urn:iso:std:[^:]+ # ISO prefix and originator - (?::(?:data|guide|isp|iwa|pas|r|tr|ts|tta)) # type - ?:\d+) # docnumber - (?::-[^:]+)? # partnumber - (?::(draft|cancelled|stage-[^:]+))? # status - (?::ed-\d+)?(?::v[^:]+)? # edition and version - (?::\w{2}(?:,\w{2})*)? # langauge - }x, '\1') # remove partnumber, status, version, and language - @id.sub!(%r{^ - (urn:iec:std:[^:]+ # IEC prefix and originator - :\d+) # docnumber - (?:-[^:]+)? # partnumber - }x, '\1') # remove partnumber - end - end -end diff --git a/lib/relaton_bib/document_relation.rb b/lib/relaton_bib/document_relation.rb deleted file mode 100644 index b27c197..0000000 --- a/lib/relaton_bib/document_relation.rb +++ /dev/null @@ -1,95 +0,0 @@ -module RelatonBib - # Documett relation - class DocumentRelation - include RelatonBib - - TYPES = %w[ - includes includedIn hasPart partOf merges mergedInto splits splitInto - instanceOf hasInstance exemplarOf hasExemplar manifestationOf - hasManifestation reproductionOf hasReproduction reprintOf hasReprint - expressionOf hasExpression translatedFrom hasTranslation arrangementOf - hasArrangement abridgementOf hasAbridgement annotationOf hasAnnotation - draftOf hasDraft editionOf hasEdition updates updatedBy derivedFrom - derives describes describedBy catalogues cataloguedBy hasSuccessor - successorOf adaptedFrom hasAdaptation adoptedFrom adoptedAs reviewOf - hasReview commentaryOf hasCommentary related hasComplement complementOf - obsoletes obsoletedBy cites isCitedIn - ].freeze - - # @return [String] - attr_accessor :type - - # @return [RelatonBib::FormattedString, nil] - attr_reader :description - - # @return [String] - # attr_reader :identifier, :url - - # @return [RelatonBib::BibliographicItem] - attr_reader :bibitem - - # @return [Array<RelatonBib::Locality, RelatonBib::LocalityStack>] - attr_reader :locality - - # @return [Array<RelatonBib::SourceLocality, - # RelatonBib::SourceLocalityStack>] - attr_reader :source_locality - - # @param type [String] - # @param description [RelatonBib::FormattedString, nil] - # @param bibitem [RelatonBib::BibliographicItem, - # RelatonIso::IsoBibliographicItem] - # @param locality [Array<RelatonBib::Locality>] - # @param locality_stack [Array<RelatonBib::LocalityStack>] - # @param source_locality [Array<RelatonBib::SourceLocality, - # RelatonBib::SourceLocalityStack>] - def initialize(type:, bibitem:, **args) - type = "obsoletes" if type == "Now withdrawn" - unless self.class::TYPES.include? type - Util.warn "Invalid relation type: `#{type}`" - end - @type = type - @description = args[:description] - @locality = args[:locality] || args[:locality_stack] || [] - @source_locality = args[:source_locality] || args[:source_locality_stack] || [] - @bibitem = bibitem - end - - # @param builder [Nokogiri::XML::Builder] - def to_xml(builder, **opts) - opts.delete :bibdata - opts.delete :note - builder.relation(type: type) do - builder.description { description.to_xml builder } if description - bibitem.to_xml(**opts.merge(builder: builder, embedded: true)) - locality.each { |l| l.to_xml builder } - source_locality.each { |l| l.to_xml builder } - end - end - - # @return [Hash] - def to_hash # rubocop:disable Metrics/AbcSize - hash = { "type" => type, "bibitem" => bibitem.to_hash(embedded: true) } - hash["description"] = description.to_hash if description - locality.each_with_object(hash) do |l, obj| - k, v = l.to_hash.first - hash[k] ||= [] - hash[k] << v - end - if source_locality&.any? - hash["source_locality"] = single_element_array(source_locality) - end - hash - end - - # @param prefix [String] - # @return [String] - def to_asciibib(prefix = "") - pref = prefix.empty? ? prefix : prefix + "." - out = "#{prefix}.type:: #{type}\n" - out += description.to_asciibib "#{pref}desctiption" if description - out += bibitem.to_asciibib "#{pref}bibitem" if bibitem - out - end - end -end diff --git a/lib/relaton_bib/document_relation_collection.rb b/lib/relaton_bib/document_relation_collection.rb deleted file mode 100644 index aab6d07..0000000 --- a/lib/relaton_bib/document_relation_collection.rb +++ /dev/null @@ -1,57 +0,0 @@ -# frozen_string_literal: true - -module RelatonBib - # Document relation collection - class DocRelationCollection - extend Forwardable - - def_delegators :@array, :<<, :[], :first, :last, :empty?, :any?, :size, - :each, :detect, :map, :reduce, :length, :unshift, :max_by - - # @param relation [Array<RelatonBib::DocumentRelation, Hash>] - # @option relation [String] :type - # @option relation [String] :identifier - # @option relation [String, NIllClass] :url (nil) - # @option relation [Array<RelatonBib::Locality, RelatonBib::LocalityStack>] :locality - # @option relation [Array<RelatonBib::SourceLocality, RelatonBib::SourceLocalityStack>] :source_locality - # @option relation [RelatonBib::BibliographicItem, nil] :bibitem (nil) - def initialize(relation) - @array = relation.map { |r| r.is_a?(Hash) ? DocumentRelation.new(**r) : r } - end - - # - # Returns new DocumentRelationCollection with selected relations. - # - # @example Select relations with type "obsoletes" - # relations.select { |r| r.type == "obsoletes" } - # #=> <RelatonBib::DocRelationCollection:0x00007f9a0191d5f0 @array=[...]> - # - # @return [RelatonBib::DocRelationCollection] new DocumentRelationCollection - # with selected relations - # - def select(&block) - arr = @array.select(&block) - self.class.new arr - end - - # @todo We don't have replace type anymore. Suppose we should update this - # method or delete it. - # - # @return [RelatonBib::DocRelationCollection] - def replaces - DocRelationCollection.new(@array.select { |r| r.type == "replace" }) - end - - # @param prefix [String] - # @return [String] - def to_asciibib(prefix = "") - pref = prefix.empty? ? "relation" : "#{prefix}.relation" - out = "" - @array.each do |r| - out += size > 1 ? "#{pref}::\n" : "" - out += r.to_asciibib pref - end - out - end - end -end diff --git a/lib/relaton_bib/document_status.rb b/lib/relaton_bib/document_status.rb deleted file mode 100644 index c23e6b9..0000000 --- a/lib/relaton_bib/document_status.rb +++ /dev/null @@ -1,92 +0,0 @@ -# frozen_string_literal: true - -module RelatonBib - # Document status. - class DocumentStatus - # @return [RelatonBib::DocumentStatus::Stage] - attr_reader :stage - - # @return [RelatonBib::DocumentStatus::Stage, nil] - attr_reader :substage - - # @return [String, nil] - attr_reader :iteration - - # @param stage [String, Hash, RelatonBib::DocumentStatus::Stage] - # @param substage [String, Hash, nil, RelatonBib::DocumentStatus::Stage] - # @param iteration [String, nil] - def initialize(stage:, substage: nil, iteration: nil) - @stage = stage_new stage - @substage = stage_new substage - @iteration = iteration - end - - # @param [Nokogiri::XML::Builder] - def to_xml(builder) - builder.status do - # FormattedString.instance_method(:to_xml).bind(status).call builder - builder.stage { |b| stage.to_xml b } - builder.substage { |b| substage.to_xml b } if substage - builder.iteration iteration unless iteration.to_s.empty? - end - end - - # @return [Hash] - def to_hash - hash = { "stage" => stage.to_hash } - hash["substage"] = substage.to_hash if substage - hash["iteration"] = iteration if iteration - hash - end - - # @param prefix [String] - # @return [String] - def to_asciibib(prefix = "") - pref = prefix.empty? ? prefix : "#{prefix}." - out = "#{pref}docstatus.stage:: #{stage.value}\n" - out += "#{pref}docstatus.substage:: #{substage.value}\n" if substage - out += "#{pref}docstatus.iteration:: #{iteration}\n" if iteration - out - end - - private - - # @param stg [RelatonBib::DocumentStatus::Stage, Hash, String, nil] - # @return [RelatonBib::DocumentStatus::Stage] - def stage_new(stg) - case stg - when Stage then stg - when Hash then self.class::Stage.new(**stg) - when String then self.class::Stage.new(value: stg) - end - end - - class Stage - # @return [String] - attr_reader :value - - # @return [String, nil] - attr_reader :abbreviation - - # @param value [String] - # @param abbreviation [String, nil] - def initialize(value:, abbreviation: nil) - @value = value - @abbreviation = abbreviation - end - - # @param [Nokogiri::XML::Builder] - def to_xml(builder) - builder.parent[:abbreviation] = abbreviation if abbreviation - builder.text value - end - - # @return [Hash] - def to_hash - hash = { "value" => value } - hash["abbreviation"] = abbreviation if abbreviation - hash - end - end - end -end diff --git a/lib/relaton_bib/document_type.rb b/lib/relaton_bib/document_type.rb deleted file mode 100644 index cd26aa9..0000000 --- a/lib/relaton_bib/document_type.rb +++ /dev/null @@ -1,52 +0,0 @@ -module RelatonBib - class DocumentType - attr_reader :type, :abbreviation - - # - # Initialize a DocumentType. - # - # @param [String] type document type - # @param [String, nil] abbreviation type abbreviation - # - def initialize(type:, abbreviation: nil) - @type = type - @abbreviation = abbreviation - end - - # - # Build XML representation of the document type. - # - # @param [Nokogiri::XML::Builder] builder XML builder - # - def to_xml(builder) - xml = builder.doctype @type - xml[:abbreviation] = @abbreviation if @abbreviation - end - - # - # Hash representation of the document type. - # - # @return [Hash] - # - def to_hash - hash = { "type" => @type } - hash["abbreviation"] = @abbreviation if @abbreviation - hash - end - - # - # Asciibib representation of the document type. - # - # @param [String] prefix prefix - # - # @return [String] AsciiBib representation - # - def to_asciibib(prefix = "") - pref = prefix.empty? ? prefix : "#{prefix}." - pref += "doctype." - out = "#{pref}type:: #{@type}\n" - out += "#{pref}abbreviation:: #{@abbreviation}\n" if @abbreviation - out - end - end -end diff --git a/lib/relaton_bib/edition.rb b/lib/relaton_bib/edition.rb deleted file mode 100644 index 18c267f..0000000 --- a/lib/relaton_bib/edition.rb +++ /dev/null @@ -1,55 +0,0 @@ -module RelatonBib - class Edition - # @return [String] edition - attr_reader :content - - # @return [String, nil] number - attr_reader :number - - # - # Initialize edition. - # - # @param [String, Integer, Float] content edition - # @param [String, Integer, Float, nil] number number - # - def initialize(content:, number: nil) - @content = content.to_s - @number = number&.to_s - end - - # - # Render edition as XML. - # - # @param [Nokogiri::XML::Builder] builder XML builder - # - def to_xml(builder) - node = builder.edition(content) - node[:number] = number if number - end - - # - # Return edition as hash. - # - # @return [Hash] edition as hash. - # - def to_hash - hash = { "content" => content } - hash["number"] = number if number - hash - end - - # - # Render edition as AsciiBib. - # - # @param [String] prefix prefix - # - # @return [String] edition as AsciiBib. - # - def to_asciibib(prefix = "") - pref = prefix.empty? ? "edition" : "#{prefix}.edition" - out = "#{pref}.content:: #{content}\n" - out += "#{pref}.number:: #{number}\n" if number - out - end - end -end diff --git a/lib/relaton_bib/editorial_group.rb b/lib/relaton_bib/editorial_group.rb deleted file mode 100644 index 41908b7..0000000 --- a/lib/relaton_bib/editorial_group.rb +++ /dev/null @@ -1,41 +0,0 @@ -require "relaton_bib/technical_committee" - -module RelatonBib - class EditorialGroup - include RelatonBib - - # @return [Array<RelatonBib::TechnicalCommittee>] - attr_accessor :technical_committee - - # @param technical_committee [Array<RelatonBib::TechnicalCommittee>] - def initialize(technical_committee) - @technical_committee = technical_committee - end - - # @param builder [Nokogigi::XML::Builder] - def to_xml(builder) - builder.editorialgroup do |b| - technical_committee.each { |tc| tc.to_xml b } - end - end - - # @return [Hash] - def to_hash - single_element_array technical_committee - end - - # @param prefix [String] - # @return [String] - def to_asciibib(prefix = "") - pref = prefix.empty? ? "editorialgroup" : "#{prefix}.editorialgroup" - technical_committee.map do |tc| - tc.to_asciibib pref, technical_committee.size - end.join - end - - # @return [true] - def presence? - technical_committee.any? - end - end -end diff --git a/lib/relaton_bib/extent.rb b/lib/relaton_bib/extent.rb deleted file mode 100644 index 7061b8a..0000000 --- a/lib/relaton_bib/extent.rb +++ /dev/null @@ -1,39 +0,0 @@ -module RelatonBib - class Extent - attr_accessor :locality - - # - # @param [Array<RelatonBib::Locality, RelatonBib::LocalityStack>] locality - # - def initialize(locality) - @locality = locality - end - - def to_xml(builder) - builder.extent do |b| - locality.each { |l| l.to_xml(b) } - end - end - - def to_hash - hash = Hash.new { |h, k| h[k] = [] } - locality.each_with_object(hash) do |l, obj| - k, v = l.to_hash.first - obj[k] << v - end - end - - def to_asciibib(prefix = "", count = 1) - pref = prefix.empty? ? "extent" : "#{prefix}.extent" - out = count > 1 ? "#{pref}::\n" : "" - locality.each do |l| - out += l.to_asciibib(pref, locality.size) - end - out - end - - def to_bibtex(item) - locality.map { |l| l.to_bibtex(item) }.join - end - end -end diff --git a/lib/relaton_bib/forename.rb b/lib/relaton_bib/forename.rb deleted file mode 100644 index a09edcd..0000000 --- a/lib/relaton_bib/forename.rb +++ /dev/null @@ -1,65 +0,0 @@ -module RelatonBib - class Forename < LocalizedString - # @return [String, nil] - attr_accessor :initial - - # - # Initialize Forename instance - # - # @param [String] content content of forename, can be empty - # @param [Array<String>] language languages, `en`, `fr`, `de` etc. - # @param [Array<String>] script scripts `Latn`, `Cyrl` etc. - # @param [String, nil] initial initial of forename - # - def initialize(content: nil, language: [], script: [], initial: nil) - @initial = initial - super content, language, script - end - - def ==(other) - super && initial == other.initial - end - - def to_s - content.nil? ? initial : super - end - - # - # Render forename to XML - # - # @param [Nokogiri::XML::Builder] builder XML builder - # - def to_xml(builder) - node = builder.forename { super } - node[:initial] = initial if initial - end - - # - # Render forename to hash - # - # @return [Hash, String] forename hash or string representation - # - def to_hash - ls = super - hash = ls.is_a?(Hash) ? ls : { "content" => ls } - hash["initial"] = initial if initial - hash - end - - # - # Render forename to asciibib - # - # @param [String] pref prefix - # @param [Integer] count size of array - # - # @return [String] asciibib string - # - def to_asciibib(pref, count = 1) - prf = pref.empty? ? pref : "#{pref}." - prf += "forename" - out = super prf, count - out += "#{prf}.initial:: #{initial}\n" if initial - out - end - end -end diff --git a/lib/relaton_bib/formatted_ref.rb b/lib/relaton_bib/formatted_ref.rb deleted file mode 100644 index f89f7f1..0000000 --- a/lib/relaton_bib/formatted_ref.rb +++ /dev/null @@ -1,17 +0,0 @@ -require "relaton_bib/formatted_string" - -module RelatonBib - class FormattedRef < FormattedString - # @param [Nokogiri::XML::Builder] - def to_xml(builder) - builder.formattedref { super } - end - - # @param prefix [String] - # @return [String] - def to_asciibib(prefix = "") - pref = prefix.empty? ? "formattedref" : "#{prefix}.formattedref" - super pref - end - end -end diff --git a/lib/relaton_bib/formatted_string.rb b/lib/relaton_bib/formatted_string.rb deleted file mode 100644 index 7d78816..0000000 --- a/lib/relaton_bib/formatted_string.rb +++ /dev/null @@ -1,133 +0,0 @@ -# frozen_string_literal: true - -require "relaton_bib/localized_string" - -module RelatonBib - # Formatted string - class FormattedString < LocalizedString - FORMATS = %w[text/plain text/html application/docbook+xml - application/tei+xml text/x-asciidoc text/markdown - application/x-metanorma+xml].freeze - - # @return [String] - attr_reader :format - - # @param content [String, Array<RelatonBib::LocalizedString>] - # @param language [String, nil] language code Iso639 - # @param script [String, nil] script code Iso15924 - # @param format [String] the content type - def initialize(content: "", language: nil, script: nil, format: "text/plain") - # if format && !FORMATS.include?(format) - # raise ArgumentError, %{Format "#{format}" is invalid.} - # end - - @format = format - super(content, language, script) - end - - def ==(other) - super && format == other.format - end - - # @param builder [Nokogiri::XML::Builder] - def to_xml(builder) - builder.parent["format"] = format if format - super - end - - # - # Encode content. - # - # @param [String] cnt content - # - # @return [String] encoded content - # - def encode(cnt) # rubocop:disable Metrics/MethodLength - return escp(cnt) unless format == "text/html" - - parts = cnt.scan(%r{ - <(?<tago>\w+)(?<attrs>[^>]*)> | # tag open - </(?<tagc>\w+)> | # tag close - (?<cmt><!--.*?-->) | # comment - (?<cnt>.+?)(?=<|$) # content - }x) - scan_xml parts - end - - # - # Scan XML and escape HTML entities. - # - # @param [Array<Array<String,nil>>] parts XML parts - # - # @return [String] output string - # - def scan_xml(parts) # rubocop:disable Metrics/AbcSize,Metrics/CyclomaticComplexity,Metrics/PerceivedComplexity,Metrics/MethodLength - return "" unless parts.any? - - out = "" - while parts.any? && (parts.first[3] || parts.first[4]) - _, _, _, cmt, cnt = parts.shift - out += "#{cmt}#{escp(cnt)}" - end - unless out.empty? - out += scan_xml(parts) if parts.any? && parts.first[0] - return out - end - - tago, attrs, tagc, = parts.shift - out = if tago && attrs && attrs[-1] == "/" - "<#{tago}#{attrs}>" - elsif tago - inr = scan_xml parts - _, _, tagc, = parts.shift - if tago == tagc - "<#{tago}#{attrs}>#{inr}</#{tagc}>" - else - "#{escp("<#{tago}#{attrs}>")}#{inr}#{escp("</#{tagc}>")}" - end - end - out += scan_xml(parts) if parts.any? && (parts.first[0] || parts.first[3] || parts.first[4]) - out - end - - # @return [Hash] - def to_hash - hash = super - return hash unless format - - hash = { "content" => hash } unless hash.is_a? Hash - hash["format"] = format - hash - end - - # @param prefix [String] - # @param count [Integer] number of elements - # @return [String] - def to_asciibib(prefix = "", count = 1, has_attrs = false) - has_attrs ||= !(format.nil? || format.empty?) - pref = prefix.empty? ? prefix : "#{prefix}." - # out = count > 1 ? "#{prefix}::\n" : "" - out = super - out += "#{pref}format:: #{format}\n" if format - out - end - - # - # Remove HTML tags except <em>, <strong>, <stem>, <sup>, <sub>, <tt>, <br>, <p>. - # Replace <i> with <em>, <b> with <strong>. - # - # @param [String] str content - # - # @return [String] cleaned content - # - def cleanup(str) - return str unless format == "text/html" - - str.gsub(/(?<=<)\w+:(?=\w+>)/, "").gsub(/(?<=<\/)\w+:(?=\w+>)/, "") - .gsub(/<i>/, "<em>").gsub(/<\/i>/, "</em>") - .gsub(/<b>/, "<strong>").gsub(/<\/b>/, "</strong>") - .gsub(/<(?!\/?(em|strong|stem|sup|sub|tt|br\s?\/|p|ol|ul|li))[^\s!]\/?.*?>/i, "") - .gsub(/\s+([.,:;!?<])/, "\\1").strip.squeeze(" ") - end - end -end diff --git a/lib/relaton_bib/full_name.rb b/lib/relaton_bib/full_name.rb deleted file mode 100644 index 8063054..0000000 --- a/lib/relaton_bib/full_name.rb +++ /dev/null @@ -1,106 +0,0 @@ -module RelatonBib - # Person's full name - class FullName - include RelatonBib - - # @return [Array<RelatonBib::Forename>] - attr_accessor :forename - - # @return [Array<RelatonBib::LocalizedString>] - attr_accessor :initials, :addition, :prefix - - # @return [RelatonBib::LocalizedString, nil] - attr_accessor :surname, :abbreviation, :completename - - # - # Initialize FullName instance - # - # @param surname [RelatonBib::LocalizedString, nil] surname or completename should be present - # @param abbreviation [RelatonBib::LocalizedString, nil] abbreviation - # @param forename [Array<RelatonBib::Forename>] forename - # @param initials [RelatonBib::LocalizedString, String, nil] string of initials - # @param addition [Array<RelatonBib::LocalizedString>] array of additions - # @param prefix [Array<RelatonBib::LocalizedString>] array of prefixes - # @param completename [RelatonBib::LocalizedString, nil] completename or surname should be present - # - def initialize(**args) # rubocop:disable Metrics/AbcSize - unless args[:surname] || args[:completename] - raise ArgumentError, "Should be given :surname or :completename" - end - - @surname = args[:surname] - @abbreviation = args[:abbreviation] - @forename = args.fetch :forename, [] - @initials = args[:initials].is_a?(String) ? LocalizedString.new(args[:initials]) : args[:initials] - @addition = args.fetch :addition, [] - @prefix = args.fetch :prefix, [] - @completename = args[:completename] - end - - def ==(other) - surname == other.surname && abbreviation == other.abbreviation && completename == other.completename && - forename == other.forename && initials == other.initials && addition == other.addition && prefix == other.prefix - end - - # @param opts [Hash] - # @option opts [Nokogiri::XML::Builder] :builder XML builder - # @option opts [String] :lang language - def to_xml(**opts) # rubocop:disable Metrics/AbcSize, Metrics/MethodLength,Metrics/CyclomaticComplexity,Metrics/PerceivedComplexity - opts[:builder].name do |builder| - builder.abbreviation { abbreviation.to_xml builder } if abbreviation - if completename - builder.completename { completename.to_xml builder } - else - pref = prefix.select { |p| p.language&.include? opts[:lang] } - pref = prefix unless pref.any? - pref.each { |p| builder.prefix { p.to_xml builder } } - frnm = forename.select { |f| f.language&.include? opts[:lang] } - frnm = forename unless frnm.any? - frnm.each { |f| f.to_xml builder } - builder.send(:"formatted-initials") { initials.to_xml builder } if initials - builder.surname { surname.to_xml builder } - addn = addition.select { |a| a.language&.include? opts[:lang] } - addn = addition unless addn.any? - addn.each { |a| builder.addition { a.to_xml builder } } - end - end - end - - # @return [Hash] - def to_hash # rubocop:disable Metrics/AbcSize,Metrics/CyclomaticComplexity,Metrics/PerceivedComplexity,Metrics/MethodLength - hash = {} - hash["abbreviation"] = abbreviation.to_hash if abbreviation - if forename.any? || initials - hash["given"] = {} - hash["given"]["forename"] = single_element_array(forename) if forename&.any? - hash["given"]["formatted_initials"] = initials.to_hash if initials - end - hash["surname"] = surname.to_hash if surname - hash["addition"] = single_element_array(addition) if addition&.any? - hash["prefix"] = single_element_array(prefix) if prefix&.any? - hash["completename"] = completename.to_hash if completename - hash - end - - # @param pref [String] - # @return [String] - def to_asciibib(pref) # rubocop:disable Metrics/AbcSize,Metrics/CyclomaticComplexity,Metrics/MethodLength,Metrics/PerceivedComplexity - prf = pref.empty? ? pref : "#{pref}." - prf += "name" - out = "" - out += abbreviation.to_asciibib "#{prf}.abbreviation" if abbreviation - given = "#{pref}.given" - out += forename.map do |fn| - fn.to_asciibib given, forename.size - end.join - out += initials.to_asciibib "#{given}.formatted-initials" if initials - out += surname.to_asciibib "#{prf}.surname" if surname - addition.each do |ad| - out += ad.to_asciibib "#{prf}.addition", addition.size - end - prefix.each { |pr| out += pr.to_asciibib "#{prf}.prefix", prefix.size } - out += completename.to_asciibib "#{prf}.completename" if completename - out - end - end -end diff --git a/lib/relaton_bib/hash_converter.rb b/lib/relaton_bib/hash_converter.rb deleted file mode 100644 index 81ce265..0000000 --- a/lib/relaton_bib/hash_converter.rb +++ /dev/null @@ -1,568 +0,0 @@ -module RelatonBib - module HashConverter - extend self - # @param args [Hash] - # @return [Hash] - def hash_to_bib(args) # rubocop:disable Metrics/AbcSize,Metrics/MethodLength - return nil unless args.is_a?(Hash) - - ret = Marshal.load(Marshal.dump(symbolize(args))) # deep copy - title_hash_to_bib(ret) - link_hash_to_bib(ret) - language_hash_to_bib(ret) - script_hash_to_bib(ret) - dates_hash_to_bib(ret) - docid_hash_to_bib(ret) - version_hash_to_bib(ret) - biblionote_hash_to_bib(ret) - abstract_hash_to_bib(ret) - formattedref_hash_to_bib(ret) - docstatus_hash_to_bib(ret) - contributors_hash_to_bib(ret) - copyright_hash_to_bib(ret) - relations_hash_to_bib(ret) - series_hash_to_bib(ret) - medium_hash_to_bib(ret) - place_hash_to_bib(ret) - extent_hash_to_bib(ret) - size_hash_to_bib(ret) - accesslocation_hash_to_bib(ret) - classification_hash_to_bib(ret) - validity_hash_to_bib(ret) - keyword_hash_to_bib(ret) - # ret[:keyword] = RelatonBib.array(ret[:keyword]) - ret[:license] = RelatonBib.array(ret[:license]) - # editorialgroup_hash_to_bib ret - # ics_hash_to_bib ret - # structuredidentifier_hash_to_bib ret - # doctype_hash_to_bib ret - ext_has_to_bib ret - ret - end - - def ext_has_to_bib(ret) - doctype_hash_to_bib ret - ret[:subdoctype] = ret[:ext][:subdoctype] if ret.dig(:ext, :subdoctype) - editorialgroup_hash_to_bib ret - ics_hash_to_bib ret - structuredidentifier_hash_to_bib ret - end - - def keyword_hash_to_bib(ret) - ret[:keyword] = RelatonBib.array(ret[:keyword]).map do |keyword| - localizedstring keyword - end - end - - def extent_hash_to_bib(ret) - return unless ret[:extent] - - ret[:extent] = RelatonBib.array(ret[:extent]).map do |e| - RelatonBib::Extent.new locality(e) - end - end - - def locality(loc) - if loc[:locality_stack] - RelatonBib.array(loc[:locality_stack]).map do |l| - LocalityStack.new locality(l) - end - else - RelatonBib.array(loc[:locality]).map do |l| - Locality.new(l[:type], l[:reference_from], l[:reference_to]) - end - end - end - - def size_hash_to_bib(ret) - return unless ret[:size] - - ret[:size] = RelatonBib.array(ret[:size]) - size = ret[:size]&.map do |val| - BibliographicSize::Value.new(**val) - end - ret[:size] = BibliographicSize.new(size) - end - - def title_hash_to_bib(ret) - return unless ret[:title] - - ret[:title] = RelatonBib.array(ret[:title]) - .reduce(TypedTitleStringCollection.new) do |m, t| - if t.is_a?(Hash) then m << TypedTitleString.new(**t) - else - m + TypedTitleString.from_string(t) - end - end - end - - def language_hash_to_bib(ret) - return unless ret[:language] - - ret[:language] = RelatonBib.array(ret[:language]) - end - - def script_hash_to_bib(ret) - return unless ret[:script] - - ret[:script] = RelatonBib.array(ret[:script]) - end - - def abstract_hash_to_bib(ret) - return unless ret[:abstract] - - ret[:abstract] = RelatonBib.array(ret[:abstract]).map do |a| - a.is_a?(String) ? FormattedString.new(content: a) : a - end - end - - def link_hash_to_bib(ret) - return unless ret[:link] - - ret[:link] = RelatonBib.array(ret[:link]) - end - - def place_hash_to_bib(ret) - return unless ret[:place] - - ret[:place] = RelatonBib.array(ret[:place]).map do |pl| - pl.is_a?(String) ? Place.new(name: pl) : Place.new(**pl) - end - end - - def accesslocation_hash_to_bib(ret) - return unless ret[:accesslocation] - - ret[:accesslocation] = RelatonBib.array(ret[:accesslocation]) - end - - def dates_hash_to_bib(ret) # rubocop:disable Metrics/AbcSize - return unless ret[:date] - - ret[:date] = RelatonBib.array(ret[:date]) - ret[:date].each_with_index do |d, i| - # value is synonym of on: it is reserved word in YAML - if d[:value] - ret[:date][i][:on] ||= d[:value] - ret[:date][i].delete(:value) - end - end - end - - def docid_hash_to_bib(ret) # rubocop:disable Metrics/AbcSize - return unless ret[:docid] - - ret[:docid] = RelatonBib.array(ret[:docid]).map do |id| - id[:type] ||= id[:id].match(/^\w+(?=\s)/)&.to_s - create_docid(**id) - end - end - - def create_docid(**args) - DocumentIdentifier.new(**args) - end - - def version_hash_to_bib(ret) - return unless ret[:version] - - ret[:version] = RelatonBib.array(ret[:version]).map do |v| - BibliographicItem::Version.new(v[:revision_date], v[:draft]) - end - end - - def biblionote_hash_to_bib(ret) # rubocop:disable Metrics/MethodLength,Metrics/AbcSize - return unless ret[:biblionote] - - ret[:biblionote] = RelatonBib.array(ret[:biblionote]) - .reduce(BiblioNoteCollection.new([])) do |mem, n| - mem << if n.is_a?(String) then BiblioNote.new content: n - else BiblioNote.new(**n) - end - end - end - - def formattedref_hash_to_bib(ret) - ret[:formattedref] && - ret[:formattedref] = formattedref(ret[:formattedref]) - end - - def docstatus_hash_to_bib(ret) - ret[:docstatus] && ret[:docstatus] = DocumentStatus.new( - stage: stage(ret[:docstatus][:stage]), - substage: stage(ret[:docstatus][:substage]), - iteration: ret[:docstatus][:iteration], - ) - end - - # @param stg [Hash] - # @return [RelatonBib::DocumentStatus::Stage] - def stage(stg) - return unless stg - - args = stg.is_a?(String) ? { value: stg } : stg - DocumentStatus::Stage.new(**args) - end - - def contributors_hash_to_bib(ret) # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength,Metrics/PerceivedComplexity - return unless ret[:contributor] - - ret[:contributor] = RelatonBib.array(ret[:contributor]) - ret[:contributor]&.each_with_index do |c, i| - roles = RelatonBib.array(ret[:contributor][i][:role]).map do |r| - if r.is_a? Hash - desc = RelatonBib.array(r[:description]).map { |d| d.is_a?(String) ? d : d[:content] } - { type: r[:type], description: desc } - # elsif r.is_a? Array - # { type: r[0], description: r.fetch(1) } - else - { type: r } - end - end - ret[:contributor][i][:role] = roles - ret[:contributor][i][:entity] = if c[:person] - person_hash_to_bib(c[:person]) - else - org_hash_to_bib(c[:organization]) - end - ret[:contributor][i].delete(:person) - ret[:contributor][i].delete(:organization) - end - end - - def org_hash_to_bib(org) # rubocop:disable Metrics/AbcSize - return nil if org.nil? - - org[:identifier] = RelatonBib.array(org[:identifier])&.map do |a| - OrgIdentifier.new(a[:type], a[:id]) - end - org[:subdivision] = RelatonBib.array(org[:subdivision]).map do |sd| - LocalizedString.new sd.is_a?(Hash) ? sd[:content] : sd - end - org[:contact] = contacts_hash_to_bib(org) - org[:logo] = Image.new(**org[:logo][:image]) if org[:logo] - org - end - - def person_hash_to_bib(person) - Person.new( - name: fullname_hash_to_bib(person), - credential: RelatonBib.array(person[:credential]), - affiliation: affiliation_hash_to_bib(person), - contact: contacts_hash_to_bib(person), - identifier: person_identifiers_hash_to_bib(person), - ) - end - - def fullname_hash_to_bib(person) # rubocop:disable Metrics/AbcSize - n = person[:name] - fname, inits = given_hash_to_bib n[:given] || n # `n` is for backward compatibility - FullName.new( - abbreviation: localizedstring(n[:abbreviation]), - forename: fname, initials: inits, - addition: RelatonBib.array(n[:addition])&.map { |f| localizedstring(f) }, - prefix: RelatonBib.array(n[:prefix])&.map { |f| localizedstring(f) }, - surname: localizedstring(n[:surname]), - completename: localizedstring(n[:completename]) - ) - end - - def given_hash_to_bib(given) - return [[], nil] unless given - - fname = RelatonBib.array(given[:forename])&.map { |f| forename_hash_to_bib(f) } - inits = localizedstring(given[:formatted_initials]) - [fname, inits] - end - - def forename_hash_to_bib(fname) - case fname - when Hash then Forename.new(**fname) - when String then Forename.new(content: fname) - end - end - - def person_identifiers_hash_to_bib(person) - RelatonBib.array(person[:identifier])&.map do |a| - PersonIdentifier.new(a[:type], a[:id]) - end - end - - def affiliation_hash_to_bib(person) # rubocop:disable Metrics/AbcSize, Metrics/MethodLength - return [] unless person[:affiliation] - - RelatonBib.array(person[:affiliation]).map do |a| - a[:description] = RelatonBib.array(a[:description]).map do |d| - cnt = if d.is_a?(Hash) - { content: d[:content], language: d[:language], - script: d[:script], format: d[:format] } - else { content: d } - end - FormattedString.new(**cnt) - end - Affiliation.new( - organization: Organization.new(**org_hash_to_bib(a[:organization])), - description: a[:description], name: localizedstring(a[:name]) - ) - end - end - - def contacts_hash_to_bib(entity) # rubocop:disable Metrics/AbcSize,Metrics/MethodLength,Metrics/CyclomaticComplexity - return [] unless entity[:contact] - - RelatonBib.array(entity[:contact]).map do |a| - type, value = a.reject { |k, _| k == :type }.flatten - case type - when :street, :city, :state, :country, :postcode # it's for old version compatibility, should be removed in the future - a[:street] = RelatonBib.array(a[:street]) - Address.new(**a) - when :address then create_address(a[:address]) - when :phone, :email, :uri - Contact.new(type: type.to_s, value: value, subtype: a[:type]) - else # it's for old version compatibility, should be removed in the future - Contact.new(**a) - end - end - end - - def create_address(adr) - if adr.is_a?(Hash) - adr[:street] = RelatonBib.array(adr[:street]) - Address.new(**adr) - else - Address.new(formatted_address: adr) - end - end - - # @param ret [Hash] - def copyright_hash_to_bib(ret) - return unless ret[:copyright] - - ret[:copyright] = RelatonBib.array(ret[:copyright]).map do |c| - c[:owner] = RelatonBib.array(c[:owner]).map do |o| - org_hash_to_bib(o) - end - c - end - end - - # @param ret [Hash] - def relations_hash_to_bib(ret) # rubocop:disable Metrics/MethodLength,Metrics/AbcSize - return unless ret[:relation] - - ret[:relation] = RelatonBib.array(ret[:relation]) - ret[:relation]&.each do |rel| - rel[:description] = FormattedString.new(**rel[:description]) if rel[:description] - relation_bibitem_hash_to_bib(rel) - relation_locality_hash_to_bib(rel) - relation_locality_stack_hash_to_bib(rel) - relation_source_locality_hash_to_bib(rel) - relaton_source_locality_stack_hash_to_bib(rel) - end - end - - # @param rel [Hash] relation - def relation_bibitem_hash_to_bib(rel) - if rel[:bibitem] - rel[:bibitem] = bib_item hash_to_bib(rel[:bibitem]) - else - Util.warn "Bibitem missing: `#{rel}`" - rel[:bibitem] = nil - end - end - - # @param item_hash [Hash] - # @return [RelatonBib::BibliographicItem] - def bib_item(item_hash) - BibliographicItem.new(**item_hash) - end - - # @param rel [Hash] relation - # @return [RelatonBib::LocalityStack] - def relation_locality_hash_to_bib(rel) - return unless rel[:locality]&.any? - - rel[:locality] = RelatonBib.array(rel[:locality]).map do |bl| - Locality.new(bl[:type], bl[:reference_from], bl[:reference_to]) - end - end - - def relation_locality_stack_hash_to_bib(rel) - return unless rel[:locality_stack]&.any? - - rel[:locality_stack] = RelatonBib.array(rel[:locality_stack]).map do |ls| - LocalityStack.new relation_locality_hash_to_bib(ls) - end - end - - # def locality_locality_stack(lls) - # if lls[:locality_stack] - # RelatonBib.array(lls[:locality_stack]).map do |lc| - # l = lc[:locality] || lc - # Locality.new(l[:type], l[:reference_from], l[:reference_to]) - # end - # else - # [Locality.new(lls[:type], lls[:reference_from], lls[:reference_to])] - # end - # end - - # @param rel [Hash] relation - def relation_source_locality_hash_to_bib(rel) # rubocop:disable Metrics/AbcSize, Metrics/MethodLength - return unless rel[:source_locality]&.any? - - rel[:source_locality] = RelatonBib.array(rel[:source_locality])&.map do |loc| - # sls = if sl[:source_locality_stack] - # RelatonBib.array(sl[:source_locality_stack]).map do |l| - # SourceLocality.new(l[:type], l[:reference_from], l[:reference_to]) - # end - # else - # l = SourceLocality.new(sl[:type], sl[:reference_from], sl[:reference_to]) - # [l] - # end - SourceLocality.new loc[:type], loc[:reference_from], loc[:reference_to] - end - end - - def relaton_source_locality_stack_hash_to_bib(rel) - return unless rel[:source_locality_stack]&.any? - - rel[:source_locality_stack] = RelatonBib.array(rel[:source_locality_stack]).map do |loc| - SourceLocalityStack.new relation_source_locality_hash_to_bib(loc) - end - end - - # @param ret [Hash] - def series_hash_to_bib(ret) # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity - ret[:series] = RelatonBib.array(ret[:series])&.map do |s| - s[:formattedref] && s[:formattedref] = formattedref(s[:formattedref]) - if s[:title] - s[:title] = { content: s[:title] } unless s[:title].is_a?(Hash) - s[:title] = typed_title_strig(s[:title]) - end - s[:abbreviation] && - s[:abbreviation] = localizedstring(s[:abbreviation]) - Series.new(**s) - end - end - - # @param title [Hash] - # @return [RelatonBib::TypedTitleString] - def typed_title_strig(title) - TypedTitleString.new(**title) - end - - # @param ret [Hash] - def medium_hash_to_bib(ret) - ret[:medium] = Medium.new(**ret[:medium]) if ret[:medium] - end - - # @param ret [Hash] - def classification_hash_to_bib(ret) - if ret[:classification] - ret[:classification] = RelatonBib.array(ret[:classification]).map do |cls| - Classification.new(**cls) - end - end - end - - # @param ret [Hash] - def validity_hash_to_bib(ret) - return unless ret[:validity] - - b = parse_validity_time(ret[:validity], :begins) - e = parse_validity_time(ret[:validity], :ends) - r = parse_validity_time(ret[:validity], :revision) - ret[:validity] = Validity.new(begins: b, ends: e, revision: r) - end - - def parse_validity_time(val, period) - t = val[period]&.to_s - return unless t - - p = period == :ends ? -1 : 1 - case t - when /^\d{4}$/ - Date.new(t.to_i, p, p).to_time - when /^(?<year>\d{4})-(?<month>\d{1,2})$/ - Date.new($~[:year].to_i, $~[:month].to_i, p).to_time - else Time.parse t - end - end - - # @param ret [Hash] - def editorialgroup_hash_to_bib(ret) - eg = ret.dig(:ext, :editorialgroup) || ret[:editorialgroup] # @todo remove ret[:editorialgroup] in the future - return unless eg - - technical_committee = RelatonBib.array(eg).map do |wg| - TechnicalCommittee.new WorkGroup.new(**wg) - end - ret[:editorialgroup] = EditorialGroup.new technical_committee - end - - # @param ret [Hash] - def ics_hash_to_bib(ret) - ics = ret.dig(:ext, :ics) || ret[:ics] # @todo remove ret[:ics] in the future - return unless ics - - ret[:ics] = RelatonBib.array(ics).map { |item| ICS.new(**item) } - end - - # @param ret [Hash] - def structuredidentifier_hash_to_bib(ret) - struct_id = ret.dig(:ext, :structuredidentifier) || ret[:structuredidentifier] # @todo remove ret[:structuredidentifier] in the future - return unless struct_id - - sids = RelatonBib.array(struct_id).map do |si| - si[:agency] = RelatonBib.array si[:agency] - StructuredIdentifier.new(**si) - end - ret[:structuredidentifier] = StructuredIdentifierCollection.new sids - end - - # @param ogj [Hash, Array, String] - # @return [Hash, Array, String] - def symbolize(obj) - case obj - when Hash - obj.reduce({}) do |memo, (k, v)| - memo[k.to_sym] = symbolize(v) - memo - end - when Array then obj.reduce([]) { |memo, v| memo << symbolize(v) } - else obj - end - end - - # @param lst [Hash, Array<RelatonBib::LocalizedString>, String] - # @return [RelatonBib::LocalizedString] - def localizedstring(lst) - return unless lst - - if lst.is_a?(Hash) - LocalizedString.new(lst[:content], lst[:language], lst[:script]) - else LocalizedString.new(lst) - end - end - - # @param frf [Hash, String] - # @return [RelatonBib::FormattedRef] - def formattedref(frf) - if frf.is_a?(Hash) - RelatonBib::FormattedRef.new(**frf) - else - RelatonBib::FormattedRef.new(content: frf) - end - end - - def doctype_hash_to_bib(ret) - doctype = ret.dig(:ext, :doctype) || ret[:doctype] # @todo remove ret[:doctype] in the future - return unless doctype - - ret[:doctype] = doctype.is_a?(String) ? create_doctype(type: doctype) : create_doctype(**doctype) - end - - def create_doctype(**args) - DocumentType.new(**args) - end - end -end diff --git a/lib/relaton_bib/hit.rb b/lib/relaton_bib/hit.rb deleted file mode 100644 index b5b0b70..0000000 --- a/lib/relaton_bib/hit.rb +++ /dev/null @@ -1,52 +0,0 @@ -require "weakref" - -module RelatonBib - class Hit - # @return [RelatonBib::HitCollection] - attr_accessor :hit_collection - - # @return [Array<Hash>] - attr_reader :hit - - # @param hit [Hash] - # @param hit_collection [RelatonBib::HitCollection] - def initialize(hit, hit_collection = nil) - @hit = hit - @hit_collection = WeakRef.new hit_collection if hit_collection - end - - # @return [String] - def to_s - inspect - end - - # @return [String] - def inspect - "<#{self.class}:#{format('%<id>#.14x', id: object_id << 1)} " \ - "@text=\"#{@hit_collection&.text}\" " \ - "@fetched=\"#{!@fetch.nil?}\" " \ - "@fullIdentifier=\"#{@fetch&.shortref(nil)}\" " \ - "@title=\"#{@hit[:code]}\">" - end - - def fetch - raise "Not implemented" - end - - # @param opts [Hash] - # @option opts [Nokogiri::XML::Builder] :builder XML builder - # @option opts [Boolean] :bibdata - # @option opts [String, Symbol] :lang language - # @return [String] XML - def to_xml(**opts) - if opts[:builder] - fetch.to_xml(**opts) - else - builder = Nokogiri::XML::Builder.new(encoding: "UTF-8") do |xml| - fetch.to_xml(**opts.merge(builder: xml)) - end - builder.doc.root.to_xml - end - end - end -end diff --git a/lib/relaton_bib/hit_collection.rb b/lib/relaton_bib/hit_collection.rb deleted file mode 100644 index 0c1b546..0000000 --- a/lib/relaton_bib/hit_collection.rb +++ /dev/null @@ -1,105 +0,0 @@ -require "forwardable" - -module RelatonBib - class HitCollection - extend Forwardable - - def_delegators :@array, :<<, :[], :first, :empty?, :any?, :size, :each, - :each_slice, :reduce, :map - - # @return [TrueClass, FalseClass] - attr_reader :fetched - - # @return [String] - attr_reader :text - - # @return [String] - attr_reader :year - - # @param text [String] reference to search - def initialize(text, year = nil) - @array = [] - @text = text - @year = year - @fetched = false - end - - # - # Fetches hits from the data source - # - # @return [self] self object - # - def fetch - workers = WorkersPool.new 4 - workers.worker(&:fetch) - each do |hit| - workers << hit - end - workers.end - workers.result - @fetched = true - self - end - - # - # Renders the collection as XML - # - # @param opts [Hash] options - # @option opts [Nokogiri::XML::Builder] :builder XML builder - # @option opts [Boolean] :bibdata render bibdata if true - # @option opts [String, Symbol] :lang language - # - # @return [String] XML representation of the collection - # - def to_xml(**opts) - builder = Nokogiri::XML::Builder.new(encoding: "UTF-8") do |xml| - xml.documents do - @array.each do |hit| - hit.fetch - hit.to_xml(**opts.merge(builder: xml)) - end - end - end - builder.to_xml - end - - # - # Selects matching hits and returns a new collection - # - # @param [Proc] &block proc to select hits - # - # @return [RelatonBib::HitCollection] new hit collection - # - def select(&block) - me = deep_dup - array_dup = instance_variable_get(:@array).deep_dup - me.instance_variable_set(:@array, array_dup) - array_dup.select!(&block) - array_dup.each { |h| h.hit_collection = WeakRef.new me } - me - end - - def reduce!(sum, &block) - @array = @array.reduce sum, &block - self - end - - # - # Returns String representation of the collection - # - # @return [String] String representation of the collection - # - def to_s - inspect - end - - # - # Returns String representation of the collection - # - # @return [String] String representation of the collection - # - def inspect - "<#{self.class}:#{format('%#.14x', object_id << 1)} @ref=#{@text} @fetched=#{@fetched}>" - end - end -end diff --git a/lib/relaton_bib/ics.rb b/lib/relaton_bib/ics.rb deleted file mode 100644 index 55561b7..0000000 --- a/lib/relaton_bib/ics.rb +++ /dev/null @@ -1,42 +0,0 @@ -module RelatonBib - class ICS - # @return [String] - attr_reader :code - - # @return [String, nil] - attr_reader :text - - # @param code [String] - # @param text [String, nil] - def initialize(code:, text: nil) - @code = code - @text = text - end - - # @param builder [Nokogiri::XML::Builder] - def to_xml(builder) - builder.ics do |b| - b.code code - b.text_ text if text - end - end - - # @return [Hash] - def to_hash - hash = { "code" => code } - hash["text"] = text if text - hash - end - - # @param prefix [String] - # @param count [Integer] number of ics - # @return [String] - def to_asciibib(prefix = "", count = 1) - pref = prefix.empty? ? "ics" : "#{prefix}.ics" - out = count > 1 ? "#{pref}::\n" : "" - out += "#{pref}.code:: #{code}\n" - out += "#{pref}.text:: #{text}\n" if text - out - end - end -end diff --git a/lib/relaton_bib/image.rb b/lib/relaton_bib/image.rb deleted file mode 100644 index f0491a2..0000000 --- a/lib/relaton_bib/image.rb +++ /dev/null @@ -1,95 +0,0 @@ -module RelatonBib - class Image - # @return [String] - attr_accessor :src, :mimetype - - # @return [String, nil] - attr_accessor :id, :filename, :width, :height, :alt, :title, :longdesc - - # - # Initializes a new Image object. - # - # @param src [String] the source URL of the image - # @param mimetype [String] the MIME type of the image - # @param args [Hash] additional arguments - # @option id [String, nil] the ID of the image - # @option args [String, nil] :filename the filename of the image - # @option args [String, nil] :width the width of the image - # @option args [String, nil] :height the height of the image - # @option args [String, nil] :alt the alternative text for the image - # @option args [String, nil] :title the title of the image - # @option args [String, nil] :longdesc the long description of the image - # - def initialize(src:, mimetype:, **args) - @src = src - @mimetype = mimetype - args.each { |k, v| send "#{k}=", v } - end - - def ==(other) - other.is_a?(Image) && id == other.id && src == other.src && mimetype == other.mimetype && - filename == other.filename && width == other.width && height == other.height && - alt == other.alt && title == other.title && longdesc == other.longdesc - end - - # - # Converts the image object to XML format. - # - # @param [Nokogiri::XML::Builder] builder The XML builder object. - # - # @return [void] - # - def to_xml(builder) # rubocop:disable Metrics/AbcSize,Metrics/CyclomaticComplexity,Metrics/MethodLength - builder.image do - builder.parent[:id] = id if id - builder.parent[:src] = src - builder.parent[:mimetype] = mimetype - builder.parent[:filename] = filename if filename - builder.parent[:width] = width if width - builder.parent[:height] = height if height - builder.parent[:alt] = alt if alt - builder.parent[:title] = title if title - builder.parent[:longdesc] = longdesc if longdesc - end - end - - # - # Converts the Image object to a hash representation. - # - # @return [Hash] The hash representation of the Image object. - # - def to_hash # rubocop:disable Metrics/AbcSize,Metrics/CyclomaticComplexity - hash = { "image" => { "src" => src, "mimetype" => mimetype } } - hash["image"]["id"] = id if id - hash["image"]["filename"] = filename if filename - hash["image"]["width"] = width if width - hash["image"]["height"] = height if height - hash["image"]["alt"] = alt if alt - hash["image"]["title"] = title if title - hash["image"]["longdesc"] = longdesc if longdesc - hash - end - - # - # Converts the image object to AsciiBib format. - # - # @param prefix [String] The prefix to be added to the AsciiBib output. - # - # @return [String] The image object converted to AsciiBib format. - # - def to_asciibib(prefix = "") # rubocop:disable Metrics/AbcSize,Metrics/CyclomaticComplexity,Metrics/PerceivedComplexity,Metrics/MethodLength - pref = prefix.empty? ? "image." : "#{prefix}.image." - out = "" - out += "#{pref}id:: #{id}\n" if id - out += "#{pref}src:: #{src}\n" - out += "#{pref}mimetype:: #{mimetype}\n" - out += "#{pref}filename:: #{filename}\n" if filename - out += "#{pref}width:: #{width}\n" if width - out += "#{pref}height:: #{height}\n" if height - out += "#{pref}alt:: #{alt}\n" if alt - out += "#{pref}title:: #{title}\n" if title - out += "#{pref}longdesc:: #{longdesc}\n" if longdesc - out - end - end -end diff --git a/lib/relaton_bib/localized_string.rb b/lib/relaton_bib/localized_string.rb deleted file mode 100644 index 342ed37..0000000 --- a/lib/relaton_bib/localized_string.rb +++ /dev/null @@ -1,149 +0,0 @@ -# frozen_string_literal: true - -module RelatonBib - # Localized string. - class LocalizedString - include RelatonBib - - # @return [Array<String>] language Iso639 code - attr_reader :language - - # @return [Array<String>] script Iso15924 code - attr_reader :script - - # @return [String, Array<RelatonBib::LocalizedString>] - attr_accessor :content - - # @param content [String, Array<RelatonBib::LocalizedString>] - # @param language [String] language code Iso639 - # @param script [String] script code Iso15924 - def initialize(content, language = nil, script = nil) # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/PerceivedComplexity - if content.is_a?(Array) && content.none? - raise ArgumentError, "LocalizedString content is empty" - end - - @language = language.is_a?(String) ? [language] : language - @script = script.is_a?(String) ? [script] : script - @content = if content.is_a?(Array) - content.map do |c| - case c - when Hash - LocalizedString.new c[:content], c[:language], c[:script] - when String then LocalizedString.new c - else c - end - end - else cleanup content - end - end - - def ==(other) - return false unless other.is_a? LocalizedString - - content == other.content && language == other.language && script == other.script - end - - # - # String representation. - # - # @return [String] - # - def to_s - content.is_a?(Array) ? content.first.to_s : content.to_s - end - - # - # Returns true if content is empty. - # - # @return [Boolean] - # - def empty? - content.empty? - end - - # @param builder [Nokogiri::XML::Builder] - def to_xml(builder) # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity,Metrics/PerceivedComplexity - return unless content - - if content.is_a?(Array) - content.each { |c| builder.variant { c.to_xml builder } } - else - builder.parent["language"] = language.join(",") if language&.any? - builder.parent["script"] = script.join(",") if script&.any? - builder.parent.inner_html = encode content - end - end - - # - # Encode content. - # - # @param [String] cnt content - # - # @return [String] encoded content - # - def encode(cnt) - escp cnt - end - - # - # Escope HTML entities. - # - # @param [String] str input string - # - # @return [String] output string - # - def escp(str) - return unless str - - coder = HTMLEntities.new - coder.encode coder.decode(str.dup.force_encoding("UTF-8")) - end - - # @return [Hash, Array<Hash>] - def to_hash # rubocop:disable Metrics/AbcSize,Metrics/CyclomaticComplexity,Metrics/PerceivedComplexity - if content.nil? || content.is_a?(String) - # return content unless language || script - - hash = {} - hash["content"] = content # unless content.nil? || content.empty? - hash["language"] = single_element_array(language) if language&.any? - hash["script"] = single_element_array(script) if script&.any? - hash - else content&.map &:to_hash - end - end - - # @param prefix [String] - # @param count [Integer] number of elements - # @return [String] - def to_asciibib(prefix = "", count = 1, has_attrs = false) # rubocop:disable Metrics/AbcSize,Metrics/CyclomaticComplexity,Metrics/PerceivedComplexity,Metrics/MethodLength - pref = prefix.empty? ? prefix : "#{prefix}." - case content - when String - unless language&.any? || script&.any? || has_attrs - return "#{prefix}:: #{content}\n" - end - - out = count > 1 ? "#{prefix}::\n" : "" - out += "#{pref}content:: #{content}\n" - language&.each { |l| out += "#{pref}language:: #{l}\n" } - script&.each { |s| out += "#{pref}script:: #{s}\n" } - out - when Array - content.map { |c| c.to_asciibib "#{pref}variant", content.size }.join - else count > 1 ? "#{prefix}::\n" : "" - end - end - - # - # Should be implemented in subclass. - # - # @param [String] str content - # - # @return [String] cleaned content - # - def cleanup(str) - str - end - end -end diff --git a/lib/relaton_bib/medium.rb b/lib/relaton_bib/medium.rb deleted file mode 100644 index 845f570..0000000 --- a/lib/relaton_bib/medium.rb +++ /dev/null @@ -1,76 +0,0 @@ -module RelatonBib - class Medium - # @return [String, nil] - attr_reader :content, :genre, :form, :carrier, :size, :scale - - # - # Initialize a Medium object. - # - # @param content [String, nil] content of the medium - # @param genre [String, nil] genre of the medium - # @param form [String, nil] form of the medium - # @param carrier [String, nil] carrier of the medium - # @param size [String, nil] size of the medium - # @param scale [String, nil] - # - def initialize(**args) - @content = args[:content] - @genre = args[:genre] - @form = args[:form] - @carrier = args[:carrier] - @size = args[:size] - @scale = args[:scale] - end - - # - # Render Medium object to XML. - # - # @param builder [Nokogiri::XML::Builder] - # - def to_xml(builder) # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity - builder.medium do - builder.content content if content - builder.genre genre if genre - builder.form form if form - builder.carrier carrier if carrier - builder.size size if size - builder.scale scale if scale - end - end - - # - # Render Medium object to hash. - # - # @return [Hash] - # - def to_hash # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity - hash = {} - hash["content"] = content if content - hash["genre"] = genre if genre - hash["form"] = form if form - hash["carrier"] = carrier if carrier - hash["size"] = size if size - hash["scale"] = scale if scale - hash - end - - # - # Render Medium object to AsciiBib. - # - # @param prefix [String] - # - # @return [String] - # - def to_asciibib(prefix = "") # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity - pref = prefix.empty? ? "medium." : "#{prefix}.medium." - out = "" - out += "#{pref}content:: #{content}\n" if content - out += "#{pref}genre:: #{genre}\n" if genre - out += "#{pref}form:: #{form}\n" if form - out += "#{pref}carrier:: #{carrier}\n" if carrier - out += "#{pref}size:: #{size}\n" if size - out += "#{pref}scale:: #{scale}\n" if scale - out - end - end -end diff --git a/lib/relaton_bib/organization.rb b/lib/relaton_bib/organization.rb deleted file mode 100644 index 636793e..0000000 --- a/lib/relaton_bib/organization.rb +++ /dev/null @@ -1,165 +0,0 @@ -# frozen_string_literal: true - -require "relaton_bib/contributor" - -module RelatonBib - # Organization identifier. - class OrgIdentifier - # ORCID = "orcid" - # URI = "uri" - - # @return [String] - attr_reader :type - - # @return [String] - attr_reader :value - - # @param type [String] - # @param value [String] - def initialize(type, value) - # unless [ORCID, URI].include? type - # raise ArgumentError, 'Invalid type. It should be "orsid" or "uri".' - # end - - @type = type - @value = value - end - - def ==(other) - type == other.type && value == other.value - end - - # @param builder [Nokogiri::XML::Builder] - def to_xml(builder) - builder.identifier(value, type: type) - end - - # @return [Hash] - def to_hash - { "type" => type, "id" => value } - end - - # @param prefix [String] - # @param count [Integer] - # @return [String] - def to_asciibib(prefix = "", count = 1) - pref = prefix.empty? ? prefix : "#{prefix}." - out = count > 1 ? "#{pref}identifier::\n" : "" - out += "#{pref}identifier.type:: #{type}\n" - out += "#{pref}identifier.value:: #{value}\n" - out - end - end - - # Organization. - class Organization < Contributor - # @return [Array<RelatonBib::LocalizedString>] - attr_reader :name - - # @return [RelatonBib::LocalizedString, nil] - attr_reader :abbreviation - - # @return [Array<RelatonBib::LocalizedString>] - attr_reader :subdivision - - # @return [Array<RelatonBib::OrgIdentifier>] - attr_reader :identifier - - # @return [RelatonBib::Image, nil] - attr_reader :logo - - # @param name [String, Hash, Array<String, Hash>] - # @param abbreviation [RelatoBib::LocalizedString, String] - # @param subdivision [Array<RelatoBib::LocalizedString>] - # @param url [String] - # @param identifier [Array<RelatonBib::OrgIdentifier>] - # @param contact [Array<RelatonBib::Address, RelatonBib::Contact>] - # @param logo [RelatonBib::Image, nil] - def initialize(**args) # rubocop:disable Metrics/AbcSize,Metrics/MethodLength - raise ArgumentError, "missing keyword: name" unless args[:name] - - super(url: args[:url], contact: args.fetch(:contact, [])) - - @name = if args[:name].is_a?(Array) - args[:name].map { |n| localized_string(n) } - else - [localized_string(args[:name])] - end - - @abbreviation = localized_string args[:abbreviation] - @subdivision = (args[:subdivision] || []).map do |sd| - localized_string sd - end - @identifier = args.fetch(:identifier, []) - @logo = args[:logo] - end - - def ==(other) - name == other.name && abbreviation == other.abbreviation && - subdivision == other.subdivision && identifier == other.identifier && - logo == other.logo && super - end - - # @param opts [Hash] - # @option opts [Nokogiri::XML::Builder] :builder XML builder - # @option opts [String] :lang language - def to_xml(**opts) # rubocop:disable Metrics/AbcSize,Metrics/CyclomaticComplexity,Metrics/PerceivedComplexity,Metrics/MethodLength - opts[:builder].organization do |builder| - nm = name.select { |n| n.language&.include? opts[:lang] } - nm = name unless nm.any? - nm.each { |n| builder.name { |b| n.to_xml b } } - sbdv = subdivision.select { |sd| sd.language&.include? opts[:lang] } - sbdv = subdivision unless sbdv.any? - sbdv.each { |sd| builder.subdivision { sd.to_xml builder } } - builder.abbreviation { |a| abbreviation.to_xml a } if abbreviation - builder.uri url if uri - identifier.each { |identifier| identifier.to_xml builder } - super builder - builder.logo { |b| logo.to_xml b } if logo - end - end - - # @return [Hash] - def to_hash # rubocop:disable Metrics/AbcSize,Metrics/CyclomaticComplexity - hash = { "name" => single_element_array(name) } - hash["abbreviation"] = abbreviation.to_hash if abbreviation - hash["identifier"] = single_element_array(identifier) if identifier&.any? - if subdivision&.any? - hash["subdivision"] = single_element_array(subdivision) - end - hash["logo"] = logo.to_hash if logo - { "organization" => hash.merge(super) } - end - - # @param prefix [String] - # @param count [Integer] - # @return [String] - def to_asciibib(prefix = "", count = 1) # rubocop:disable Metrics/AbcSize,Metrics/CyclomaticComplexity,Metrics/MethodLength,Metrics/PerceivedComplexity - pref = prefix.sub(/\*$/, "organization") - out = count > 1 ? "#{pref}::\n" : "" - name.each { |n| out += n.to_asciibib "#{pref}.name", name.size } - out += abbreviation.to_asciibib "#{pref}.abbreviation" if abbreviation - subdivision.each do |sd| - out += "#{pref}.subdivision::" if subdivision.size > 1 - out += sd.to_asciibib "#{pref}.subdivision" - end - identifier.each { |n| out += n.to_asciibib pref, identifier.size } - out += super pref - out += logo.to_asciibib "#{pref}.logo" if logo - out - end - - private - - # @param arg [String, Hash, RelatoBib::LocalizedString] - # @return [RelatoBib::LocalizedString] - def localized_string(arg) - case arg - when String then LocalizedString.new(arg) - when Hash - LocalizedString.new(arg[:content], arg[:language], arg[:script]) - when LocalizedString then arg - end - end - end -end diff --git a/lib/relaton_bib/person.rb b/lib/relaton_bib/person.rb deleted file mode 100644 index c0ad785..0000000 --- a/lib/relaton_bib/person.rb +++ /dev/null @@ -1,129 +0,0 @@ -# frozen_string_literal: true - -module RelatonBib - # Person identifier type. - module PersonIdentifierType - ISNI = "isni" - ORCID = "orcid" - URI = "uri" - - # Checks type. - # @param type [String] - # @raise [ArgumentError] if type isn't "isni" or "uri" - def self.check(type) - unless [ISNI, ORCID, URI].include? type - raise ArgumentError, 'Invalid type. It should be "isni", "orcid", "\ - "or "uri".' - end - end - end - - # Person identifier. - class PersonIdentifier - # @return [RelatonBib::PersonIdentifierType::ISNI, - # RelatonBib::PersonIdentifierType::ORCID, - # RelatonBib::PersonIdentifierType::URI] - attr_accessor :type - - # @return [String] - attr_accessor :value - - # @param type [RelatonBib::PersonIdentifierType::ISNI, - # RelatonBib::PersonIdentifierType::ORCID, - # RelatonBib::PersonIdentifierType::URI] - # @param value [String] - def initialize(type, value) - PersonIdentifierType.check type - - @type = type - @value = value - end - - # @param builser [Nokogiri::XML::Builder] - def to_xml(builder) - builder.identifier value, type: type - end - - # @return [Hash] - def to_hash - { "type" => type, "id" => value } - end - - # @param prefix [String] - # @param count [Integer] number of ids - # @return [String] - def to_asciibib(prefix = "", count = 1) - pref = prefix.empty? ? prefix : "#{prefix}." - out = count > 1 ? "#{prefix}::\n" : "" - out += "#{pref}type:: #{type}\n" - out += "#{pref}value:: #{value}\n" - out - end - end - - # Person class. - class Person < Contributor - # @return [RelatonBib::FullName] - attr_accessor :name - - # @return [Array<String>] - attr_reader :credential - - # @return [Array<RelatonBib::Affiliation>] - attr_accessor :affiliation - - # @return [Array<RelatonBib::PersonIdentifier>] - attr_accessor :identifier - - # @param name [RelatonBib::FullName] - # @param credential [Array<String>] - # @param affiliation [Array<RelatonBib::Affiliation>] - # @param contact [Array<RelatonBib::Address, RelatonBib::Contact>] - # @param identifier [Array<RelatonBib::PersonIdentifier>] - # @param url [String, nil] - def initialize(name:, **args) - contact = args[:contact] || [] - super(contact: contact, url: args[:url]) - @name = name - @credential = args[:credential] || [] - @affiliation = args[:affiliation] || [] - @identifier = args[:identifier] || [] - end - - # @param opts [Hash] - # @option opts [Nokogiri::XML::Builder] :builder XML builder - # @option opts [String, Symbol] :lang language - def to_xml(**opts) # rubocop:disable Metrics/AbcSize - opts[:builder].person do |builder| - name.to_xml(**opts) - credential.each { |c| builder.credential c } - affiliation.each { |a| a.to_xml(**opts) } - identifier.each { |id| id.to_xml builder } - contact.each { |contact| contact.to_xml builder } - end - end - - # @return [Hash] - def to_hash # rubocop:disable Metrics/AbcSize - hash = { "name" => name.to_hash } - hash["credential"] = credential if credential.any? - hash["affiliation"] = affiliation.map &:to_hash if affiliation.any? - hash["identifier"] = identifier.map &:to_hash if identifier.any? - { "person" => hash.merge(super) } - end - - # @param prefix [String] - # @count [Integer] number of persons - # @return [String] - def to_asciibib(prefix = "", count = 1) # rubocop:disable Metrics/AbcSize - pref = prefix.sub(/\*$/, "person") - out = count > 1 ? "#{pref}::\n" : "" - out += name.to_asciibib pref - credential.each { |c| out += "#{pref}.credential:: #{c}\n" } - affiliation.each { |af| out += af.to_asciibib pref, affiliation.size } - identifier.each { |id| out += id.to_asciibib pref, identifier.size } - out += super pref - out - end - end -end diff --git a/lib/relaton_bib/place.rb b/lib/relaton_bib/place.rb deleted file mode 100644 index b92d71b..0000000 --- a/lib/relaton_bib/place.rb +++ /dev/null @@ -1,203 +0,0 @@ -module RelatonBib - class Place - - # @return [String, nil] - attr_reader :name, :city - - # @return [Array<RelatonBib::Place::RegionType>] - attr_reader :region, :country - - # - # Initialize place. - # - # @param name [String, nil] name of place, name or city should be provided - # @param city [String, nil] name of city, city or name should be provided - # @param region [Array<RelatonBib::Place::RegionType>] region of place - # @param country [Array<RelatonBib::Place::RegionType>] country of place - # - def initialize(name: nil, city: nil, region: [], country: []) # rubocop:disable Metrics/CyclomaticComplexity - if name.nil? && city.nil? - raise ArgumentError, "`name` or `city` should be provided" - end - - @name = name - @city = city - @region = region.map { |r| r.is_a?(Hash) ? RegionType.new(**r) : r } - @country = country.map { |c| c.is_a?(Hash) ? RegionType.new(**c) : c } - end - - # - # Render place as XML. - # - # @param builder [Nologiri::XML::Builder] - # - def to_xml(builder) - if name - builder.place name - else - builder.place do |b| - b.city city - region.each { |r| b.region { r.to_xml b } } - country.each { |c| b.country { c.to_xml b } } - end - end - end - - # - # Render place as Hash. - # - # @return [Hash] - # - def to_hash - if name then name - else - hash = { "city" => city } - hash["region"] = region.map(&:to_hash) if region.any? - hash["country"] = country.map(&:to_hash) if country.any? - hash - end - end - - # - # Render place as AsciiBib. - # - # @param prefix [String] - # @param count [Integer] number of places - # - # @return [Stirng] - # - def to_asciibib(prefix = "", count = 1) # rubocop:disable Metrics/AbcSize - pref = prefix.empty? ? "place" : "#{prefix}.place" - out = count > 1 ? "#{pref}::\n" : "" - return "#{out}#{pref}.name:: #{name}\n" if name - - out += "#{pref}.city:: #{city}\n" - out += region.map { |r| r.to_asciibib("#{pref}.region", region.size) }.join - out + country.map { |c| c.to_asciibib("#{pref}.country", country.size) }.join - end - - class RegionType - STATES = { - "AK" => "Alaska", - "AL" => "Alabama", - "AR" => "Arkansas", - "AZ" => "Arizona", - "CA" => "California", - "CO" => "Colorado", - "CT" => "Connecticut", - "DC" => "District Of Columbia", - "DE" => "Delaware", - "FL" => "Florida", - "GA" => "Georgia", - "GU" => "Guam", - "HI" => "Hawaii", - "IA" => "Iowa", - "ID" => "Idaho", - "IL" => "Illinois", - "IN" => "Indiana", - "KS" => "Kansas", - "KY" => "Kentucky", - "LA" => "Louisiana", - "MA" => "Massachusetts", - "MD" => "Maryland", - "ME" => "Maine", - "MI" => "Michigan", - "MN" => "Minnesota", - "MO" => "Missouri", - "MS" => "Mississippi", - "MT" => "Montana", - "NC" => "North Carolina", - "ND" => "North Dakota", - "NE" => "Nebraska", - "NH" => "New Hampshire", - "NJ" => "New Jersey", - "NM" => "New Mexico", - "NV" => "Nevada", - "NY" => "New York", - "OH" => "Ohio", - "OK" => "Oklahoma", - "OR" => "Oregon", - "PA" => "Pennsylvania", - "PR" => "Puerto Rico", - "RI" => "Rhode Island", - "SC" => "South Carolina", - "SD" => "South Dakota", - "TN" => "Tennessee", - "TX" => "Texas", - "UT" => "Utah", - "VA" => "Virginia", - "VI" => "Virgin Islands", - "VT" => "Vermont", - "WA" => "Washington", - "WI" => "Wisconsin", - "WV" => "West Virginia", - "WY" => "Wyoming", - }.freeze - - # @return [Strign] name of region - attr_reader :name - - # @return [Strign, nil] ISO code of region - attr_reader :iso - - # @return [Boolean, nil] - attr_reader :recommended - - # - # Initialize region type. Name or valid US state ISO code should be provided. - # - # @param [String, nil] name name of region - # @param [String, nil] iso ISO code of region - # @param [Boolean, nil] recommended recommended region - # - def initialize(name: nil, iso: nil, recommended: nil) - unless name || STATES.key?(iso&.upcase) - raise ArgumentError, "`name` or valid US state ISO code should be provided" - end - - @name = name || STATES[iso&.upcase] - @iso = iso - @recommended = recommended - end - - # - # Render region type as XML. - # - # @param [Nokogiri::XML::Builder] builder XML builder - # - def to_xml(builder) - builder.parent["iso"] = iso if iso - builder.parent["recommended"] = recommended.to_s unless recommended.nil? - builder.text name - end - - # - # Render region type as Hash. - # - # @return [Hash] region type as Hash - # - def to_hash - hash = { "name" => name } - hash["iso"] = iso if iso - hash["recommended"] = recommended unless recommended.nil? - hash - end - - # - # Render region type as AsciiBib. - # - # @param [String] pref prefix - # @param [Integer] count number of region types - # - # @return [String] region type as AsciiBib - # - def to_asciibib(pref, count = 1) # rubocop:disable Metrics/AbcSize - out = count > 1 ? "#{pref}::\n" : "" - out += "#{pref}.name:: #{name}\n" - out += "#{pref}.iso:: #{iso}\n" if iso - out += "#{pref}.recommended:: #{recommended}\n" if recommended - out - end - end - end -end diff --git a/lib/relaton_bib/series.rb b/lib/relaton_bib/series.rb deleted file mode 100644 index a9babc4..0000000 --- a/lib/relaton_bib/series.rb +++ /dev/null @@ -1,119 +0,0 @@ -# frozen_string_literal: true - -module RelatonBib - # - # Series class. - # - class Series - # TYPES = %w[main alt].freeze - - # @return [String, nil] allowed values: "main" or "alt" - attr_reader :type - - # @return [RelatonBib::FormattedRef, nil] - attr_reader :formattedref - - # @return [RelatonBib::TypedTitleString] title - attr_reader :title - - # @return [String, nil] - attr_reader :place, :organization, :from, :to, :number, :partnumber, :run - - # @return [RelatonBib::LocalizedString, nil] - attr_reader :abbreviation - - # rubocop:disable Metrics/AbcSize, Metrics/MethodLength - - # @param type [String, nil] - # @param formattedref [RelatonBib::FormattedRef, nil] - # @param title [RelatonBib::TypedTitleString] title - # @param place [String, nil] - # @param orgaization [String, nil] - # @param abbreviation [RelatonBib::LocalizedString, nil] - # @param from [String, nil] - # @param to [String, nil] - # @param number [String, nil] - # @param partnumber [String, nil] - # @param run [String, nil] - def initialize(**args) - unless args[:title].is_a?(RelatonBib::TypedTitleString) - raise ArgumentError, "argument `title` should present in series" - end - - # if args[:type] && !TYPES.include?(args[:type]) - # warn "[relaton-bib] Series type is invalid: #{args[:type]}" - # end - - @type = args[:type] # if %w[main alt].include? args[:type] - @title = args[:title] - @formattedref = args[:formattedref] - @place = args[:place] - @organization = args[:organization] - @abbreviation = args[:abbreviation] - @from = args[:from] - @to = args[:to] - @number = args[:number] - @partnumber = args[:partnumber] - @run = args[:run] - end - # rubocop:enable Metrics/MethodLength - - # rubocop:disable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity - - # @param builder [Nokogiri::XML::Builder] - def to_xml(builder) # rubocop:disable Metrics/MethodLength - xml = builder.series do - formattedref&.to_xml builder - builder.title { title.to_xml builder } - builder.place place if place - builder.organization organization if organization - builder.abbreviation { abbreviation.to_xml builder } if abbreviation - builder.from from if from - builder.to to if to - builder.number number if number - builder.partnumber partnumber if partnumber - builder.run run if run - end - xml[:type] = type if type - end - # rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity - # rubocop:enable Metrics/PerceivedComplexity - - # @return [Hash] - def to_hash # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/PerceivedComplexity - hash = {} - hash["type"] = type if type - hash["formattedref"] = formattedref.to_hash if formattedref - hash["title"] = title.to_hash - hash["place"] = place if place - hash["organization"] = organization if organization - hash["abbreviation"] = abbreviation.to_hash if abbreviation - hash["from"] = from if from - hash["to"] = to if to - hash["number"] = number if number - hash["partnumber"] = partnumber if partnumber - hash["run"] = run if run - hash - end - - # @param prefix [String] - # @param count [Integer] - # @return [String] - def to_asciibib(prefix = "", count = 1) # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength,Metrics/PerceivedComplexity - pref = prefix.empty? ? "series" : prefix + ".series" - out = count > 1 ? "#{pref}::\n" : "" - out += "#{pref}.type:: #{type}\n" if type - out += formattedref.to_asciibib pref if formattedref - out += title.to_asciibib pref - out += "#{pref}.place:: #{place}\n" if place - out += "#{pref}.organization:: #{organization}\n" if organization - out += abbreviation.to_asciibib "#{pref}.abbreviation" if abbreviation - out += "#{pref}.from:: #{from}\n" if from - out += "#{pref}.to:: #{to}\n" if to - out += "#{pref}.number:: #{number}\n" if number - out += "#{pref}.partnumber:: #{partnumber}\n" if partnumber - out += "#{pref}.run:: #{run}\n" if run - out - end - end -end diff --git a/lib/relaton_bib/structured_identifier.rb b/lib/relaton_bib/structured_identifier.rb deleted file mode 100644 index 85c972d..0000000 --- a/lib/relaton_bib/structured_identifier.rb +++ /dev/null @@ -1,173 +0,0 @@ -module RelatonBib - class StructuredIdentifierCollection - include RelatonBib - extend Forwardable - - def_delegators :@collection, :any?, :size, :[], :detect, :map, :each, - :reduce - - # @param collection [Array<RelatonBib::StructuredIdentifier>] - def initialize(collection) - @collection = collection - end - - # @param builder [Nokogiri::XML::Builder] - def to_xml(builder) - @collection.each { |si| si.to_xml builder } - end - - # @return [Array<Hash>] - def to_hash - single_element_array @collection - end - - # @param prefix [String] - # @return [String] - def to_asciibib(prefix = "") - pref = prefix.empty? ? prefix : prefix + "." - pref += "structured_identifier" - @collection.reduce("") do |out, si| - out += "#{pref}::\n" if @collection.size > 1 - out + si.to_asciibib(pref) - end - end - - # remoe year from docnumber - def remove_date - @collection.each &:remove_date - end - - def remove_part - @collection.each &:remove_part - end - - def all_parts - @collection.each &:all_parts - end - - def presence? - any? - end - - # @return [RelatonBib::StructuredIdentifierCollection] - # def map(&block) - # StructuredIdentifierCollection.new @collection.map &block - # end - end - - class StructuredIdentifier - include RelatonBib - - # @return [String] - attr_reader :docnumber - - # @return [Array<String>] - attr_reader :agency - - # @return [String, nil] - attr_reader :type, :klass, :partnumber, :edition, :version, :supplementtype, - :supplementnumber, :language, :year - - # rubocop:disable Metrics/MethodLength - - # @param docnumber [String] - # @param args [Hash] - # @option args [String, nil] :type - # @option args [Array<String>] :agency - # @option args [Stirng, nil] :class - # @option args [String, nil] :partnumber - # @option args [String, nil] :edition - # @option args [String, nil] :version - # @option args [String, nil] :supplementtype - # @option args [String, nil] :supplementnumber - # @option args [String, nil] :language - # @option args [String, nil] :year - def initialize(docnumber:, **args) - @type = args[:type] - @agency = args[:agency] - @klass = args[:class] - @docnumber = docnumber - @partnumber = args[:partnumber] - @edition = args[:edition] - @version = args[:version] - @supplementtype = args[:supplementtype] - @supplementnumber = args[:supplementnumber] - @language = args[:language] - @year = args[:year] - end - - # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity - - # @param builder [Nokogiri::XML::Builder] - def to_xml(builder) - xml = builder.structuredidentifier do |b| - agency&.each { |a| b.agency a } - b.class_ klass if klass - b.docnumber docnumber - b.partnumber partnumber if partnumber - b.edition edition if edition - b.version version if version - b.supplementtype supplementtype if supplementtype - b.supplementnumber supplementnumber if supplementnumber - b.language language if language - b.year year if year - end - xml[:type] = type if type - end - - # @return [Hash] - def to_hash - hash = { "docnumber" => docnumber } - hash["type"] = type if type - hash["agency"] = single_element_array agency if agency&.any? - hash["class"] = klass if klass - hash["partnumber"] = partnumber if partnumber - hash["edition"] = edition if edition - hash["version"] = version if version - hash["supplementtype"] = supplementtype if supplementtype - hash["supplementnumber"] = supplementnumber if supplementnumber - hash["language"] = language if language - hash["year"] = year if year - hash - end - # rubocop:enable Metrics/MethodLength, Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity - - # @param prefix [String] - # @return [String] - def to_asciibib(prefix) # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength,Metrics/PerceivedComplexity - out = "#{prefix}.docnumber:: #{docnumber}\n" - agency.each { |a| out += "#{prefix}.agency:: #{a}\n" } - out += "#{prefix}.type:: #{type}\n" if type - out += "#{prefix}.class:: #{klass}\n" if klass - out += "#{prefix}.partnumber:: #{partnumber}\n" if partnumber - out += "#{prefix}.edition:: #{edition}\n" if edition - out += "#{prefix}.version:: #{version}\n" if version - out += "#{prefix}.supplementtype:: #{supplementtype}\n" if supplementtype - if supplementnumber - out += "#{prefix}.supplementnumber:: #{supplementnumber}\n" - end - out += "#{prefix}.language:: #{language}\n" if language - out += "#{prefix}.year:: #{year}\n" if year - out - end - - def remove_date - if @type == "Chinese Standard" - @docnumber.sub!(/-[12]\d\d\d/, "") - else - @docnumber.sub!(/:[12]\d\d\d/, "") - end - @year = nil - end - - # in docid manipulations, assume ISO as the default: id-part:year - def remove_part - @partnumber = nil - @docnumber = @docnumber.sub(/-\d+/, "") - end - - def all_parts - @docnumber = @docnumber + " (all parts)" - end - end -end diff --git a/lib/relaton_bib/technical_committee.rb b/lib/relaton_bib/technical_committee.rb deleted file mode 100644 index c7120bc..0000000 --- a/lib/relaton_bib/technical_committee.rb +++ /dev/null @@ -1,34 +0,0 @@ -require "relaton_bib/workgroup" - -module RelatonBib - class TechnicalCommittee - # @return [RelatonBib::WorkGroup] - attr_reader :workgroup - - # @param workgroup [RelatonBib::WorkGroup] - def initialize(workgroup) - @workgroup = workgroup - end - - # @param builder [Nokogiri::XML::Builder] - def to_xml(builder) - builder.send(:"technical-committee") { |b| workgroup.to_xml b } - end - - # @return [Hash] - def to_hash - workgroup.to_hash - end - - # @param prefix [String] - # @param count [Integer] number of technical committees - # @return [String] - def to_asciibib(prefix = "", count = 1) - pref = prefix.empty? ? prefix : "#{prefix}." - pref += "technical_committee" - out = count > 1 ? "#{pref}::\n" : "" - out += workgroup.to_asciibib pref - out - end - end -end diff --git a/lib/relaton_bib/typed_title_string.rb b/lib/relaton_bib/typed_title_string.rb deleted file mode 100644 index c6efa46..0000000 --- a/lib/relaton_bib/typed_title_string.rb +++ /dev/null @@ -1,191 +0,0 @@ -module RelatonBib - class TypedTitleStringCollection - extend Forwardable - - def_delegators :@array, :[], :first, :last, :empty?, :any?, :size, - :each, :detect, :map, :reduce, :length - - # @param title [Array<RelatonBib::TypedTitleString, Hash>] - def initialize(title = []) - @array = (title || []).map do |t| - t.is_a?(Hash) ? TypedTitleString.new(**t) : t - end - end - - # @param lang [String, nil] language code Iso639 - # @return [RelatonIsoBib::TypedTitleStringCollection] - def lang(lang = nil) - if lang - TypedTitleStringCollection.new select_lang(lang) - else self - end - end - - def delete_title_part! - titles.delete_if { |t| t.type == "title-part" } - end - - # @return [RelatonBib::TypedTitleStringCollection] - def select(&block) - TypedTitleStringCollection.new titles.select(&block) - end - - # @param init [Array, Hash] - # @return [RelatonBib::TypedTitleStringCollection] - # def reduce(init) - # self.class.new @array.reduce(init) { |m, t| yield m, t } - # end - - # @param title [RelatonBib::TypedTitleString] - # @return [self] - def <<(title) - titles << title - self - end - - # @param tcoll [RelatonBib::TypedTitleStringCollection] - # @return [RelatonBib::TypedTitleStringCollection] - def +(tcoll) - TypedTitleStringCollection.new titles + tcoll.titles - end - - def titles - @array - end - - # @param opts [Hash] - # @option opts [Nokogiri::XML::Builder] XML builder - # @option opts [String, Symbol] :lang language - def to_xml(**opts) - tl = select_lang(opts[:lang]) - tl = titles unless tl.any? - tl.each { |t| opts[:builder].title { t.to_xml opts[:builder] } } - end - - def to_hash - @array.map(&:to_hash) - end - - # - # Add main title ot bibtex entry - # - # @param [BibTeX::Entry] item bibtex entry - # - def to_bibtex(item) - tl = titles.detect { |t| t.type == "main" } || titles.first - return unless tl - - item.title = tl.title.content - end - - private - - # @param lang [String] - # @return [Array<RelatonBib::TypedTitleString] - def select_lang(lang) - titles.select { |t| t.title.language&.include? lang } - end - end - - class TypedTitleString - ARGS = %i[content language script format].freeze - - # @return [String] - attr_reader :type - - # @return [RelatonBib::FormattedString] - attr_reader :title - - # @param type [String] - # @param title [RelatonBib::FormattedString, Hash] - # @param content [String] - # @param language [String] - # @param script [String] - # @param format [String] - def initialize(**args) # rubocop:disable Metrics/MethodLength - unless args[:title] || args[:content] - raise ArgumentError, %{Keyword "title" or "content" should be passed.} - end - - @type = args[:type] - - case args[:title] - when FormattedString then @title = args[:title] - when Hash then @title = FormattedString.new(**args[:title]) - else - fsargs = args.select { |k, _v| ARGS.include? k } - @title = FormattedString.new(**fsargs) - end - end - - # - # Create TypedTitleStringCollection from string - # - # @param title [String] title string - # @param lang [String, nil] language code Iso639 - # @param script [String, nil] script code Iso15924 - # @param format [String] format text/html, text/plain - # - # @return [TypedTitleStringCollection] collection of TypedTitleString - # - def self.from_string(title, lang = nil, script = nil, format = "text/plain") - types = %w[title-intro title-main title-part] - ttls = split_title(title) - tts = ttls.map.with_index do |p, i| - next unless p - - new type: types[i], content: p, language: lang, script: script, format: format - end.compact - tts << new(type: "main", content: ttls.compact.join(" - "), - language: lang, script: script, format: format) - TypedTitleStringCollection.new tts - end - - # @param title [String] - # @return [Array<String, nil>] - def self.split_title(title) - ttls = title.sub(/\w\.Imp\s?\d+\u00A0:\u00A0/, "").split " - " - case ttls.size - when 0, 1 then [nil, ttls.first.to_s, nil] - else intro_or_part ttls - end - end - - # @param ttls [Array<String>] - # @return [Array<String, nil>] - def self.intro_or_part(ttls) - if /^(Part|Partie) \d+:/.match? ttls[1] - [nil, ttls[0], ttls[1..].join(" -- ")] - else - parts = ttls.slice(2..-1) - part = parts.join " -- " if parts.any? - [ttls[0], ttls[1], part] - end - end - - # @param builder [Nokogiri::XML::Builder] - def to_xml(builder) - builder.parent[:type] = type if type - title.to_xml builder - end - - # @return [Hash] - def to_hash - th = title.to_hash - return th unless type - - th.merge "type" => type - end - - # @param prefix [String] - # @param count [Integer] number of titles - # @return [String] - def to_asciibib(prefix = "", count = 1) # rubocop:disable Metrics/AbcSize - pref = prefix.empty? ? prefix : "#{prefix}." - out = count > 1 ? "#{pref}title::\n" : "" - out += "#{pref}title.type:: #{type}\n" if type - out += title.to_asciibib "#{pref}title", 1, !(type.nil? || type.empty?) - out - end - end -end diff --git a/lib/relaton_bib/typed_uri.rb b/lib/relaton_bib/typed_uri.rb deleted file mode 100644 index 4f8dfcd..0000000 --- a/lib/relaton_bib/typed_uri.rb +++ /dev/null @@ -1,57 +0,0 @@ -require "addressable" - -module RelatonBib - # Typed URI - class TypedUri - # @return [String, nil] - attr_reader :type, :language, :script - # @retutn [Addressable::URI] - attr_reader :content - - # @param content [String] URL - # @param type [String, nil] src/obp/rss - # @param language [String, nil] language code Iso639 (optional) (default: nil) - # @param script [String, nil] script code Iso15924 (optional) (default: nil) - def initialize(content:, type: nil, language: nil, script: nil) - @type = type - @language = language - @script = script - @content = Addressable::URI.parse content if content - end - - # @param url [String] - def content=(url) - @content = Addressable::URI.parse url - end - - # @param builder [Nokogiri::XML::Builder] - def to_xml(builder) - doc = builder.uri content.to_s - doc[:type] = type if type - doc[:language] = language if language - doc[:script] = script if script - end - - # @return [Hash] - def to_hash - hash = { "content" => content.to_s } - hash["type"] = type.to_s if type - hash["language"] = language if language - hash["script"] = script if script - hash - end - - # @param prefix [String] - # @param count [Integer] number of links - # @return [String] - def to_asciibib(prefix = "", count = 1) - pref = prefix.empty? ? "link" : "#{prefix}.link" - out = count > 1 ? "#{pref}::\n" : "" - out += "#{pref}.type:: #{type}\n" if type - out += "#{pref}.content:: #{content}\n" - out += "#{pref}.language:: #{language}\n" if language - out += "#{pref}.script:: #{script}\n" if script - out - end - end -end diff --git a/lib/relaton_bib/util.rb b/lib/relaton_bib/util.rb deleted file mode 100644 index 1922b68..0000000 --- a/lib/relaton_bib/util.rb +++ /dev/null @@ -1,16 +0,0 @@ -module RelatonBib - module Util - extend self - - PROGNAME = "relaton-bib".freeze - - def method_missing(method_name, msg = nil, prog = nil, **opts, &block) - prog ||= self::PROGNAME - Relaton.logger_pool.send method_name, msg, prog, **opts, &block - end - - def respond_to_missing?(method_name, include_private = false) - Relaton.logger_pool.respond_to?(method_name) || super - end - end -end diff --git a/lib/relaton_bib/validity.rb b/lib/relaton_bib/validity.rb deleted file mode 100644 index 04141ec..0000000 --- a/lib/relaton_bib/validity.rb +++ /dev/null @@ -1,52 +0,0 @@ -module RelatonBib - class Validity - FORMAT = "%Y-%m-%d %H:%M".freeze - - # @return [Time, nil] - attr_reader :begins - - # @return [Time, nil] - attr_reader :ends - - # @return [Time, nil] - attr_reader :revision - - # @param begins [Time, nil] - # @param ends [Time, nil] - # @param revision [Time, nil] - def initialize(begins: nil, ends: nil, revision: nil) - @begins = begins - @ends = ends - @revision = revision - end - - # @param [Nokogiri::XML::Builder] - def to_xml(builder) - builder.validity do - builder.validityBegins begins.strftime(FORMAT) if begins - builder.validityEnds ends.strftime(FORMAT) if ends - builder.revision revision.strftime(FORMAT) if revision - end - end - - # @return [Hash] - def to_hash - hash = {} - hash["begins"] = begins.strftime(FORMAT) if begins - hash["ends"] = ends.strftime(FORMAT) if ends - hash["revision"] = revision.strftime(FORMAT) if revision - hash - end - - # @param prefix [String] - # @return [String] - def to_asciibib(prefix = "") - pref = prefix.empty? ? "validity." : "#{prefix}.validity." - out = "" - out += "#{pref}begins:: #{begins.strftime(FORMAT)}\n" if begins - out += "#{pref}ends:: #{ends.strftime(FORMAT)}\n" if ends - out += "#{pref}revision:: #{revision.strftime(FORMAT)}\n" if revision - out - end - end -end diff --git a/lib/relaton_bib/version.rb b/lib/relaton_bib/version.rb deleted file mode 100644 index 553e62f..0000000 --- a/lib/relaton_bib/version.rb +++ /dev/null @@ -1,3 +0,0 @@ -module RelatonBib - VERSION = "1.20.4".freeze -end diff --git a/lib/relaton_bib/workers_pool.rb b/lib/relaton_bib/workers_pool.rb deleted file mode 100644 index 86106c6..0000000 --- a/lib/relaton_bib/workers_pool.rb +++ /dev/null @@ -1,43 +0,0 @@ -# frozen_string_literal: true - -module RelatonBib - # Workers poll. - class WorkersPool - attr_accessor :nb_hits - - def initialize(num_workers = 2) - @num_workers = num_workers < 2 ? 2 : num_workers - @queue = SizedQueue.new(num_workers * 2) - @result = [] - @nb_hits = 0 - end - - def worker(&block) - @threads = Array.new @num_workers do - Thread.new do - until (item = @queue.pop) == :END - @result << yield(item) if block - end - end - end - end - - def result - @threads.each(&:join) - @result - end - - def <<(item) - @queue << item - self - end - - def end - @num_workers.times { @queue << :END } - end - - def size - @result.size - end - end -end diff --git a/lib/relaton_bib/workgroup.rb b/lib/relaton_bib/workgroup.rb deleted file mode 100644 index 84934a5..0000000 --- a/lib/relaton_bib/workgroup.rb +++ /dev/null @@ -1,58 +0,0 @@ -module RelatonBib - class WorkGroup - # @return [String] - attr_reader :name - - # @return [Integer, nil] - attr_reader :number - - # @return [String, nil] - attr_reader :identifier, :prefix, :type - - # @param name [String] - # @param identifier [String, nil] - # @param prefix [String, nil] - # @param number [Integer, nil] - # @param type [String, nil] - def initialize(name:, identifier: nil, prefix: nil, number: nil, type: nil) - @identifier = identifier - @prefix = prefix - @name = name - @number = number - @type = type - end - - # @param builder [Nokogiri::XML::Builder] - def to_xml(builder) # rubocop:disable Metrics/AbcSize - builder.text name - builder.parent[:number] = number if number - builder.parent[:type] = type if type - builder.parent[:identifier] = identifier if identifier - builder.parent[:prefix] = prefix if prefix - end - - # @return [Hash] - def to_hash - hash = { "name" => name } - hash["number"] = number if number - hash["type"] = type if type - hash["identifier"] = identifier if identifier - hash["prefix"] = prefix if prefix - hash - end - - # @param prfx [String] - # @param count [Integer] - # @return [String] - def to_asciibib(prfx = "", count = 1) # rubocop:disable Metrics/CyclomaticComplexity - pref = prfx.empty? ? prfx : "#{prfx}." - out = count > 1 ? "#{pref}::\n" : "" - out += "#{pref}name:: #{name}\n" - out += "#{pref}number:: #{number}\n" if number - out += "#{pref}type:: #{type}\n" if type - out += "#{pref}identifier:: #{identifier}\n" if identifier - out += "#{pref}prefix:: #{prefix}\n" if prefix - out - end - end -end diff --git a/lib/relaton_bib/xml_parser.rb b/lib/relaton_bib/xml_parser.rb deleted file mode 100644 index 6d236ca..0000000 --- a/lib/relaton_bib/xml_parser.rb +++ /dev/null @@ -1,718 +0,0 @@ -require "nokogiri" - -module RelatonBib - class XMLParser - class << self - # - # Parse XML bibdata - # - # @param [String] xml XML string - # - # @return [RelatonBib::BibliographicItem, nil] bibliographic item - # - def from_xml(xml) - doc = Nokogiri::XML(xml) - doc.remove_namespaces! - bibitem = doc.at "/bibitem|/bibdata" - if bibitem - bib_item item_data(bibitem) - else - Util.warn "Can't find bibitem or bibdata element in the XML" - nil - end - end - - private - - # - # Parse bibitem data - # - # @param bibitem [Nokogiri::XML::Element] bibitem element - # - # @return [Hash] bibitem data - # - def item_data(bibitem) # rubocop:disable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity, Metrics/AbcSize, Metrics/MethodLength - ext = bibitem.at "//ext" - { - id: bibitem[:id].nil? || bibitem[:id].empty? ? nil : bibitem[:id], - type: bibitem[:type].nil? || bibitem[:type].empty? ? nil : bibitem[:type], - fetched: bibitem.at("./fetched")&.text, - title: fetch_titles(bibitem), - formattedref: fref(bibitem), - link: fetch_link(bibitem), - docid: fetch_docid(bibitem), - docnumber: bibitem.at("./docnumber")&.text, - date: fetch_dates(bibitem), - contributor: fetch_contributors(bibitem), - edition: fetch_edition(bibitem), - version: fetch_version(bibitem), - biblionote: fetch_note(bibitem), - language: fetch_language(bibitem), - script: fetch_script(bibitem), - abstract: fetch_abstract(bibitem), - docstatus: fetch_status(bibitem), - copyright: fetch_copyright(bibitem), - relation: fetch_relations(bibitem), - series: fetch_series(bibitem), - medium: fetch_medium(bibitem), - place: fetch_place(bibitem), - extent: fetch_extent(bibitem), - size: fetch_size(bibitem), - accesslocation: bibitem.xpath("./accesslocation").map(&:text), - classification: fetch_classification(bibitem), - keyword: bibitem.xpath("keyword").map(&:text), - license: bibitem.xpath("license").map(&:text), - validity: fetch_validity(bibitem), - doctype: fetch_doctype(ext), - subdoctype: ext&.at("subdoctype")&.text, - editorialgroup: fetch_editorialgroup(ext), - ics: fetch_ics(ext), - structuredidentifier: fetch_structuredidentifier(ext), - } - end - - # - # Fetch version. - # - # @param [Nokogiri::XML::Elemetn] item bibitem element - # - # @return [Array<RelatonBib::BibliographicItem::Version>] versions - # - def fetch_version(item) - item.xpath("./version").map do |v| - revision_date = v.at("revision-date")&.text - draft = v.at("draft")&.text - RelatonBib::BibliographicItem::Version.new revision_date, draft - end - end - - # - # Fetch edition - # - # @param [Nokogiri::XML::Elemetn] item bibitem element - # - # @return [RelatonBib::Edition, nil] edition - # - def fetch_edition(item) - edt = item.at("./edition") - return unless edt - - Edition.new content: edt.text, number: edt[:number] - end - - # - # Fetch place. - # - # @param [Nokogiri::XML::Element] item bibitem element - # - # @return [Array<RelatonBib::Place>] array of places - # - def fetch_place(item) - item.xpath("./place").map do |pl| - if (city = pl.at("./city")) - Place.new(city: city.text, region: create_region_country(pl), - country: create_region_country(pl, "country")) - else - Place.new(name: pl.text) - end - end - end - - # - # Create region or country from place element - # - # @param [Nokogiri::XML::Element] place place element - # @param [String] node name of the node to parse - # - # @return [Array<RelatonBib::Place::RegionType>] <description> - # - def create_region_country(place, node = "region") - place.xpath("./#{node}").map do |r| - Place::RegionType.new(name: r.text, iso: r[:iso], recommended: r[:recommended]) - end - end - - def fetch_note(item) - bnotes = item.xpath("./note").map do |n| - BiblioNote.new( - content: n.text, - type: n[:type], - format: n[:format], - language: n[:language], - script: n[:script], - ) - end - BiblioNoteCollection.new bnotes - end - - # - # Fetch language - # - # @param [Nokogiri::XML::Element] item bibitem element - # - # @return [Array<String>] language en, fr, etc. - # - def fetch_language(item) - item.xpath("./language").reduce([]) do |a, l| - l.text.empty? ? a : a << l.text - end - end - - # - # Fetch script - # - # @param [Nokogiri::XML::Element] item XML element - # - # @return [Array<String>] scripts Latn, Cyr, etc. - # - def fetch_script(item) - item.xpath("./script").reduce([]) do |a, s| - s.text.empty? ? a : a << s.text - end - end - - # - # Fetch series - # - # @param [Nokogiri::XML::Element] item bibitem element - # - # @return [Array<RelatonBib::Series>] series - # - def fetch_series(item) # rubocop:disable Metrics/CyclomaticComplexity,Metrics/AbcSize,Metrics/MethodLength,Metrics/PerceivedComplexity - item.xpath("./series").reduce([]) do |mem, sr| - formattedref = fref(sr) - title = ttitle(sr.at("title")) - next mem unless formattedref || title - - abbreviation = localized_string sr.at("abbreviation") - mem << Series.new( - type: sr[:type], formattedref: formattedref, - title: title, place: sr.at("place")&.text, - organization: sr.at("organization")&.text, - abbreviation: abbreviation, from: sr.at("from")&.text, - to: sr.at("to")&.text, number: sr.at("number")&.text, - partnumber: sr.at("partnumber")&.text, run: sr.at("run")&.text - ) - end - end - - # - # Fetch medium - # - # @param [Nokogiri::XML::Element] item item element - # - # @return [RelatonBib::Medium, nil] medium - # - def fetch_medium(item) # rubocop:disable Metrics/CyclomaticComplexity,Metrics/AbcSize,Metrics/PerceivedComplexity - medium = item.at("./medium") - return unless medium - - Medium.new( - content: medium.at("content")&.text, genre: medium.at("genre")&.text, - form: medium.at("form")&.text, carrier: medium.at("carrier")&.text, - size: medium.at("size")&.text, scale: medium.at("scale")&.text - ) - end - - # - # Fetch extent - # - # @param [Nokogiri::XML::Element] item item element - # - # @return [Array<RelatonBib::Extent>] extent - # - def fetch_extent(item) - item.xpath("./extent").map do |ex| - RelatonBib::Extent.new localities(ex) - end - end - - # - # Fetch size - # - # @param [Nokogiri::XML::Element] item item element - # - # @return [RelatonBib::BibliographicSize, nil] size - # - def fetch_size(item) - size = item.xpath("./size/value").map do |sz| - BibliographicSize::Value.new type: sz[:type], value: sz.text - end - BibliographicSize.new size if size.any? - end - - # - # Fetch classification - # - # @param [Nokogiri::XML::Element] item bibitem element - # - # @return [Array<RelatonBib::Classification>] classifications - # - def fetch_classification(item) - item.xpath("classification").map do |cls| - Classification.new type: cls[:type], value: cls.text - end - end - - # - # Parse validity - # - # @param [Nokogiri::XML::Element] item bibitem element - # - # @return [RelatonBib::Validity, nil] validity - # - def fetch_validity(item) - vl = item.at("./validity") - return unless vl - - begins = (b = vl.at("validityBegins")) && - Time.strptime(b.text, "%Y-%m-%d %H:%M") - ends = (e = vl.at("validityEnds")) && - Time.strptime(e.text, "%Y-%m-%d %H:%M") - revision = (r = vl.at("revision")) && - Time.strptime(r.text, "%Y-%m-%d %H:%M") - Validity.new begins: begins, ends: ends, revision: revision - end - - def fetch_doctype(ext) - dt = ext&.at("doctype") - return unless dt - - create_doctype dt - end - - def create_doctype(type) - DocumentType.new type: type.text, abbreviation: type[:abbreviation] - end - - # @param item [Nokogiri::XML::Element] - # @return [Array<RelatonBib::DocumentIdentifier>] - def fetch_docid(item) - item.xpath("./docidentifier").map do |id| - args = id.to_h.transform_keys(&:to_sym) - args[:id] = id.children.map { |n| n.text? ? n.content : n.to_xml }.join - args[:primary] = id[:primary] == "true" ? true : nil - create_docid(**args) - end - end - - def create_docid(**args) - DocumentIdentifier.new(**args) - end - - # @param item [Nokogiri::XML::Element] - # @return [RelatonBib::TypedTitleStringCollection] - def fetch_titles(item) - ttl = item.xpath("./title").map { |t| ttitle t } - TypedTitleStringCollection.new ttl - end - - # @param title [Nokogiri::XML::Element] - # @return [RelatonBib::TypedTitleString] - def ttitle(title) - return unless title - - content = variants(title) - content = title.children.map { |n| n.text? ? n.content : n.to_xml }.join unless content.any? - TypedTitleString.new( - type: title[:type], content: content, language: title[:language], - script: title[:script], format: title[:format] - ) - end - - # @param title [Nokogiri::XML::Element] - # @return [Array<RelatonBib::LocalizedString>] - def variants(elm) - elm.xpath("variant").map { |v| localized_string v } - end - - # - # Parse status - # - # @param [Nokogiri::XML::Element] item XML element - # - # @return [RelatonBib::DocumentStatus, nil] status - # - def fetch_status(item) - status = item.at("./status") - return unless status - - stg = status.at "stage" - DocumentStatus.new( - stage: stg ? stage(stg) : status.text, - substage: stage(status.at("substage")), - iteration: status.at("iteration")&.text, - ) - end - - # @param node [Nokogiri::XML::Elemen] - # @return [RelatonBib::DocumentStatus::Stage] - def stage(elm) - return unless elm - - DocumentStatus::Stage.new(value: elm.text, - abbreviation: elm[:abbreviation]) - end - - # @param node [Nokogiri::XML::Elemen] - # @return [Array<RelatonBib::BibliographicDate>] - def fetch_dates(item) # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity,Metrics/PerceivedComplexity - item.xpath("./date").each_with_object([]) do |d, a| - type = d[:type].to_s.empty? ? "published" : d[:type] - if (on = d.at("on")) - a << RelatonBib::BibliographicDate.new(type: type, on: on.text, - to: d.at("to")&.text) - elsif (from = d.at("from")) - a << RelatonBib::BibliographicDate.new(type: type, from: from.text, - to: d.at("to")&.text) - end - end - end - - # - # Parse organization - # - # @param [Nokogiri::XML::Element] org XML element - # - # @return [RelatonBib::Organization, nil] organization - # - def get_org(org) # rubocop:disable Metrics/AbcSize, Metrics/MethodLength - return unless org - - names = org.xpath("name").map do |n| - { content: n.text, language: n[:language], script: n[:script] } - end - identifier = org.xpath("./identifier").map do |i| - OrgIdentifier.new(i[:type], i.text) - end - subdiv = org.xpath("subdivision").map &:text - contact = parse_contact org - logo = fetch_image org.at("./logo/image") - Organization.new( - name: names, abbreviation: org.at("abbreviation")&.text, - subdivision: subdiv, # url: org.at("uri")&.text, - identifier: identifier, contact: contact, logo: logo - ) - end - - def fetch_image(elm) - return unless elm - - Image.new(**elm.to_h.transform_keys(&:to_sym)) - end - - # - # Parse person from XML - # - # @param [Nokogiri::XML::Element] person XML element - # - # @return [RelatonBib::Person, nil] person - # - def get_person(person) # rubocop:disable Metrics/AbcSize, Metrics/MethodLength - return unless person - - affiliations = person.xpath("./affiliation").map { |a| fetch_affiliation a } - - contact = parse_contact person - identifier = person.xpath("./identifier").map do |pi| - PersonIdentifier.new pi[:type], pi.text - end - - Person.new( - name: full_name(person.at("./name")), - credential: person.xpath("./credential").map(&:text), - affiliation: affiliations, - contact: contact, - identifier: identifier, - ) - end - - def full_name(name) - cname = localized_string name.at("./completename") - sname = localized_string name.at("./surname") - abbreviation = localized_string name.at("./abbreviation") - - FullName.new( - completename: cname, surname: sname, abbreviation: abbreviation, - initials: parse_initials(name), forename: parse_forename(name), - addition: name_part(name, "addition"), prefix: name_part(name, "prefix") - ) - end - - def fetch_affiliation(elm) - org = get_org elm.at("./organization") - desc = elm.xpath("./description").map do |e| - FormattedString.new(content: e.text, language: e[:language], - script: e[:script], format: e[:format]) - end - name = localized_string elm.at("./name") - Affiliation.new organization: org, description: desc, name: name - end - - def localized_string(elm) - return unless elm - - LocalizedString.new(elm.text, elm[:language], elm[:script]) - end - - # - # Parse contact information - # - # @param [Nokogiri::XML::Element] contrib contributor element - # - # @return [Array<RelatonBib::Address, RelatonBib::Contact>] contacts - # - def parse_contact(contrib) - contrib.xpath("./address|./phone|./email|./uri").map do |c| - parse_address(c) || Contact.new(type: c.name, value: c.text, subtype: c[:type]) - end - end - - # - # Parse address - # - # @param [Nokogiri::XML::Element] contact contact element - # - # @return [RelatonBib::Address] address - # - def parse_address(contact) # rubocop:disable Metrics/AbcSize,Metrics/MethodLength,Metrics/CyclomaticComplexity,Metrics/PerceivedComplexity - return unless contact.name == "address" - - Address.new( - street: contact.xpath("./street").map(&:text), - city: contact.at("./city")&.text, - state: contact.at("./state")&.text, - country: contact.at("./country")&.text, - postcode: contact.at("./postcode")&.text, - formatted_address: contact.at("./formattedAddress")&.text, - ) - end - - # - # Parse initials - # - # @param [Nokogiri::XML::Element] name person name element - # - # @return [RelatonBib::LocalizedString, nil] initials - # - def parse_initials(name) - localized_string name.at("./formatted-initials") - end - - # - # Parse forename - # - # @param [Nokogiri::XML::Element] name person name element - # - # @return [Array<RelatonBib::Forename>] forenames - # - def parse_forename(name) - name.xpath("./forename").map do |np| - args = np.attributes.each_with_object({}) { |(k, v), h| h[k.to_sym] = v.to_s } - args[:content] = np.text - Forename.new(**args) - end - end - - # - # Parse name part - # - # @param [Nokogiri::XML::Element] name person name element - # @param [String] part name part - # - # @return [Array<RelatonBib::LocalizedString>] name parts - # - def name_part(name, part) - name.xpath("./#{part}").map { |np| localized_string np } - end - - # @param item [Nokogiri::XML::Element] - # @return [Array<RelatonBib::ContributionInfo>] - def fetch_contributors(item) - item.xpath("./contributor").map { |c| fetch_contribution_info c } - end - - def fetch_contribution_info(contrib) - entity = get_org(contrib.at("./organization")) || get_person(contrib.at("./person")) - role = contrib.xpath("./role").map do |r| - { type: r[:type], description: r.xpath("./description").map(&:text) } - end - ContributionInfo.new entity: entity, role: role - end - - # @param item [Nokogiri::XML::Element] - # @return [Array<RelatonBib::FormattedString>] - def fetch_abstract(item) - item.xpath("./abstract").map do |a| - c = a.children.to_xml(encoding: "utf-8").strip - FormattedString.new(content: c, language: a[:language], - script: a[:script], format: a[:format]) - end - end - - # @param item [Nokogiri::XML::Element] - # @return [Array<RelatonBib::CopyrightAssociation>] - def fetch_copyright(item) - item.xpath("./copyright").map do |cp| - owner = cp.xpath("owner").map { |o| fetch_contribution_info o } - from = cp.at("from")&.text - to = cp.at("to")&.text - scope = cp.at("scope")&.text - CopyrightAssociation.new(owner: owner, from: from, to: to, scope: scope) - end - end - - # @param item [Nokogiri::XML::Element] - # @return [Arra<RelatonBib::TypedUri>] - def fetch_link(item) - item.xpath("./uri").map do |l| - TypedUri.new(type: l[:type], content: l.text, language: l[:language], - script: l[:script]) - end - end - - # @param item [Nokogiri::XML::Element] - # @param klass [RelatonBib::DocumentRelation.class, - # RelatonNist::DocumentRelation.class] - # @return [Array<RelatonBib::DocumentRelation>] - def fetch_relations(item, klass = DocumentRelation) - item.xpath("./relation").map do |rel| - klass.new( - type: rel[:type].nil? || rel[:type].empty? ? nil : rel[:type], - description: relation_description(rel), - bibitem: bib_item(item_data(rel.at("./bibitem"))), - locality: localities(rel), - source_locality: source_localities(rel), - ) - end - end - - # @param rel [Nokogiri::XML::Element] - # @return [RelatonBib::FormattedString, nil] - def relation_description(rel) - d = rel.at "./description" - return unless d - - FormattedString.new(content: d.text, language: d[:language], - script: d[:script], format: d[:format]) - end - - # - # Create bibliographic item - # - # @param item_hash [Hash] bibliographic item hash - # - # @return [RelatonBib::BibliographicItem] bibliographic item - # - def bib_item(item_hash) - BibliographicItem.new(**item_hash) - end - - # - # Parse locality - # - # @param rel [Nokogiri::XML::Element] relation element - # - # @return [Array<RelatonBib::Locality, RelatonBib::LocalityStack>] localities - # - def localities(rel) - rel.xpath("./locality|./localityStack").map do |lc| - if lc.name == "locality" - locality lc - else - LocalityStack.new(lc.xpath("./locality").map { |l| locality l }) - end - end - end - - # - # Create Locality object from Nokogiri::XML::Element - # - # @param loc [Nokogiri::XML::Element] - # @param klass [RelatonBib::Locality, RelatonBib::LocalityStack] - # - # @return [RelatonBib::Locality] - def locality(loc, klass = Locality) - klass.new( - loc[:type], - loc.at("./referenceFrom")&.text, - loc.at("./referenceTo")&.text, - ) - end - - # @param rel [Nokogiri::XML::Element] - # @return [Array<RelatonBib::SourceLocality, - # RelatonBib::SourceLocalityStack>] - def source_localities(rel) - rel.xpath("./sourceLocality|./sourceLocalityStack").map do |loc| - if loc.name == "sourceLocality" - # src_locs = loc.xapth("./sourceLocality").map { |sl| locality(sl, SourceLocality) } - # SourceLocalityStack.new src_locs - locality loc, SourceLocality - else - sls = loc.xpath("./sourceLocality").map { |l| locality l, SourceLocality } - SourceLocalityStack.new sls - end - end - end - - # @param item [Nokogiri::XML::Element] - # @return [RelatonBib::FormattedRef, nil] - def fref(item) - ident = item&.at("./formattedref") - return unless ident - - FormattedRef.new( - content: ident.children.to_s, format: ident[:format], - language: ident[:language], script: ident[:script] - ) - end - - # @param ext [Nokogiri::XML::Element] - # @return [RelatonBib::EditorialGroup, nil] - def fetch_editorialgroup(ext) - return unless ext && (eg = ext.at "editorialgroup") - - eg = eg.xpath("technical-committee").map do |tc| - wg = WorkGroup.new( - name: tc.text, number: tc[:number]&.to_i, type: tc[:type], - identifier: tc[:identifier], prefix: tc[:prefix] - ) - TechnicalCommittee.new wg - end - EditorialGroup.new eg if eg.any? - end - - def fetch_ics(ext) - return [] unless ext - - ext.xpath("ics").map do |ics| - ICS.new code: ics.at("code")&.text, text: ics.at("text")&.text - end - end - - # @param ext [Nokogiri::XML::Element] - # @return [RelatonBib::StructuredIdentifierCollection] - def fetch_structuredidentifier(ext) # rubocop:disable Metrics/AbcSize,Metrics/MethodLength,Metrics/CyclomaticComplexity,Metrics/PerceivedComplexity - return unless ext - - sids = ext.xpath("structuredidentifier").map do |si| - StructuredIdentifier.new( - type: si[:type], - agency: si.xpath("agency").map(&:text), - class: si.at("class")&.text, - docnumber: si.at("docnumber")&.text, - partnumber: si.at("partnumber")&.text, - edition: si.at("edition")&.text, - version: si.at("version")&.text, - supplementtype: si.at("supplementtype")&.text, - supplementnumber: si.at("supplementnumber")&.text, - language: si.at("language")&.text, - year: si.at("year")&.text, - ) - end - StructuredIdentifierCollection.new sids - end - end - end -end diff --git a/relaton-bib.gemspec b/relaton-bib.gemspec index 7f10a33..1149dc4 100644 --- a/relaton-bib.gemspec +++ b/relaton-bib.gemspec @@ -1,15 +1,15 @@ lib = File.expand_path("lib", __dir__) $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib) -require "relaton_bib/version" +require "relaton/bib/gem_version" Gem::Specification.new do |spec| spec.name = "relaton-bib" - spec.version = RelatonBib::VERSION + spec.version = Relaton::Bib::VERSION spec.authors = ["Ribose Inc."] spec.email = ["open.source@ribose.com"] - spec.summary = "RelatonBib: Ruby XMLDOC impementation." - spec.description = "RelatonBib: Ruby XMLDOC impementation." + spec.summary = "Relaton::Bib: Ruby XMLDOC impementation." + spec.description = "Relaton::Bib: Ruby XMLDOC impementation." spec.homepage = "https://github.com/relaton/relaton-bib" spec.license = "BSD-2-Clause" @@ -27,6 +27,7 @@ Gem::Specification.new do |spec| spec.add_dependency "bibtex-ruby" spec.add_dependency "htmlentities" spec.add_dependency "iso639" + spec.add_dependency "lutaml-model", "~> 0.6" spec.add_dependency "nokogiri", "~> 1.16.0" spec.add_dependency "relaton-logger", "~> 0.2.0" end diff --git a/spec/examples/asciibib.adoc b/spec/fixtures/asciibib.adoc similarity index 100% rename from spec/examples/asciibib.adoc rename to spec/fixtures/asciibib.adoc diff --git a/spec/examples/bcp_item.xml b/spec/fixtures/bcp_item.xml similarity index 100% rename from spec/examples/bcp_item.xml rename to spec/fixtures/bcp_item.xml diff --git a/spec/examples/bcp_item.yml b/spec/fixtures/bcp_item.yml similarity index 100% rename from spec/examples/bcp_item.yml rename to spec/fixtures/bcp_item.yml diff --git a/spec/examples/bib_item.yml b/spec/fixtures/bib_item.yml similarity index 93% rename from spec/examples/bib_item.yml rename to spec/fixtures/bib_item.yml index 3489c89..a6d1638 100644 --- a/spec/examples/bib_item.yml +++ b/spec/fixtures/bib_item.yml @@ -181,6 +181,9 @@ contributor: identifier: type: uri id: www.person.com + role: + - type: author + description: Author description - person: name: @@ -300,13 +303,12 @@ series: content: Journal number: "7" - title: - content: - - content: Series - language: en - script: Latn - - content: Séries - language: fr - script: Latn + - content: Series + language: en + script: Latn + - content: Séries + language: fr + script: Latn - title: content: RFC number: "4" @@ -320,10 +322,10 @@ place: - bib place - city: Geneva region: - - name: Region + - name: Europe country: - iso: CH - name: Switzelznd + name: Switzeland recommended: true extent: @@ -366,9 +368,21 @@ keyword: license: License validity: - begins: "2010-10-10 12:21" - ends: "2011-02-03 18:30" - revision: "2011-03-04 09:00" + begins: "2010-10-10" + ends: "2011-02-03" + revision: "2011-03-04" + +# depiction: +# scope: cover +# image: +# srl: cover1.png +# mimetype: image/png +# filename: cover1.png +# width: "200" +# height: 100% +# alt: Cover 1 +# title: Cover #1 +# longdesc: Cover number 1 ext: doctype: diff --git a/spec/fixtures/bibdata_from_old_yaml.xml b/spec/fixtures/bibdata_from_old_yaml.xml new file mode 100644 index 0000000..c5b7ffe --- /dev/null +++ b/spec/fixtures/bibdata_from_old_yaml.xml @@ -0,0 +1,331 @@ +<bibdata type="standard" schema-version="v1.4.1"> + <fetched>2024-12-11</fetched> + <title>Geographic information</title> + <title language="fr" script="Latn">Information géographique</title> + <uri type="src" language="en" script="Latn">https://www.iso.org/standard/53798.html</uri> + <uri type="obp">https://www.iso.org/obp/ui/#!iso:std:53798:en</uri> + <uri type="rss">https://www.iso.org/contents/data/standard/05/37/53798.detail.rss</uri> + <uri type="doi">http://standrd.org/doi-123</uri> + <uri type="file">file://path/file</uri> + <docidentifier type="ISO" primary="true" language="en" script="Latn">ISO TC 211</docidentifier> + <docidentifier type="isbn">ISBN</docidentifier> + <docidentifier type="lccn">LCCN</docidentifier> + <docidentifier type="issn" scope="series">ISSN</docidentifier> + <docidentifier type="URN">urn:iso:std:iso:123:stage-90.93:ed-3:en,fr</docidentifier> + <docidentifier>XYZ</docidentifier> + <docidentifier type="DOI">10.17487/rfc1149</docidentifier> + <docidentifier type="Internet-Draft">draft-ietf-somewg-someprotocol-07</docidentifier> + <docnumber>TC211</docnumber> + <date type="issued"> + <on>2014</on> + </date> + <date type="published"> + <on>2014-04</on> + </date> + <date type="accessed"> + <on>2015-05-20</on> + </date> + <contributor> + <role type="publisher"> + <description>Publisher role</description> + </role> + <organization> + <name>International Organization for Standardization</name> + <subdivision> + <name>division</name> + </subdivision> + <abbreviation>ISO</abbreviation> + <uri>www.iso.org</uri> + <logo> + <image id="logo1" src="logo1.png" mimetype="image/png" filename="logo1.png" width="200" height="100%" alt="Logo 1" title="Logo #1" longdesc="Logo number 1"/> + </logo> + </organization> + </contributor> + <contributor> + <role type="author"/> + <person> + <name> + <abbreviation>AB</abbreviation> + <completename language="en" script="Latn">A. Bierman</completename> + </name> + <credential>Credential</credential> + <affiliation> + <organization> + <name>IETF</name> + <abbreviation>IETF</abbreviation> + <identifier type="uri">www.ietf.org</identifier> + </organization> + </affiliation> + <address> + <street>Street</street> + <city>City</city> + <state>State</state> + <country>Country</country> + <postcode>123456</postcode> + </address> + <phone type="work">223322</phone> + <email>person@email.org</email> + <uri>www.person.com</uri> + </person> + </contributor> + <contributor> + <role type="publisher"> + <description>Publisher description</description> + </role> + <role type="editor"> + <description>Editor description</description> + </role> + <organization> + <name>Institute of Electrical and Electronics Engineers</name> + <abbreviation>IEEE</abbreviation> + <identifier type="uri">www.ieee.org</identifier> + <address> + <formattedAddress>Formatted address</formattedAddress> + </address> + </organization> + </contributor> + <contributor> + <role type="author"> + <description>Author description</description> + </role> + <person> + <name> + <prefix>Prefix</prefix> + <forename>Arnold</forename> + <formatted-initials>A.</formatted-initials> + <surname>Bierman</surname> + <addition>Addition</addition> + </name> + <affiliation> + <name language="en" script="Latn">Name</name> + <description language="en">Description</description> + <organization> + <name>IETF</name> + <abbreviation>IETF</abbreviation> + </organization> + </affiliation> + <identifier type="uri">www.person.com</identifier> + <address> + <street>Street</street> + <city>City</city> + <state>State</state> + <country>Country</country> + <postcode>123456</postcode> + </address> + <phone type="work">223322</phone> + </person> + </contributor> + <contributor> + <role type="editor"/> + <person> + <name> + <forename language="en" script="Latn" initial="A">Arnold</forename> + <forename initial="B"/> + <formatted-initials language="en" script="Latn">A. B.</formatted-initials> + <surname language="en" script="Latn">Bierman</surname> + </name> + </person> + </contributor> + <contributor> + <role type="distributor"> + <description>sponsor</description> + </role> + <organization> + <name>World Wide Web Consortium</name> + <address> + <formattedAddress>Address string</formattedAddress> + </address> + </organization> + </contributor> + <edition number="1.2">Edition 1</edition> + <version> + <revision-date>2019-04-01</revision-date> + <draft>draft</draft> + </version> + <note>note</note> + <note type="annote">An note</note> + <note type="howpublished">How published</note> + <note type="comment">Comment</note> + <note type="tableOfContents">Table Of Contents</note> + <language>en</language> + <language>fr</language> + <script>Latn</script> + <abstract language="en" script="Latn"> + <p>ISO 19115-1:2014 defines the schema required for...</p> + </abstract> + <abstract language="fr" script="Latn">L'ISO 19115-1:2014 définit le schéma requis pour...</abstract> + <status> + <stage abbreviation="CD">30</stage> + <substage>substage</substage> + <iteration>final</iteration> + </status> + <copyright> + <from>2014</from> + <to>2020</to> + <owner> + <organization> + <name>International Organization for Standardization</name> + <abbreviation>ISO</abbreviation> + <uri>www.iso.org</uri> + </organization> + </owner> + <scope>Scope</scope> + </copyright> + <relation type="updates"> + <bibitem> + <formattedref>ISO 19115:2003</formattedref> + </bibitem> + <locality type="section"> + <referenceFrom>Reference from</referenceFrom> + </locality> + <sourceLocalityStack> + <sourceLocality type="volume"> + <referenceFrom>2</referenceFrom> + </sourceLocality> + <sourceLocality type="chapter"> + <referenceFrom>3</referenceFrom> + </sourceLocality> + </sourceLocalityStack> + </relation> + <relation type="obsoletes"> + <description>supersedes</description> + <bibitem type="standard"> + <formattedref>ISO 19115:2003/Cor 1:2006</formattedref> + </bibitem> + <localityStack> + <locality type="chapter"> + <referenceFrom>1</referenceFrom> + </locality> + </localityStack> + <localityStack> + <locality type="page"> + <referenceFrom>2</referenceFrom> + </locality> + </localityStack> + <sourceLocality type="section"> + <referenceFrom>Reference from</referenceFrom> + <referenceTo>Reference to</referenceTo> + </sourceLocality> + </relation> + <relation type="partOf"> + <bibitem> + <title type="main">Book title</title> + </bibitem> + </relation> + <series type="Internet-Draft"> + <title>Internet-Draft</title> + <number>draft-ietf-somewg-someprotocol-07</number> + <run>seriesrun</run> + </series> + <series type="main"> + <title type="original" format="text/plain" language="en" script="Latn">ISO/IEC FDIS 10118-3</title> + <place> + <formattedPlace>Serie's place</formattedPlace> + </place> + <organization>Serie's organization</organization> + <abbreviation>ABVR</abbreviation> + <from>2009-02-01</from> + <to>2010-12-20</to> + <number>serie1234</number> + <partnumber>part5678</partnumber> + </series> + <series type="alt"> + <formattedref>serieref</formattedref> + <title>Formattedref</title> + </series> + <series type="journal"> + <title>Journal</title> + <number>7</number> + </series> + <series> + <title language="en" script="Latn">Series</title> + <title language="fr" script="Latn">Séries</title> + </series> + <series> + <title>RFC</title> + <number>4</number> + </series> + <medium> + <form>medium form</form> + <size>medium size</size> + <scale>medium scale</scale> + </medium> + <place> + <formattedPlace>bib place</formattedPlace> + </place> + <place> + <city>Geneva</city> + <region>Europe</region> + <country iso="CH" recommended="true">Switzeland</country> + </place> + <extent> + <locality type="section"> + <referenceFrom>Reference from</referenceFrom> + <referenceTo>Reference to</referenceTo> + </locality> + <locality type="chapter"> + <referenceFrom>4</referenceFrom> + </locality> + </extent> + <extent> + <localityStack> + <locality type="page"> + <referenceFrom>10</referenceFrom> + <referenceTo>20</referenceTo> + </locality> + <locality type="volume"> + <referenceFrom>1</referenceFrom> + </locality> + </localityStack> + </extent> + <size> + <value type="page">490</value> + <value type="plate">3</value> + </size> + <accesslocation>accesslocation1</accesslocation> + <accesslocation>accesslocation2</accesslocation> + <license>License</license> + <classification type="type">value</classification> + <classification type="keyword">Keywords</classification> + <classification type="mendeley">Mendeley Tags</classification> + <keyword> + <taxon>Keyword</taxon> + </keyword> + <keyword> + <taxon>Key Word</taxon> + </keyword> + <validity> + <validityBegins>2010-10-10</validityBegins> + <validityEnds>2011-02-03</validityEnds> + <revision>2011-03-04</revision> + </validity> + <ext> + <doctype abbreviation="DCT">Doctype</doctype> + <subdoctype>Subdoctype</subdoctype> + <flavor>iso</flavor> + <editorialgroup> + <technical-committee number="1" type="Type" identifier="Identifier" prefix="Prefix">Editorial group</technical-committee> + </editorialgroup> + <ics> + <code>01</code> + <text>First</text> + </ics> + <structuredidentifier type="type 1"> + <agency>agency 1</agency> + <agency>agency 2</agency> + <class>class 1</class> + <docnumber>123</docnumber> + <partnumber>4</partnumber> + <edition>1</edition> + <version>2</version> + <supplementtype>type 2</supplementtype> + <supplementnumber>5</supplementnumber> + <language>en</language> + <year>2020</year> + </structuredidentifier> + <structuredidentifier> + <agency>agency 3</agency> + <docnumber>456</docnumber> + </structuredidentifier> + </ext> +</bibdata> diff --git a/spec/examples/bibdata_item.xml b/spec/fixtures/bibdata_item.xml similarity index 90% rename from spec/examples/bibdata_item.xml rename to spec/fixtures/bibdata_item.xml index 0dcb33b..f8faa18 100644 --- a/spec/examples/bibdata_item.xml +++ b/spec/fixtures/bibdata_item.xml @@ -32,7 +32,9 @@ </role> <organization> <name>International Organization for Standardization</name> - <subdivision>division</subdivision> + <subdivision> + <name>Subdivision</name> + </subdivision> <abbreviation>ISO</abbreviation> <uri>www.iso.org</uri> <logo> @@ -147,10 +149,10 @@ <language>en</language> <language>fr</language> <script>Latn</script> - <abstract format="text/html" language="en" script="Latn"> + <abstract language="en" script="Latn"> <p>ISO 19115-1:2014 defines the schema required for...</p> </abstract> - <abstract format="text/plain" language="fr" script="Latn">L'ISO 19115-1:2014 définit le schéma requis pour...</abstract> + <abstract language="fr" script="Latn">L'ISO 19115-1:2014 définit le schéma requis pour...</abstract> <status> <stage abbreviation="CD">30</stage> <substage>substage</substage> @@ -170,7 +172,7 @@ </copyright> <relation type="updates"> <bibitem> - <formattedref format="text/plain">ISO 19115:2003</formattedref> + <formattedref>ISO 19115:2003</formattedref> </bibitem> <locality type="section"> <referenceFrom>Reference from</referenceFrom> @@ -185,9 +187,9 @@ </sourceLocalityStack> </relation> <relation type="obsoletes"> - <description format="text/plain">supersedes</description> + <description>supersedes</description> <bibitem type="standard"> - <formattedref format="text/plain">ISO 19115:2003/Cor 1:2006</formattedref> + <formattedref>ISO 19115:2003/Cor 1:2006</formattedref> </bibitem> <localityStack> <locality type="chapter"> @@ -216,7 +218,9 @@ </series> <series type="main"> <title type="original" format="text/plain" language="en" script="Latn">ISO/IEC FDIS 10118-3</title> - <place>Serie's place</place> + <place> + <formattedPlace>Serie's place</formattedPlace> + </place> <organization>Serie's organization</organization> <abbreviation>ABVR</abbreviation> <from>2009-02-01</from> @@ -225,7 +229,7 @@ <partnumber>part5678</partnumber> </series> <series type="alt"> - <formattedref format="text/plain" language="en" script="Latn">serieref</formattedref> + <formattedref>serieref</formattedref> <title format="text/plain">Formattedref</title> </series> <series type="journal"> @@ -233,10 +237,8 @@ <number>7</number> </series> <series> - <title format="text/plain"> - <variant language="en" script="Latn">Series</variant> - <variant language="fr" script="Latn">Séries</variant> - </title> + <title format="text/plain" language="en" script="Latn">Series</title> + <title language="fr" script="Latn">Séries</title> </series> <series> <title format="text/plain">RFC</title> @@ -247,7 +249,9 @@ <size>medium size</size> <scale>medium scale</scale> </medium> - <place>bib place</place> + <place> + <formattedPlace>bib place</formattedPlace> + </place> <place> <city>Geneva</city> <region>Region</region> @@ -283,16 +287,21 @@ <classification type="type">value</classification> <classification type="keyword">Keywords</classification> <classification type="mendeley">Mendeley Tags</classification> - <keyword>Keyword</keyword> - <keyword>Key Word</keyword> + <keyword> + <taxon>Keyword</taxon> + </keyword> + <keyword> + <taxon>Key Word</taxon> + </keyword> <validity> - <validityBegins>2010-10-10 12:21</validityBegins> - <validityEnds>2011-02-03 18:30</validityEnds> - <revision>2011-03-04 09:00</revision> + <validityBegins>2010-10-10</validityBegins> + <validityEnds>2011-02-03</validityEnds> + <revision>2011-03-04</revision> </validity> <ext> <doctype abbreviation="DCT">Doctype</doctype> <subdoctype>Subdoctype</subdoctype> + <flavor>iso</flavor> <editorialgroup> <technical-committee number="1" type="Type" identifier="Identifier" prefix="Prefix">Editorial group</technical-committee> </editorialgroup> @@ -318,4 +327,4 @@ <docnumber>456</docnumber> </structuredidentifier> </ext> -</bibdata> \ No newline at end of file +</bibdata> diff --git a/spec/examples/bibdata_item_fr.xml b/spec/fixtures/bibdata_item_fr.xml similarity index 100% rename from spec/examples/bibdata_item_fr.xml rename to spec/fixtures/bibdata_item_fr.xml diff --git a/spec/fixtures/bibitem.xml b/spec/fixtures/bibitem.xml new file mode 100644 index 0000000..123f60a --- /dev/null +++ b/spec/fixtures/bibitem.xml @@ -0,0 +1,301 @@ +<bibitem id="ISOTC211" type="standard" schema-version="v1.4.1"> + <fetched>2024-12-11</fetched> + <formattedref>ISO TC 211</formattedref> + <title type="title-main" format="text/plain">Geographic information</title> + <title type="main" format="text/plain">Geographic information</title> + <title format="text/plain" language="fr" script="Latn">Information géographique</title> + <uri type="src" language="en" script="Latn">https://www.iso.org/standard/53798.html</uri> + <uri type="obp">https://www.iso.org/obp/ui/#!iso:std:53798:en</uri> + <uri type="rss">https://www.iso.org/contents/data/standard/05/37/53798.detail.rss</uri> + <uri type="doi">http://standrd.org/doi-123</uri> + <uri type="file">file://path/file</uri> + <docidentifier type="ISO" primary="true" language="en" script="Latn">ISO TC 211</docidentifier> + <docidentifier type="isbn">ISBN</docidentifier> + <docidentifier type="lccn">LCCN</docidentifier> + <docidentifier type="issn" scope="series">ISSN</docidentifier> + <docidentifier type="URN">urn:iso:std:iso:123:stage-90.93:ed-3:en,fr</docidentifier> + <docidentifier>XYZ</docidentifier> + <docidentifier type="DOI">10.17487/rfc1149</docidentifier> + <docidentifier type="Internet-Draft">draft-ietf-somewg-someprotocol-07</docidentifier> + <docnumber>TC211</docnumber> + <date type="issued" text=""> + <on>2014</on> + </date> + <date type="published" text=""> + <on>2014-04</on> + </date> + <date type="accessed" text=""> + <on>2015-05-20</on> + </date> + <contributor> + <role type="publisher"> + <description>Publisher role</description> + </role> + <organization> + <name type="Org name type" language="en" script="Latn" locale="en-US">International Organization for Standardization</name> + <subdivision type="Sub Div type"> + <name>Sub division name</name> + </subdivision> + <abbreviation>ISO</abbreviation> + <uri>www.iso.org</uri> + <logo> + <image id="logo1" src="logo1.png" mimetype="image/png" filename="logo1.png" width="200" height="100%" alt="Logo 1" title="Logo #1" longdesc="Logo number 1"/> + </logo> + </organization> + </contributor> + <contributor> + <role type="author"/> + <person> + <name> + <abbreviation>AB</abbreviation> + <completename language="en" script="Latn">A. Bierman</completename> + </name> + <credential>Credential</credential> + <affiliation> + <organization> + <name>IETF</name> + <abbreviation>IETF</abbreviation> + <identifier type="uri">www.ietf.org</identifier> + </organization> + </affiliation> + <address> + <street>Street</street> + <city>City</city> + <state>State</state> + <country>Country</country> + <postcode>123456</postcode> + </address> + <phone type="mobile">223322</phone> + <email>person@email.org</email> + <uri>www.person.com</uri> + </person> + </contributor> + <contributor> + <role type="publisher"> + <description>Publisher description</description> + </role> + <role type="editor"> + <description>Editor description</description> + </role> + <organization> + <name>Institute of Electrical and Electronics Engineers</name> + <abbreviation>IEEE</abbreviation> + <identifier type="uri">www.ieee.org</identifier> + <address> + <formattedAddress>Formatted address</formattedAddress> + </address> + </organization> + </contributor> + <contributor> + <role type="author"/> + <person> + <name> + <prefix>Prefix</prefix> + <forename>Arnold</forename> + <formatted-initials>A.</formatted-initials> + <surname>Bierman</surname> + <addition>Addition</addition> + </name> + <affiliation> + <name language="en" script="Latn">Name</name> + <description language="en">Description</description> + <organization> + <name>IETF</name> + <abbreviation>IETF</abbreviation> + </organization> + </affiliation> + <identifier type="uri">www.person.com</identifier> + <address> + <street>Street</street> + <city>City</city> + <state>State</state> + <country>Country</country> + <postcode>123456</postcode> + </address> + <phone type="work">223322</phone> + </person> + </contributor> + <contributor> + <role type="editor"/> + <person> + <name> + <forename language="en" script="Latn" initial="A">Arnold</forename> + <forename initial="B"/> + <formatted-initials language="en" script="Latn">A. B.</formatted-initials> + <surname language="en" script="Latn">Bierman</surname> + </name> + </person> + </contributor> + <contributor> + <role type="distributor"> + <description>sponsor</description> + </role> + <organization> + <name>World Wide Web Consortium</name> + <address> + <formattedAddress>Address string</formattedAddress> + </address> + </organization> + </contributor> + <edition number="1.2">Edition 1</edition> + <version> + <revision-date>2019-04-01</revision-date> + <draft>draft</draft> + </version> + <note>note</note> + <note type="annote">An note</note> + <note type="howpublished">How published</note> + <note type="comment">Comment</note> + <note type="tableOfContents">Table Of Contents</note> + <language>en</language> + <language>fr</language> + <locale>en-US</locale> + <script>Latn</script> + <abstract language="en" script="Latn"> + <p>ISO 19115-1:2014 defines the schema required for...</p> + </abstract> + <abstract language="fr" script="Latn">L'ISO 19115-1:2014 définit le schéma requis pour...</abstract> + <status> + <stage abbreviation="CD">30</stage> + <substage>substage</substage> + <iteration>final</iteration> + </status> + <copyright> + <from>2014</from> + <to>2020</to> + <owner> + <organization> + <name>International Organization for Standardization</name> + <abbreviation language="en">ISO</abbreviation> + <uri>www.iso.org</uri> + </organization> + </owner> + <scope>Scope</scope> + </copyright> + <relation type="updates"> + <bibitem> + <formattedref>ISO 19115:2003</formattedref> + </bibitem> + <locality type="section"> + <referenceFrom>Reference from</referenceFrom> + </locality> + <sourceLocalityStack> + <sourceLocality type="volume"> + <referenceFrom>2</referenceFrom> + </sourceLocality> + <sourceLocality type="chapter"> + <referenceFrom>3</referenceFrom> + </sourceLocality> + </sourceLocalityStack> + </relation> + <relation type="obsoletes"> + <description>supersedes</description> + <bibitem type="standard"> + <formattedref>ISO 19115:2003/Cor 1:2006</formattedref> + </bibitem> + <localityStack> + <locality type="chapter"> + <referenceFrom>1</referenceFrom> + </locality> + </localityStack> + <localityStack> + <locality type="page"> + <referenceFrom>2</referenceFrom> + </locality> + </localityStack> + <sourceLocality type="section"> + <referenceFrom>Reference from</referenceFrom> + <referenceTo>Reference to</referenceTo> + </sourceLocality> + </relation> + <relation type="partOf"> + <bibitem> + <title type="main" format="text/plain">Book title</title> + </bibitem> + </relation> + <series type="main"> + <formattedref>Series formatted ref</formattedref> + <title type="main">Series Title</title> + <place> + <city>New York</city> + <region iso="NY" recommended="true">New York</region> + <country iso="US" recommended="true">USA</country> + <formattedPlace>New York, NY, US</formattedPlace> + </place> + </series> + <series type="alt"> + <formattedref>ISO/IEC FDIS 10118-3</formattedref> + <title type="original" language="en" script="Latn" locale="en-US">ISO/IEC FDIS 10118-3</title> + <organization>Serie's organization</organization> + <abbreviation language="en" script="Latn" locale="en-US">ABVR</abbreviation> + <from>2009-02-01</from> + <to>2010-12-20</to> + <number>serie1234</number> + <partnumber>part5678</partnumber> + <run>2</run> + </series> + <medium> + <content>Medium content</content> + <genre>Medium Genre</genre> + <form>Medium form</form> + <carrier>Medium carrier</carrier> + <size>Medium size</size> + <scale>Medium scale</scale> + </medium> + <place> + <city>Geneva</city> + <region>Europe</region> + <country iso="CH" recommended="true">Switzeland</country> + <formattedPlace>Geneva, Switzeland</formattedPlace> + </place> + <price currency="USD">123</price> + <extent> + <localityStack> + <locality type="section"> + <referenceFrom>Reference from</referenceFrom> + <referenceTo>Reference to</referenceTo> + </locality> + <locality type="chapter"> + <referenceFrom>4</referenceFrom> + </locality> + </localityStack> + </extent> + <extent> + <localityStack> + <locality type="page"> + <referenceFrom>10</referenceFrom> + <referenceTo>20</referenceTo> + </locality> + <locality type="volume"> + <referenceFrom>1</referenceFrom> + </locality> + </localityStack> + </extent> + <size> + <value type="page">490</value> + <value type="plate">3</value> + </size> + <accesslocation>accesslocation1</accesslocation> + <accesslocation>accesslocation2</accesslocation> + <license>License</license> + <classification type="type">value</classification> + <classification type="keyword">Keywords</classification> + <classification type="mendeley">Mendeley Tags</classification> + <keyword> + <vocab language="en" script="Latn">Vocab 1</vocab> + <taxon language="en" script="Latn">Taxon 1</taxon> + <taxon language="fr" script="Latn">Taxon 2</taxon> + <vocabid type="vocab-id-type" uri="http://vovab"> + <code>444</code> + <term>VocabId Term</term> + </vocabid> + </keyword> + <validity> + <validityBegins>2010-10-10</validityBegins> + <validityEnds>2011-02-03</validityEnds> + <revision>2011-03-04</revision> + </validity> + <depiction scope="cover"> + <image src="cover1.png" mimetype="image/png" filename="cover1.png" width="200" height="100%" alt="Cover 1" title="Cover #1" longdesc="Cover number 1"/> + </depiction> +</bibitem> diff --git a/spec/examples/bibtex_article.xml b/spec/fixtures/bibtex_article.xml similarity index 100% rename from spec/examples/bibtex_article.xml rename to spec/fixtures/bibtex_article.xml diff --git a/spec/examples/bibtex_book.xml b/spec/fixtures/bibtex_book.xml similarity index 100% rename from spec/examples/bibtex_book.xml rename to spec/fixtures/bibtex_book.xml diff --git a/spec/examples/bibtex_inbook.xml b/spec/fixtures/bibtex_inbook.xml similarity index 100% rename from spec/examples/bibtex_inbook.xml rename to spec/fixtures/bibtex_inbook.xml diff --git a/spec/examples/bibtex_inproceedings.xml b/spec/fixtures/bibtex_inproceedings.xml similarity index 100% rename from spec/examples/bibtex_inproceedings.xml rename to spec/fixtures/bibtex_inproceedings.xml diff --git a/spec/examples/bibtex_phdthesis.xml b/spec/fixtures/bibtex_phdthesis.xml similarity index 100% rename from spec/examples/bibtex_phdthesis.xml rename to spec/fixtures/bibtex_phdthesis.xml diff --git a/spec/examples/bibtex_techreport.xml b/spec/fixtures/bibtex_techreport.xml similarity index 100% rename from spec/examples/bibtex_techreport.xml rename to spec/fixtures/bibtex_techreport.xml diff --git a/spec/examples/citeproc.json b/spec/fixtures/citeproc.json similarity index 100% rename from spec/examples/citeproc.json rename to spec/fixtures/citeproc.json diff --git a/spec/examples/from_bibtex.xml b/spec/fixtures/from_bibtex.xml similarity index 100% rename from spec/examples/from_bibtex.xml rename to spec/fixtures/from_bibtex.xml diff --git a/spec/examples/bib_item.xml b/spec/fixtures/from_old_yaml.xml similarity index 79% rename from spec/examples/bib_item.xml rename to spec/fixtures/from_old_yaml.xml index ac55493..d73d067 100644 --- a/spec/examples/bib_item.xml +++ b/spec/fixtures/from_old_yaml.xml @@ -1,14 +1,13 @@ -<bibitem id="ISOTC211" type="standard" schema-version="v1.2.9"> - <fetched>2024-12-11</fetched> - <title type="title-main" format="text/plain">Geographic information</title> - <title type="main" format="text/plain">Geographic information</title> - <title format="text/plain" language="fr" script="Latn">Information géographique</title> - <uri type="src" language="en" script="Latn">https://www.iso.org/standard/53798.html</uri> +<bibitem id="ISOTC211" type="standard" schema-version="v1.4.1"> + <fetched>2025-01-23</fetched> + <title>Geographic information</title> + <title language="fr" script="Latn">Information géographique</title> + <uri language="en" script="Latn" type="src">https://www.iso.org/standard/53798.html</uri> <uri type="obp">https://www.iso.org/obp/ui/#!iso:std:53798:en</uri> <uri type="rss">https://www.iso.org/contents/data/standard/05/37/53798.detail.rss</uri> <uri type="doi">http://standrd.org/doi-123</uri> <uri type="file">file://path/file</uri> - <docidentifier type="ISO" primary="true" language="en" script="Latn">ISO TC 211</docidentifier> + <docidentifier language="en" script="Latn" type="ISO" primary="true">ISO TC 211</docidentifier> <docidentifier type="isbn">ISBN</docidentifier> <docidentifier type="lccn">LCCN</docidentifier> <docidentifier type="issn" scope="series">ISSN</docidentifier> @@ -32,7 +31,9 @@ </role> <organization> <name>International Organization for Standardization</name> - <subdivision>division</subdivision> + <subdivision> + <name>division</name> + </subdivision> <abbreviation>ISO</abbreviation> <uri>www.iso.org</uri> <logo> @@ -62,7 +63,7 @@ <country>Country</country> <postcode>123456</postcode> </address> - <phone type="mobile">223322</phone> + <phone type="work">223322</phone> <email>person@email.org</email> <uri>www.person.com</uri> </person> @@ -84,7 +85,9 @@ </organization> </contributor> <contributor> - <role type="author"/> + <role type="author"> + <description>Author description</description> + </role> <person> <name> <prefix>Prefix</prefix> @@ -147,10 +150,10 @@ <language>en</language> <language>fr</language> <script>Latn</script> - <abstract format="text/html" language="en" script="Latn"> + <abstract language="en" script="Latn"> <p>ISO 19115-1:2014 defines the schema required for...</p> </abstract> - <abstract format="text/plain" language="fr" script="Latn">L'ISO 19115-1:2014 définit le schéma requis pour...</abstract> + <abstract language="fr" script="Latn">L'ISO 19115-1:2014 définit le schéma requis pour...</abstract> <status> <stage abbreviation="CD">30</stage> <substage>substage</substage> @@ -170,7 +173,7 @@ </copyright> <relation type="updates"> <bibitem> - <formattedref format="text/plain">ISO 19115:2003</formattedref> + <formattedref>ISO 19115:2003</formattedref> </bibitem> <locality type="section"> <referenceFrom>Reference from</referenceFrom> @@ -185,9 +188,9 @@ </sourceLocalityStack> </relation> <relation type="obsoletes"> - <description format="text/plain">supersedes</description> + <description>supersedes</description> <bibitem type="standard"> - <formattedref format="text/plain">ISO 19115:2003/Cor 1:2006</formattedref> + <formattedref>ISO 19115:2003/Cor 1:2006</formattedref> </bibitem> <localityStack> <locality type="chapter"> @@ -206,17 +209,19 @@ </relation> <relation type="partOf"> <bibitem> - <title type="main" format="text/plain">Book title</title> + <title type="main">Book title</title> </bibitem> </relation> <series type="Internet-Draft"> - <title format="text/plain">Internet-Draft</title> + <title>Internet-Draft</title> <number>draft-ietf-somewg-someprotocol-07</number> <run>seriesrun</run> </series> <series type="main"> - <title type="original" format="text/plain" language="en" script="Latn">ISO/IEC FDIS 10118-3</title> - <place>Serie's place</place> + <title language="en" script="Latn" type="original" format="text/plain">ISO/IEC FDIS 10118-3</title> + <place> + <formattedPlace>Serie's place</formattedPlace> + </place> <organization>Serie's organization</organization> <abbreviation>ABVR</abbreviation> <from>2009-02-01</from> @@ -225,21 +230,19 @@ <partnumber>part5678</partnumber> </series> <series type="alt"> - <formattedref format="text/plain" language="en" script="Latn">serieref</formattedref> - <title format="text/plain">Formattedref</title> + <formattedref>serieref</formattedref> + <title>Formattedref</title> </series> <series type="journal"> - <title format="text/plain">Journal</title> + <title>Journal</title> <number>7</number> </series> <series> - <title format="text/plain"> - <variant language="en" script="Latn">Series</variant> - <variant language="fr" script="Latn">Séries</variant> - </title> + <title language="en" script="Latn">Series</title> + <title language="fr" script="Latn">Séries</title> </series> <series> - <title format="text/plain">RFC</title> + <title>RFC</title> <number>4</number> </series> <medium> @@ -247,11 +250,13 @@ <size>medium size</size> <scale>medium scale</scale> </medium> - <place>bib place</place> + <place> + <formattedPlace>bib place</formattedPlace> + </place> <place> <city>Geneva</city> - <region>Region</region> - <country iso="CH" recommended="true">Switzelznd</country> + <region>Europe</region> + <country iso="CH" recommended="true">Switzeland</country> </place> <extent> <locality type="section"> @@ -283,11 +288,15 @@ <classification type="type">value</classification> <classification type="keyword">Keywords</classification> <classification type="mendeley">Mendeley Tags</classification> - <keyword>Keyword</keyword> - <keyword>Key Word</keyword> + <keyword> + <taxon>Keyword</taxon> + </keyword> + <keyword> + <taxon>Key Word</taxon> + </keyword> <validity> - <validityBegins>2010-10-10 12:21</validityBegins> - <validityEnds>2011-02-03 18:30</validityEnds> - <revision>2011-03-04 09:00</revision> + <validityBegins>2010-10-10</validityBegins> + <validityEnds>2011-02-03</validityEnds> + <revision>2011-03-04</revision> </validity> -</bibitem> \ No newline at end of file +</bibitem> diff --git a/spec/examples/hash.yml b/spec/fixtures/hash.yml similarity index 100% rename from spec/examples/hash.yml rename to spec/fixtures/hash.yml diff --git a/spec/examples/id_item.xml b/spec/fixtures/id_item.xml similarity index 100% rename from spec/examples/id_item.xml rename to spec/fixtures/id_item.xml diff --git a/spec/examples/id_item.yml b/spec/fixtures/id_item.yml similarity index 100% rename from spec/examples/id_item.yml rename to spec/fixtures/id_item.yml diff --git a/spec/examples/ieee_bibxml.xml b/spec/fixtures/ieee_bibxml.xml similarity index 100% rename from spec/examples/ieee_bibxml.xml rename to spec/fixtures/ieee_bibxml.xml diff --git a/spec/fixtures/item.yaml b/spec/fixtures/item.yaml new file mode 100644 index 0000000..475290b --- /dev/null +++ b/spec/fixtures/item.yaml @@ -0,0 +1,410 @@ +id: ISO1231994 +type: standard +schema_version: 1.0.0 +fetched: "2022-05-02" +formattedref: ISO 123:1994 +title: + - content: Geographic information -- Metadata + language: en + script: Latn + locale: en-US + - content: Information géographique -- Métadonnées + language: fr + script: Latn + locale: fr-FR +source: + - type: src + content: https://www.iso.org/standard/22722.html + - type: doi + content: 10.1007/978-3-319-99155-2_1 +docidentifier: + - type: ISO + content: ISO 123:1994 + language: en + script: Latn + locale: en-US + scope: global + primary: true + - type: DOI + content: 10.1007/978-3-319-99155-2_1 +docnumber: "123" +date: + - type: published + at: "1994-01-01" + - type: confirmed + from: "1994-02-01" + to: "1994-12-31" +contributor: + - role: + type: author + description: + - content: Role of the author + language: en + script: Latn + locale: en-US + person: + name: + abbreviation: + content: Prof. J. + language: en + script: Latn + locale: en-US + prefix: + - content: Prof. + language: en + script: Latn + locale: en-US + forename: + - initial: J + content: John + language: en + script: Latn + locale: en-US + formatted_initials: + content: J.D. + language: en + script: Latn + locale: en-US + surname: + content: Doe + language: en + script: Latn + locale: en-US + addition: + - content: PhD + language: en + script: Latn + locale: en-US + completename: + content: Prof. John Doe PhD + language: en + script: Latn + locale: en-US + note: + - type: legal + content: J.D. + language: en + script: Latn + locale: en-US + variant: + - type: pseudonym + completename: + content: John Q. Public + language: en + script: Latn + locale: en-US + credential: + - PhD + affiliation: + - name: + content: ISO + language: en + script: Latn + locale: en-US + description: + - content: Affiliation of the author + language: en + script: Latn + locale: en-US + organization: + name: + - type: primary + content: International Organization for Standardization + identifier: + - type: orcid + content: 0000-0002-1825-0097 + address: + - street: + - 1, rue de Varembé + city: Geneva + country: Switzerland + postcode: "1211" + formatted_address: 1, rue de Varembé,<br>Geneva, Switzerland, 1211 + phone: + - type: mobile + content: "+41 22 749 01 11" + email: + - jdoe@email.org + uri: + - type: primary + content: https://orcid.org/0000-0002-1825-0097 + - role: + type: publisher + description: + - content: Role of the publisher + organization: + name: + - type: primary + content: International Organization for Standardization + language: en + script: Latn + locale: en-US + subdivision: + - type: primary + name: + content: ISO/TC 211 + abbreviation: + content: ISO + identifier: + - type: ISNI + content: 0000 0001 2345 6789 + address: + - street: + - 1, rue de Varembé + city: Geneva + country: Switzerland + postcode: "1211" + formatted_address: 1, rue de Varembé,<br>Geneva, Switzerland, 1211 + phone: + - type: main + content: "+41 22 749 01 11" + email: + - office@iso.org + uri: + - type: primary + content: https://www.iso.org + language: en + script: Latn + locale: en-US + logo: + image: + id: 12345678-abcd-1234-abcd-1234567890ab + src: https://www.iso.org/files/live/sites/isoorg/files/store/en/PUB100080.jpg + mimetype: image/jpeg + filename: PUB100080.jpg + alt: ISO logo + title: ISO Logo + longdesc: https://www.iso.org/files/live/sites/isoorg/files/store/en/PUB100080.jpg + width: 100% + height: auto +edition: + number: "1" + content: First edition +version: + - revision_date: "1994-01-01" + draft: PD +note: + - type: errata + content: This is an errata + language: en + script: Latn + locale: en-US +language: + - en + - fr +locale: + - en-US + - fr-FR +script: + - Latn +abstract: + - content: This is an abstract. <em>This is emphasized</em> + language: en + script: Latn + locale: en-US +status: + stage: + abbreviation: IS + content: Published + substage: + abbreviation: FDIS + content: Final Draft International Standard + iteration: "3" +copyright: + - from: "1994" + to: "2000" + owner: + - organization: + name: + - content: ISO + - person: + name: + completename: + content: John Doe + scope: Book preface +relation: + - type: isPartOf + description: + content: Part of the ISO 123 serieso + language: en + script: Latn + locale: en-US + bibitem: + formattedref: ISO 123-1:1994 + docidentifier: + - type: ISO + content: ISO 123-1:1994 + locality: + - type: section + reference_from: "1" + reference_to: "10" + locality_stack: + - connective: and + locality: + - type: article + reference_from: "1" + - type: page + reference_from: "2" + reference_to: "5" + source_locality: + - type: chapter + reference_from: "4" + reference_to: "11" + source_locality_stack: + - connective: or + source_locality: + - type: article + reference_from: "2" + reference_to: "5" + source_locality: + - type: article + reference_from: "7" + reference_to: "9" +series: + - type: main + formattedref: ISO 123 + title: + - content: ISO 123 + place: + city: New York + region: + - iso: US-NY + recommended: true + content: New York + country: + - iso: US + recommended: true + content: United States + formatted_place: New York, United States + uri: + type: primary + content: https://www.iso.org/series/123 + organization: International Organization for Standardization + abbreviation: + content: ISO + from: "2000-01-01" + to: "2000-12-31" + number: "1" + partnumber: "1" + run: Run 1 +medium: + content: cri + genre: statical dataset + form: c + carrier: cr + size: 500 kB + scale: 1:10,000 +place: + - city: Geneva + region: + - iso: CH-GE + recommended: true + content: Geneva + country: + - iso: CH + recommended: true + content: Switzerland + formatted_place: Geneva, Switzerland + uri: + type: primary + content: https://www.iso.org/series/123 +price: + - currency: CHF + content: "123.45" + - currency: USD + content: "123.45" +extent: + - locality: + - type: page + reference_from: "1" + reference_to: "10" + - locality_stack: + - connective: and + locality: + - type: article + reference_from: "1" + - type: page + reference_from: "2" + reference_to: "5" +size: + value: + - type: page + content: "10" + - type: article + content: "5" +accesslocation: + - file/path +license: + - MIT +classification: + - type: ISO + content: "123" + language: en + script: Latn + locale: en-US + scope: local + primary: true +keyword: + - vocab: + - content: geographic + language: en + script: Latn + locale: en-US + taxon: + - content: information + language: en + script: Latn + locale: en-US + vocabid: + type: AGROVOC + uri: http://aims.fao.org/aos/agrovoc/ + code: "1234" + term: Test term +validity: + begins: "1994-01-01" + ends: "1994-12-31" + revision: "1994-12-31" +depiction: + scope: local + image: + - id: 12345678-abcd-1234-abcd-1234567890ab + src: https://www.iso.org/files/live/sites/isoorg/files/store/en/PUB100080.jpg + mimetype: image/jpeg + filename: PUB100080.jpg + alt: ISO logo + title: ISO Logo + longdesc: https://www.iso.org/files/live/sites/isoorg/files/store/en/PUB100080.jpg + width: 100% + height: auto +ext: + schema_version: 1.0.0 + doctype: + abbreviation: std + content: Standard + subdoctype: Technical Report + flavor: iso + editorialgroup: + technical_committee: + number: "211" + type: main + identifier: ISO/TC 211 + prefix: ISO + content: Geographic information + ics: + - code: "01.040.11" + text: ISO 123-1 + structuredidentifier: + - type: standard + agency: + - ISO + klass: technical report + docnumber: "123-1" + partnumber: "1" + edition: "2" + version: "3" + supplementtype: "A" + supplementnumber: "1" + amendment: "1" + corrigendum: "1" + language: "en" + year: "1994" diff --git a/spec/examples/manual.bib b/spec/fixtures/manual.bib similarity index 100% rename from spec/examples/manual.bib rename to spec/fixtures/manual.bib diff --git a/spec/examples/misc.bib b/spec/fixtures/misc.bib similarity index 100% rename from spec/examples/misc.bib rename to spec/fixtures/misc.bib diff --git a/spec/examples/phdthesis.bib b/spec/fixtures/phdthesis.bib similarity index 100% rename from spec/examples/phdthesis.bib rename to spec/fixtures/phdthesis.bib diff --git a/spec/examples/rfc.xml b/spec/fixtures/rfc.xml similarity index 88% rename from spec/examples/rfc.xml rename to spec/fixtures/rfc.xml index b893601..d471db8 100644 --- a/spec/examples/rfc.xml +++ b/spec/fixtures/rfc.xml @@ -3,6 +3,9 @@ <title>Geographic information</title> <author> <organization abbrev="ISO">International Organization for Standardization</organization> + <address> + <uri>www.iso.org</uri> + </address> </author> <author fullname="A. Bierman"> <organization abbrev="IETF">IETF</organization> @@ -21,6 +24,9 @@ </author> <author role="editor"> <organization abbrev="IEEE">IEEE</organization> + <address> + <postalLine>Formatted address</postalLine> + </address> </author> <author fullname="Arnold Bierman" initials="A." surname="Bierman"> <organization abbrev="IETF">IETF</organization> @@ -40,6 +46,9 @@ </author> <author> <organization>W3C</organization> + <address> + <postalLine>Address string</postalLine> + </address> </author> <date year="2014" month="April"/> <workgroup>Editorial group</workgroup> @@ -54,4 +63,4 @@ <seriesInfo name="Journal" value="7"/> <seriesInfo name="Series"/> <seriesInfo name="RFC" value="4"/> -</reference> \ No newline at end of file +</reference> diff --git a/spec/examples/techreport.bib b/spec/fixtures/techreport.bib similarity index 100% rename from spec/examples/techreport.bib rename to spec/fixtures/techreport.bib diff --git a/spec/relaton/bib/bibdata_spec.rb b/spec/relaton/bib/bibdata_spec.rb new file mode 100644 index 0000000..c092cbc --- /dev/null +++ b/spec/relaton/bib/bibdata_spec.rb @@ -0,0 +1,14 @@ +describe Relaton::Bib::Bibdata do + context "XML" do + let(:file) { "spec/fixtures/bibdata_item.xml" } + let(:input_xml) { File.read file, encoding: "UTF-8" } + let(:item) { described_class.from_xml input_xml } + + it "round trip" do + expect(described_class.to_xml(item)).to be_equivalent_to input_xml + schema = Jing.new "grammars/biblio-compile.rng" + errors = schema.validate file + expect(errors).to eq [] + end + end +end diff --git a/spec/relaton/bib/bibitem_spec.rb b/spec/relaton/bib/bibitem_spec.rb new file mode 100644 index 0000000..bcb2810 --- /dev/null +++ b/spec/relaton/bib/bibitem_spec.rb @@ -0,0 +1,14 @@ +describe Relaton::Bib::Bibitem do + context "XML" do + let(:file) { "spec/fixtures/bibitem.xml" } + let(:input_xml) { File.read(file, encoding: "UTF-8") } + let(:item) { described_class.from_xml input_xml } + + it "round trip" do + expect(described_class.to_xml(item)).to be_equivalent_to input_xml + schema = Jing.new "grammars/biblio-compile.rng" + errors = schema.validate file + expect(errors).to eq [] + end + end +end diff --git a/spec/relaton/bib/item_spec.rb b/spec/relaton/bib/item_spec.rb new file mode 100644 index 0000000..7803822 --- /dev/null +++ b/spec/relaton/bib/item_spec.rb @@ -0,0 +1,10 @@ +describe Relaton::Bib::Item do + let(:input_yaml) { File.read("spec/fixtures/item.yaml", encoding: "UTF-8") } + let(:item) { described_class.from_yaml input_yaml } + + it "round trip" do + input_hash = YAML.safe_load input_yaml + output_hash = YAML.safe_load described_class.to_yaml(item) + expect(output_hash).to eq input_hash + end +end diff --git a/spec/relaton_bib/util_spec.rb b/spec/relaton/bib/util_spec.rb similarity index 71% rename from spec/relaton_bib/util_spec.rb rename to spec/relaton/bib/util_spec.rb index a51f514..38df284 100644 --- a/spec/relaton_bib/util_spec.rb +++ b/spec/relaton/bib/util_spec.rb @@ -1,11 +1,11 @@ -describe RelatonBib::Util do +describe Relaton::Bib::Util do it "#respond_to_missing?" do expect(described_class.respond_to?(:warn)).to be true end it "#method_missing" do expect do - expect(described_class.warn("msg")).to be nil + expect(described_class.warn("msg")).to be_nil # true end.to output(/\[relaton-bib\] WARN: msg\n/).to_stderr_from_any_process end end diff --git a/spec/relaton/bib_spec.rb b/spec/relaton/bib_spec.rb new file mode 100644 index 0000000..e08c967 --- /dev/null +++ b/spec/relaton/bib_spec.rb @@ -0,0 +1,67 @@ +describe Relaton::Bib do + it "has a version number" do + expect(Relaton::Bib::VERSION).not_to be nil + end + + it "returns grammar hash" do + hash = Relaton::Bib.grammar_hash + expect(hash).to be_instance_of String + expect(hash.size).to eq 32 + end + + # context "parse date" do + # it "February 2012" do + # expect(Relaton.parse_date("February 2012")).to eq "2012-02" + # expect(Relaton.parse_date("February 2012", str: false)).to eq Date.new(2012, 2, 1) + # end + + # it "February 11, 2012" do + # expect(Relaton.parse_date("February 11, 2012")).to eq "2012-02-11" + # expect(Relaton.parse_date("February 11, 2012", str: false)).to eq Date.new(2012, 2, 11) + # end + + # it "2012-02-11" do + # expect(Relaton.parse_date("2012-02-11")).to eq "2012-02-11" + # expect(Relaton.parse_date("2012-02-11", str: false)).to eq Date.new(2012, 2, 11) + # end + + # it "2012-2-3" do + # expect(Relaton.parse_date("2012-2-3")).to eq "2012-02-03" + # expect(Relaton.parse_date("2012-2-3", str: false)).to eq Date.new(2012, 2, 3) + # end + + # it "2012-02" do + # expect(Relaton.parse_date("2012-02")).to eq "2012-02" + # expect(Relaton.parse_date("2012-02", str: false)).to eq Date.new(2012, 2, 1) + # end + + # it "2012-2" do + # expect(Relaton.parse_date("2012-2")).to eq "2012-02" + # expect(Relaton.parse_date("2012-2", str: false)).to eq Date.new(2012, 2, 1) + # end + + # it "invalid date" do + # expect do + # expect(Relaton.parse_date("2012-02-31")).to eq "2012-02-31" + # end.to output(/invalid date/).to_stderr_from_any_process + # end + # end + + # it "parse YAML with an old version of Psych" do + # method = double "params" + # expect(method).to receive(:parameters).and_return [%i[req yaml]] + # expect(YAML).to receive(:method).with(:safe_load).and_return method + # expect(YAML).to receive(:safe_load).with(kind_of(String), [], symbolize_names: false).and_return({}) + # Relaton.parse_yaml "key: value" + # end + + # it "parse YAML with a new version of Psych" do + # method = double "params" + # expect(method).to receive(:parameters).and_return [%i[req yaml permitted_classes]] + # expect(YAML).to receive(:method).with(:safe_load).and_return method + # expect(YAML).to receive(:safe_load) + # .with(kind_of(String), permitted_classes: [], symbolize_names: false) + # .and_return({}) + # Relaton.parse_yaml "key: value" + # end +end diff --git a/spec/relaton_bib/bibtex_parser_spec.rb b/spec/relaton/bibtex_parser_spec.rb similarity index 86% rename from spec/relaton_bib/bibtex_parser_spec.rb rename to spec/relaton/bibtex_parser_spec.rb index e8b8fdd..59c2e55 100644 --- a/spec/relaton_bib/bibtex_parser_spec.rb +++ b/spec/relaton/bibtex_parser_spec.rb @@ -1,6 +1,6 @@ -RSpec.describe RelatonBib::BibtexParser do - it "parse BibTex" do - items = RelatonBib::BibtexParser.from_bibtex <<~BIBTEX +describe "Relaton::BibtexParser" do + xit "parse BibTex" do + items = described_class.from_bibtex <<~BIBTEX @article{mrx05, type = "standard", auTHor = "Mr. X and Y, Mr.", @@ -66,7 +66,7 @@ } BIBTEX expect(items).to be_instance_of Hash - expect(items["mrx05"]).to be_instance_of RelatonBib::BibliographicItem + expect(items["mrx05"]).to be_instance_of Relaton::Bib::Item file = "spec/examples/from_bibtex.xml" xml = items["mrx05"].to_xml @@ -75,7 +75,7 @@ end context "parse title" do - it "with subtitle" do + xit "with subtitle" do bibtex = BibTeX.parse <<~BIBTEX @article{mrx05, title = {Something Great}, @@ -87,7 +87,7 @@ expect(title[1].title.content).to eq "Sub title" end - it "with double curly braces" do + xit "with double curly braces" do bibtex = BibTeX.parse <<~BIBTEX @article{mrx05, title = {{Something Great}}, @@ -99,34 +99,34 @@ end context "parse contributor" do - it "howpublished" do + xit "howpublished" do bibtex = BibTeX.parse <<~BIBTEX @article{mrx05, howpublished = "\\publisher{Taylor {\\&} Francis},\\url{http://www.tandfonline.com/doi/abs/10.1080/17538940802439549}" } BIBTEX contribs = described_class.send :fetch_contributor, bibtex["mrx05"] - expect(contribs[0][:entity]).to be_instance_of RelatonBib::Organization + expect(contribs[0][:entity]).to be_instance_of Relaton::Bib::Organization expect(contribs[0][:entity].name[0].content).to eq "Taylor & Francis" expect(contribs[0][:role][0][:type]).to eq "publisher" end end context "parse note" do - it "with howpublished as note" do + xit "with howpublished as note" do bibtex = BibTeX.parse <<~BIBTEX @article{mrx05, howpublished = {How Published Note}, } BIBTEX note = described_class.send :fetch_note, bibtex["mrx05"] - expect(note).to be_instance_of RelatonBib::BiblioNoteCollection - expect(note[0]).to be_instance_of RelatonBib::BiblioNote + expect(note).to be_instance_of Relaton::Bib::BiblioNoteCollection + expect(note[0]).to be_instance_of Relaton::Bib::BiblioNote expect(note[0].type).to eq "howpublished" expect(note[0].content).to eq "How Published Note" end - it "don't parse howpublished as note" do + xit "don't parse howpublished as note" do bibtex = <<~BIBTEX @article{mrx05, howpublished = "\\publisher{Taylor {\&} Francis},\\url{http://www.tandfonline.com/doi/abs/10.1080/17538940802439549}" @@ -134,13 +134,13 @@ BIBTEX docs = BibTeX.parse bibtex note = described_class.send :fetch_note, docs["mrx05"] - expect(note).to be_instance_of RelatonBib::BiblioNoteCollection + expect(note).to be_instance_of Relaton::Bib::BiblioNoteCollection expect(note).to be_empty end end context "parse keywords" do - it "with comma separator" do + xit "with comma separator" do bibtex = BibTeX.parse <<~BIBTEX @article{mrx05, keywords = {Sensor Web,data acquisition}, @@ -150,7 +150,7 @@ expect(keywords).to eq %w[Sensor\ Web data\ acquisition] end - it "with comma and space separator" do + xit "with comma and space separator" do bibtex = BibTeX.parse <<~BIBTEX @article{mrx05, keywords = {Sensor Web, data acquisition}, @@ -160,7 +160,7 @@ expect(keywords).to eq %w[Sensor\ Web data\ acquisition] end - it "empty" do + xit "empty" do bibtex = BibTeX.parse <<~BIBTEX @article{mrx05, } diff --git a/spec/relaton_bib/bibxml_parser_spec.rb b/spec/relaton/bibxml_parser_spec.rb similarity index 75% rename from spec/relaton_bib/bibxml_parser_spec.rb rename to spec/relaton/bibxml_parser_spec.rb index aa27783..bcdcc2b 100644 --- a/spec/relaton_bib/bibxml_parser_spec.rb +++ b/spec/relaton/bibxml_parser_spec.rb @@ -1,23 +1,23 @@ -RSpec.describe "BibXML parser" do - it "parse RFC" do +describe Relaton::BibXMLParser do + xit "parse RFC" do bibxml = File.read "spec/examples/rfc.xml", encoding: "UTF-8" - bib = RelatonBib::BibXMLParser.parse bibxml + bib = described_class.parse bibxml expect(bib.to_bibxml).to be_equivalent_to bibxml end - it "parse BCP" do + xit "parse BCP" do bibxml = File.read "spec/examples/bcp_item.xml", encoding: "UTF-8" - bib = RelatonBib::BibXMLParser.parse bibxml + bib = described_class.parse bibxml expect(bib.to_bibxml).to be_equivalent_to bibxml end - it "IEEE" do + xit "IEEE" do bibxml = File.read "spec/examples/ieee_bibxml.xml", encoding: "UTF-8" - bib = RelatonBib::BibXMLParser.parse bibxml + bib = described_class.parse bibxml expect(bib.to_bibxml).to be_equivalent_to bibxml end - it "returns contacts" do + xit "returns contacts" do doc = Nokogiri::XML <<~END_XML <reference anchor="RFC8341" target="https://www.rfc-editor.org/info/rfc8341"> <front> @@ -39,106 +39,106 @@ </reference> END_XML addr = doc.at "//reference/front/author[1]/address" - cont = RelatonBib::BibXMLParser.send(:contacts, addr) - expect(cont[0]).to be_instance_of RelatonBib::Address + cont = described_class.send(:contacts, addr) + expect(cont[0]).to be_instance_of Relaton::Bib::Address expect(cont[1].type).to eq "phone" expect(cont[2].type).to eq "email" expect(cont[3].type).to eq "uri" end - it "parse I-D doctype" do - doctype = RelatonBib::BibXMLParser.doctype("I-D") - expect(doctype).to be_instance_of RelatonBib::DocumentType + xit "parse I-D doctype" do + doctype = described_class.doctype("I-D") + expect(doctype).to be_instance_of Relaton::Bib::DocumentType expect(doctype.type).to eq "internet-draft" end context "parse PubID" do - it "Internet-Draft" do + xit "Internet-Draft" do doc = Nokogiri::XML <<~END_XML <reference anchor="I-D.3k1n-6tisch-alice0"> </reference> END_XML ref = doc.at "/reference" - id = RelatonBib::BibXMLParser.docids ref, nil + id = described_class.docids ref, nil expect(id).to be_a Array - expect(id.first).to be_a RelatonBib::DocumentIdentifier + expect(id.first).to be_a Relaton::Bib::Docidentifier expect(id.first.type).to eq "Internet-Draft" expect(id.first.id).to eq "draft-3k1n-6tisch-alice0" - expect(id[1]).to be_a RelatonBib::DocumentIdentifier + expect(id[1]).to be_a Relaton::Bib::Docidentifier expect(id[1].type).to eq "I-D" expect(id[1].id).to eq "I-D.3k1n-6tisch-alice0" expect(id[1].scope).to eq "anchor" end - it "Internet-Draft from seriesInfo" do + xit "Internet-Draft from seriesInfo" do doc = Nokogiri::XML <<~END_XML <reference> <seriesInfo name="Internet-Draft" value="draft-3k1n-6tisch-alice0-01"/> </reference> END_XML ref = doc.at "/reference" - id = RelatonBib::BibXMLParser.docids ref, nil + id = described_class.docids ref, nil expect(id).to be_a Array - expect(id.first).to be_a RelatonBib::DocumentIdentifier + expect(id.first).to be_a Relaton::Bib::Docidentifier expect(id.first.type).to eq "Internet-Draft" expect(id.first.id).to eq "draft-3k1n-6tisch-alice0-01" end - it "Internet-Draft from docName" do + xit "Internet-Draft from docName" do doc = Nokogiri::XML <<~END_XML <reference docName="draft-ietf-acvp-subsha-1.0"> </reference> END_XML ref = doc.at "/reference" - id = RelatonBib::BibXMLParser.docids ref, nil - expect(id[0]).to be_a RelatonBib::DocumentIdentifier + id = described_class.docids ref, nil + expect(id[0]).to be_a Relaton::Bib::Docidentifier expect(id[0].type).to eq "Internet-Draft" expect(id[0].id).to eq "draft-ietf-acvp-subsha-1.0" expect(id[1].scope).to eq "docName" end - it "add version" do + xit "add version" do doc = Nokogiri::XML <<~END_XML <reference anchor="I-D.3k1n-6tisch-alice0-01"> </reference> END_XML ref = doc.at "/reference" - id = RelatonBib::BibXMLParser.docids ref, "02" + id = described_class.docids ref, "02" expect(id).to be_a Array - expect(id.first).to be_a RelatonBib::DocumentIdentifier + expect(id.first).to be_a Relaton::Bib::Docidentifier expect(id.first.type).to eq "Internet-Draft" expect(id.first.id).to eq "draft-3k1n-6tisch-alice0-02" end end context "parse I-D format links" do - it "DOI" do + xit "DOI" do doc = Nokogiri::XML <<~END_XML <reference anchor="I-D-12.3"> <format type="DOC" target="https://www.rfc-editor.org/info/I-D-12.3.doc"/> </reference> END_XML ref = doc.at "/reference" - link = RelatonBib::BibXMLParser.link ref, nil, "1" + link = described_class.link ref, nil, "1" expect(link.size).to eq 1 expect(link[0][:type]).to eq "DOC" end - it "TXT" do + xit "TXT" do bibxml = <<~END_XML <reference anchor="I-D-12.3"> <format type="TXT" target="https://www.rfc-editor.org/info/rfc1.txt"/> </reference> END_XML - id = RelatonBib::BibXMLParser.parse bibxml + id = described_class.parse bibxml expect(id.link).to be_instance_of Array - expect(id.link[0]).to be_instance_of RelatonBib::TypedUri + expect(id.link[0]).to be_instance_of Relaton::Bib::Bsource expect(id.link[0].type).to eq "TXT" expect(id.link[0].content.to_s).to eq "https://www.rfc-editor.org/info/rfc1.txt" end end - it "parse RFC seriesinfo" do + xit "parse RFC seriesinfo" do bibxml = <<~END_XML <reference anchor="RFC0001" target="https://www.rfc-editor.org/info/rfc1"> <front> @@ -152,16 +152,16 @@ <seriesInfo name="DOI" value="10.17487/RFC0001"/> </reference> END_XML - rfc = RelatonBib::BibXMLParser.parse bibxml + rfc = described_class.parse bibxml expect(rfc.docidentifier[2].type).to eq "DOI" expect(rfc.docidentifier[2].id).to eq "10.17487/RFC0001" end - it "parse incomplete month name" do - expect(RelatonBib::BibXMLParser.month("Sept")).to eq "09" + xit "parse incomplete month name" do + expect(described_class.month("Sept")).to eq "09" end - it "skip empty organization" do + xit "skip empty organization" do bibxml = <<~END_XML <reference anchor="RFC0001" target="https://www.rfc-editor.org/info/rfc1"> <front> @@ -174,7 +174,7 @@ </front> </reference> END_XML - rfc = RelatonBib::BibXMLParser.parse bibxml + rfc = described_class.parse bibxml expect(rfc.contributor).to be_empty end @@ -187,8 +187,8 @@ # </front> # </reference> # END_XML - # rfc = RelatonBib::BibXMLParser.parse bibxml - # expect(rfc.contributor[0].entity).to be_instance_of RelatonBib::Organization + # rfc = described_class.parse bibxml + # expect(rfc.contributor[0].entity).to be_instance_of Relaton::Bib::Organization # expect(rfc.contributor[0].entity.name[0].content).to eq "IAB" # expect(rfc.contributor[0].role[0].type).to eq "author" # # expect(rfc.contributor[0].role[0].description[0].content).to eq "BibXML author" diff --git a/spec/relaton_bib/renderer/bibtex_builder_spec.rb b/spec/relaton/renderer/bibtex_builder_spec.rb similarity index 71% rename from spec/relaton_bib/renderer/bibtex_builder_spec.rb rename to spec/relaton/renderer/bibtex_builder_spec.rb index 69b93db..6c2db26 100644 --- a/spec/relaton_bib/renderer/bibtex_builder_spec.rb +++ b/spec/relaton/renderer/bibtex_builder_spec.rb @@ -1,9 +1,9 @@ -describe RelatonBib::Renderer::BibtexBuilder do +describe Relaton::Renderer::BibtexBuilder do context "instance methods" do - subject { RelatonBib::Renderer::BibtexBuilder.new bibitem } + subject { Relaton::Renderer::BibtexBuilder.new bibitem } context "add_link" do - let(:bibitem) { RelatonBib::BibliographicItem.new link: ["http://example.com"] } - it "ignore links without type" do + let(:bibitem) { Relaton::Bib::Item.new link: ["http://example.com"] } + xit "ignore links without type" do item = double "item" expect(item).not_to receive :doi= expect(item).not_to receive :url= @@ -14,8 +14,8 @@ end end - it "render article" do - bibitem = RelatonBib::XMLParser.from_xml File.read("spec/examples/bibtex_article.xml") + xit "render article" do + bibitem = Relaton::XMLParser.from_xml File.read("spec/examples/bibtex_article.xml") expect(bibitem.to_bibtex).to eq <<~"OUTPUT" @article{DOC123, title = {Miscellaneous}, @@ -29,8 +29,8 @@ OUTPUT end - it "render book, rpoceedings" do - bibitem = RelatonBib::XMLParser.from_xml File.read("spec/examples/bibtex_book.xml") + xit "render book, rpoceedings" do + bibitem = Relaton::XMLParser.from_xml File.read("spec/examples/bibtex_book.xml") expect(bibitem.to_bibtex).to eq <<~"OUTPUT" @book{DOC123, title = {Title}, @@ -46,8 +46,8 @@ OUTPUT end - it "render inbook, incollection" do - bibitem = RelatonBib::XMLParser.from_xml File.read("spec/examples/bibtex_inbook.xml") + xit "render inbook, incollection" do + bibitem = Relaton::XMLParser.from_xml File.read("spec/examples/bibtex_inbook.xml") expect(bibitem.to_bibtex).to eq <<~"OUTPUT" @inbook{DOC123, title = {Title}, @@ -66,8 +66,8 @@ OUTPUT end - it "render inproceedings" do - bibitem = RelatonBib::XMLParser.from_xml File.read("spec/examples/bibtex_inproceedings.xml") + xit "render inproceedings" do + bibitem = Relaton::XMLParser.from_xml File.read("spec/examples/bibtex_inproceedings.xml") expect(bibitem.to_bibtex).to eq <<~"OUTPUT" @inproceedings{DOC123, title = {Title}, @@ -84,8 +84,8 @@ OUTPUT end - it "render phdthesis" do - bibitem = RelatonBib::XMLParser.from_xml File.read("spec/examples/bibtex_phdthesis.xml") + xit "render phdthesis" do + bibitem = Relaton::XMLParser.from_xml File.read("spec/examples/bibtex_phdthesis.xml") expect(bibitem.to_bibtex).to eq <<~"OUTPUT" @phdthesis{DOC123, title = {Title}, @@ -97,8 +97,8 @@ OUTPUT end - it "render techreport" do - bibitem = RelatonBib::XMLParser.from_xml File.read("spec/examples/bibtex_techreport.xml") + xit "render techreport" do + bibitem = Relaton::XMLParser.from_xml File.read("spec/examples/bibtex_techreport.xml") expect(bibitem.to_bibtex).to eq <<~"OUTPUT" @techreport{DOC123, title = {Title}, diff --git a/spec/relaton/renderer/bibxml_spec.rb b/spec/relaton/renderer/bibxml_spec.rb new file mode 100644 index 0000000..283c67d --- /dev/null +++ b/spec/relaton/renderer/bibxml_spec.rb @@ -0,0 +1,28 @@ +describe Relaton::Renderer::BibXML do + context "instance methods" do + context "ref_attrs" do + xit "upcase anchor for IANA" do + docid = Relaton::Bib::Docidentifier.new id: "IANA dns-parameters", type: "IANA" + bib = Relaton::Bib::Item.new(docid: [docid]) + renderer = Relaton::Renderer::BibXML.new bib + ref_attrs = renderer.ref_attrs + expect(ref_attrs).to be_instance_of Hash + expect(ref_attrs[:anchor]).to eq "DNS-PARAMETERS" + end + end + + context "render_seriesinfo" do + xit "do not render trademark" do + docid = [ + Relaton::Bib::Docidentifier.new(id: "IEEE 123", type: "IEEE"), + Relaton::Bib::Docidentifier.new(id: "IEEE 123", type: "IEEE", scope: "trademark"), + ] + bib = Relaton::Bib::Item.new docid: docid + renderer = Relaton::Bib::Renderer::BibXML.new bib + builder = double "builder" + # expect(builder).to receive(:seriesInfo).with(name: "IEEE", value: "IEEE 123").once + renderer.render_seriesinfo builder + end + end + end +end diff --git a/spec/relaton_bib/bib_item_locality_spec.rb b/spec/relaton_bib/bib_item_locality_spec.rb deleted file mode 100644 index 94f3533..0000000 --- a/spec/relaton_bib/bib_item_locality_spec.rb +++ /dev/null @@ -1,7 +0,0 @@ -RSpec.describe RelatonBib::BibItemLocality do - it "warn if locality type is invalid" do - expect do - RelatonBib::BibItemLocality.new "type", "from" - end.to output(/Invalid locality type/).to_stderr_from_any_process - end -end diff --git a/spec/relaton_bib/bibliographic_date_spec.rb b/spec/relaton_bib/bibliographic_date_spec.rb deleted file mode 100644 index fa668c2..0000000 --- a/spec/relaton_bib/bibliographic_date_spec.rb +++ /dev/null @@ -1,125 +0,0 @@ -# forzen_string_literal: true - -require "relaton_bib/bibliographic_item" - -RSpec.describe RelatonBib::BibliographicDate do - context "date on given" do - subject do - RelatonBib::BibliographicDate.new(type: "published", on: "November 2014") - end - - it "parse 'November 2014' format date" do - expect(subject.on).to eq "2014-11" - end - - it "return full date if part isn't :year, :month, or :day" do - expect(subject.on(:hour)).to eq "2014-11" - end - - it "return Date" do - expect(subject.on(:date)).to be_instance_of Date - end - - it "returns xml string" do - xml = Nokogiri::XML::Builder.new(encoding: "UTF-8") do |builder| - subject.to_xml builder - end.doc.root.to_xml - expect(xml).to be_equivalent_to <<~XML - <date type="published"><on>2014-11</on></date> - XML - end - - it "returns xml string with full date" do - xml = Nokogiri::XML::Builder.new(encoding: "UTF-8") do |builder| - subject.to_xml builder, date_format: :full - end.doc.root.to_xml - expect(xml).to be_equivalent_to <<~XML - <date type="published"><on>2014-11-01</on></date> - XML - end - end - - context "parse date" do - subject { RelatonBib::BibliographicDate.new(type: "published", on: "2014") } - - it "yyyy-mm-dd" do - date = subject.send :parse_date, "2014-11-02" - expect(date).to be_instance_of Date - expect(date).to eq Date.new(2014, 11, 2) - end - - it "yyyy-m-d" do - expect(subject.send(:parse_date, "2014-2-3")).to eq Date.new(2014, 2, 3) - end - - it "yyyy-mm" do - expect(subject.send(:parse_date, "2014-11")).to eq Date.new(2014, 11, 1) - end - - it "yyyy-m" do - expect(subject.send(:parse_date, "2014-2")).to eq Date.new(2014, 2, 1) - end - - it "yyyy" do - expect(subject.send(:parse_date, "2014")).to eq Date.new(2014, 1, 1) - end - - it "not match any pattern" do - expect(subject.send(:parse_date, "November 2014")).to eq "November 2014" - end - end - - context "dates from and to given" do - subject do - RelatonBib::BibliographicDate.new( - type: "published", from: "2014-11", to: "2015-12", - ) - end - - it "returns xml string" do - xml = Nokogiri::XML::Builder.new(encoding: "UTF-8") do |builder| - subject.to_xml builder - end.doc.root.to_xml - expect(xml).to be_equivalent_to <<~XML - <date type="published"><from>2014-11</from><to>2015-12</to></date> - XML - end - - it "returns xml string with short date" do - xml = Nokogiri::XML::Builder.new(encoding: "UTF-8") do |builder| - subject.to_xml builder, date_format: :short - end.doc.root.to_xml - expect(xml).to be_equivalent_to <<~XML - <date type="published"><from>2014-11</from><to>2015-12</to></date> - XML - end - end - - it "handle full date" do - item = RelatonBib::BibliographicDate.new type: "published", on: "2014-11-22" - xml = Nokogiri::XML::Builder.new(encoding: "UTF-8") do |builder| - item.to_xml builder, date_format: :full - end.doc.root.to_xml - - expect(xml).to be_equivalent_to <<~XML - <date type="published"><on>2014-11-22</on></date> - XML - end - - it "handle year only" do - item = RelatonBib::BibliographicDate.new(type: "published", on: "2014") - xml = Nokogiri::XML::Builder.new(encoding: "UTF-8") do |builder| - item.to_xml builder, date_format: :full - end.doc.root.to_xml - - expect(xml).to be_equivalent_to <<~XML - <date type="published"><on>2014-01-01</on></date> - XML - end - - it "handle date not matched any patterns" do - item = RelatonBib::BibliographicDate.new type: "published", on: "Nov 2020" - expect(item.on(:year)).to eq 2020 - expect(item.on(:month)).to eq 11 - end -end diff --git a/spec/relaton_bib/bibliographic_item_spec.rb b/spec/relaton_bib/bibliographic_item_spec.rb deleted file mode 100644 index 6449bc0..0000000 --- a/spec/relaton_bib/bibliographic_item_spec.rb +++ /dev/null @@ -1,358 +0,0 @@ -# frozen_string_literal: true - -require "yaml" -require "jing" - -RSpec.describe "RelatonBib" => :BibliographicItem do - context "initialize" do - it "with keyword Hash" do - keyword = [{ content: "keyword", language: "en", script: "Latn" }] - bib = RelatonBib::BibliographicItem.new(formattedref: "ref", keyword: keyword) - expect(bib.keyword).to be_instance_of Array - expect(bib.keyword.first).to be_instance_of RelatonBib::LocalizedString - expect(bib.keyword.first.content).to eq "keyword" - expect(bib.keyword.first.language).to eq ["en"] - expect(bib.keyword.first.script).to eq ["Latn"] - end - end - - context "instance" do - subject do - hash = YAML.load_file "spec/examples/bib_item.yml" - RelatonBib::BibliographicItem.from_hash(hash) - end - - context "makeid" do - it "with docid" do - expect(subject.makeid(nil, false)).to eq "ISOTC211" - end - - it "with argument" do - docid = RelatonBib::DocumentIdentifier.new type: "ISO", id: "ISO 123 (E)" - expect(subject.makeid(docid, false)).to eq "ISO123E" - end - end - - it "has schema-version" do - expect(subject.schema).to match(/^v\d+\.\d+\.\d+$/) - end - - it "is instance of BibliographicItem" do - expect(subject).to be_instance_of RelatonBib::BibliographicItem - end - - it "get set fetched" do - expect(subject.fetched).to eq "2022-05-02" - subject.fetched = "2022-05-03" - expect(subject.fetched).to eq "2022-05-03" - end - - it "has array of titiles" do - expect(subject.title).to be_instance_of( - RelatonBib::TypedTitleStringCollection, - ) - expect(subject.title(lang: "fr")[0].title.content).to eq( - "Information g\u00E9ographique", - ) - end - - it "has urls" do - expect(subject.url).to eq "https://www.iso.org/standard/53798.html" - expect(subject.url(:rss)).to eq "https://www.iso.org/contents/data/"\ - "standard/05/37/53798.detail.rss" - end - it "returns shortref" do - expect(subject.shortref(subject.docidentifier.first)).to eq "ISOTC211:2014" - end - - it "returns abstract with en language" do - expect(subject.abstract(lang: "en")).to be_instance_of( - RelatonBib::FormattedString, - ) - end - - it "to most recent reference" do - item = subject.to_most_recent_reference - expect(item.relation[3].bibitem.structuredidentifier[0].year).to eq "2020" - expect(item.structuredidentifier[0].year).to be_nil - end - - it "to all parts" do - item = subject.to_all_parts - expect(item).to_not be subject - expect(item.all_parts).to be true - expect(item.relation.last.type).to eq "instanceOf" - expect(item.title.detect { |t| t.type == "title-part" }).to be_nil - expect(item.title.detect { |t| t.type == "main" }.title.content).to eq( - "Geographic information", - ) - expect(item.abstract).to be_empty - id_with_part = item.docidentifier.detect do |d| - d.type != "Internet-Draft" && d.id =~ /-\d/ - end - expect(id_with_part).to be_nil - expect(item.docidentifier.reject { |d| d.id =~ %r{(all parts)} }.size) - .to eq 1 - expect(item.docidentifier.detect { |d| d.id =~ /:[12]\d\d\d/ }).to be_nil - expect(item.structuredidentifier.detect { |d| !d.partnumber.nil? }) - .to be_nil - expect(item.structuredidentifier.detect { |d| d.docnumber =~ /-\d/ }) - .to be_nil - expect( - item.structuredidentifier.detect { |d| d.docnumber !~ %r{(all parts)} }, - ).to be_nil - expect( - item.structuredidentifier.detect { |d| d.docnumber =~ /:[12]\d\d\d/ }, - ).to be_nil - end - - context "render XML" do - it "returns bibitem xml string" do - file = "spec/examples/bib_item.xml" - subject_xml = subject.to_xml - .gsub(/(?<=<fetched>)\d{4}-\d{2}-\d{2}/, Date.today.to_s) - File.write file, subject_xml, encoding: "utf-8" unless File.exist? file - xml = File.read(file, encoding: "utf-8") - .gsub(/(?<=<fetched>)\d{4}-\d{2}-\d{2}/, Date.today.to_s) - expect(subject_xml).to be_equivalent_to xml - schema = Jing.new "grammars/biblio-compile.rng" - errors = schema.validate file - expect(errors).to eq [] - end - - it "returns bibdata xml string" do - file = "spec/examples/bibdata_item.xml" - subject_xml = subject.to_xml(bibdata: true) - .gsub(/(?<=<fetched>)\d{4}-\d{2}-\d{2}/, Date.today.to_s) - File.write file, subject_xml, encoding: "utf-8" unless File.exist? file - xml = File.read(file, encoding: "utf-8") - .gsub(/(?<=<fetched>)\d{4}-\d{2}-\d{2}/, Date.today.to_s) - expect(subject_xml).to be_equivalent_to xml - schema = Jing.new "grammars/biblio-compile.rng" - errors = schema.validate file - expect(errors).to eq [] - end - - it "render only French laguage tagged string" do - file = "spec/examples/bibdata_item_fr.xml" - xml = subject.to_xml(bibdata: true, lang: "fr") - .sub(/(?<=<fetched>)\d{4}-\d{2}-\d{2}/, Date.today.to_s) - File.write file, xml, encoding: "UTF-8" unless File.exist? file - expect(xml).to be_equivalent_to File.read(file, encoding: "UTF-8") - .sub(/(?<=<fetched>)\d{4}-\d{2}-\d{2}/, Date.today.to_s) - end - - it "render addition elements" do - xml = subject.to_xml { |b| b.element "test" } - expect(xml).to include "<element>test</element>" - end - - it "add note to xml" do - xml = subject.to_xml note: [{ text: "Note", type: "note" }] - expect(xml).to include "<note format=\"text/plain\" type=\"note\">" \ - "Note</note>" - end - - it "render ext schema-verson" do - expect(subject).to receive(:respond_to?).with(:ext_schema).and_return(true).twice - expect(subject).to receive(:ext_schema).and_return("v1.0.0").twice - expect(subject.to_xml(bibdata: true)).to include "<ext schema-version=\"v1.0.0\">" - end - end - - it "deals with hashes" do - file = "spec/examples/bib_item.yml" - h = RelatonBib::HashConverter.hash_to_bib(YAML.load_file(file)) - b = RelatonBib::BibliographicItem.new(**h) - expect(b.to_xml).to be_equivalent_to subject.to_xml - end - - context "converts item to hash" do - it do - hash = subject.to_hash - file = "spec/examples/hash.yml" - File.write file, hash.to_yaml unless File.exist? file - expect(hash).to eq YAML.load_file(file) - expect(hash["revdate"]).to eq "2019-04-01" - end - - it "with ext schema-version" do - expect(subject).to receive(:respond_to?).with(:ext_schema).and_return(true).twice - expect(subject).to receive(:ext_schema).and_return("v1.0.0").twice - hash = subject.to_hash - expect(hash["ext"]["schema-version"]).to eq "v1.0.0" - end - end - - context "converts to BibTex" do - it "standard" do - bibtex = subject.to_bibtex - .sub(/(?<=timestamp = {)\d{4}-\d{2}-\d{2}/, Date.today.to_s) - file = "spec/examples/misc.bib" - File.write(file, bibtex, encoding: "utf-8") unless File.exist? file - expect(bibtex).to eq File.read(file, encoding: "utf-8") - .sub(/(?<=timestamp = {)\d{4}-\d{2}-\d{2}/, Date.today.to_s) - end - - it "techreport" do - expect(subject).to receive(:type).and_return("techreport") - .at_least :once - bibtex = subject.to_bibtex - .sub(/(?<=timestamp = {)\d{4}-\d{2}-\d{2}/, Date.today.to_s) - file = "spec/examples/techreport.bib" - File.write(file, bibtex, encoding: "utf-8") unless File.exist? file - expect(bibtex).to eq File.read(file, encoding: "utf-8") - .sub(/(?<=timestamp = {)\d{4}-\d{2}-\d{2}/, Date.today.to_s) - end - - it "manual" do - expect(subject).to receive(:type).and_return("manual").at_least :once - bibtex = subject.to_bibtex - .sub(/(?<=timestamp = {)\d{4}-\d{2}-\d{2}/, Date.today.to_s) - file = "spec/examples/manual.bib" - File.write(file, bibtex, encoding: "utf-8") unless File.exist? file - expect(bibtex).to eq File.read(file, encoding: "utf-8") - .sub(/(?<=timestamp = {)\d{4}-\d{2}-\d{2}/, Date.today.to_s) - end - - it "phdthesis" do - expect(subject).to receive(:type).and_return("phdthesis").at_least :once - bibtex = subject.to_bibtex - file = "spec/examples/phdthesis.bib" - File.write(file, bibtex, encoding: "utf-8") unless File.exist? file - expect(bibtex).to eq File.read(file, encoding: "utf-8") - end - end - - it "convert item to AsciiBib" do - file = "spec/examples/asciibib.adoc" - bib = subject.to_asciibib - File.write file, bib, encoding: "UTF-8" unless File.exist? file - expect(bib).to eq File.read(file, encoding: "UTF-8") - end - - context "convert item to BibXML" do - it "RFC" do - file = "spec/examples/rfc.xml" - rfc = subject.to_bibxml - File.write file, rfc, encoding: "UTF-8" unless File.exist? file - expect(rfc).to be_equivalent_to File.read file, encoding: "UTF-8" - end - - it "BCP" do - hash = YAML.load_file "spec/examples/bcp_item.yml" - bcpbib = RelatonBib::BibliographicItem.from_hash(hash) - file = "spec/examples/bcp_item.xml" - bcpxml = bcpbib.to_bibxml - File.write file, bcpxml, encoding: "UTF-8" unless File.exist? file - expect(bcpxml).to be_equivalent_to File.read file, encoding: "UTF-8" - end - - it "ID" do - hash = YAML.load_file "spec/examples/id_item.yml" - id = RelatonBib::BibliographicItem.from_hash hash - file = "spec/examples/id_item.xml" - idxml = id.to_bibxml - File.write file, idxml, encoding: "UTF-8" unless File.exist? file - expect(idxml).to be_equivalent_to File.read file, encoding: "UTF-8" - end - - it "render keywords" do - docid = RelatonBib::DocumentIdentifier.new type: "IETF", id: "ID" - bibitem = RelatonBib::BibliographicItem.new keyword: ["kw"], docid: [docid] - expect(bibitem.to_bibxml(include_keywords: true)).to be_equivalent_to <<~XML - <reference anchor="ID"> - <front> - <keyword>kw</keyword> - </front> - </reference> - XML - end - - it "render person's forename" do - docid = RelatonBib::DocumentIdentifier.new type: "IETF", id: "ID" - sname = RelatonBib::LocalizedString.new "Cook" - fname = RelatonBib::Forename.new content: "James", initial: "J" - name = RelatonBib::FullName.new surname: sname, forename: [fname] - entity = RelatonBib::Person.new name: name - contrib = RelatonBib::ContributionInfo.new entity: entity - bibitem = RelatonBib::BibliographicItem.new docid: [docid], contributor: [contrib] - expect(bibitem.to_bibxml).to be_equivalent_to <<~XML - <reference anchor="ID"> - <front> - <author fullname="James Cook" initials="J." surname="Cook"> - <organization/> - </author> - </front> - </reference> - XML - end - - it "render organization as author name" do - docid = RelatonBib::DocumentIdentifier.new type: "IETF", id: "ID" - entity = RelatonBib::Organization.new name: "org" - role = [{ type: "author", description: ["BibXML author"] }] - contrib = RelatonBib::ContributionInfo.new entity: entity, role: role - bibitem = RelatonBib::BibliographicItem.new docid: [docid], contributor: [contrib] - expect(bibitem.to_bibxml).to be_equivalent_to <<~XML - <reference anchor="ID"> - <front> - <author> - <organization>org</organization> - </author> - </front> - </reference> - XML - end - end - - it "convert item to citeproc" do - file = "spec/examples/citeproc.json" - cp = subject.to_citeproc - File.write file, cp.to_json, encoding: "UTF-8" unless File.exist? file - json = JSON.parse(File.read(file, encoding: "UTF-8")) - json[0]["timestamp"] = Date.today.to_s - cp[0]["timestamp"] = Date.today.to_s - expect(cp).to eq json - end - end - - it "initialize with copyright object" do - org = RelatonBib::Organization.new( - name: "Test Org", abbreviation: "TO", url: "test.org", - ) - owner = [RelatonBib::ContributionInfo.new(entity: org)] - copyright = RelatonBib::CopyrightAssociation.new(owner: owner, from: "2018") - bibitem = RelatonBib::BibliographicItem.new( - formattedref: RelatonBib::FormattedRef.new(content: "ISO123"), - copyright: [copyright], - ) - expect(bibitem.to_xml).to include( - "<formattedref format=\"text/plain\">ISO123</formattedref>", - ) - end - - it "warn invalid type argument error" do - expect { RelatonBib::BibliographicItem.new type: "type" }.to output( - /\[relaton-bib\] WARN: Type `type` is invalid./, - ).to_stderr_from_any_process - end - - context RelatonBib::CopyrightAssociation do - it "initialise with owner object" do - org = RelatonBib::Organization.new( - name: "Test Org", abbreviation: "TO", url: "test.org", - ) - owner = [RelatonBib::ContributionInfo.new(entity: org)] - copy = RelatonBib::CopyrightAssociation.new owner: owner, from: "2019" - expect(copy.owner).to eq owner - end - end - - it "initialize with string link" do - bibitem = RelatonBib::BibliographicItem.new link: ["http://example.com"] - expect(bibitem.link[0]).to be_instance_of RelatonBib::TypedUri - expect(bibitem.link[0].content).to be_instance_of Addressable::URI - expect(bibitem.link[0].content.to_s).to eq "http://example.com" - end -end diff --git a/spec/relaton_bib/contribution_info_spec.rb b/spec/relaton_bib/contribution_info_spec.rb deleted file mode 100644 index 88a8594..0000000 --- a/spec/relaton_bib/contribution_info_spec.rb +++ /dev/null @@ -1,7 +0,0 @@ -RSpec.describe RelatonBib::ContributorRole do - it "raises invalid type argument error" do - expect { RelatonBib::ContributorRole.new type: "type" }.to output( - /Contributor's type `type` is invalid/, - ).to_stderr_from_any_process - end -end diff --git a/spec/relaton_bib/contributor_spec.rb b/spec/relaton_bib/contributor_spec.rb deleted file mode 100644 index d4237aa..0000000 --- a/spec/relaton_bib/contributor_spec.rb +++ /dev/null @@ -1,228 +0,0 @@ -describe RelatonBib::Address do - it "raises ArgumentError if either formatted address or city and country are not provided" do - expect { RelatonBib::Address.new }.to raise_error(ArgumentError) - end - - context "==" do - it "same content" do - contrib = RelatonBib::Address.new(formatted_address: "formatted address") - other = RelatonBib::Address.new(formatted_address: "formatted address") - expect(contrib).to eq other - end - - it "different content" do - contrib = RelatonBib::Address.new(formatted_address: "formatted address") - other = RelatonBib::Address.new(formatted_address: "other formatted address") - expect(contrib).not_to eq other - end - end - - context "render formatted address" do - let(:contrib) { RelatonBib::Address.new(formatted_address: "formatted address") } - - it "as XML" do - xml = Nokogiri::XML::Builder.new { |b| contrib.to_xml(b) }.doc.root - formatted_address = xml.xpath("/address/formattedAddress").text - expect(formatted_address).to eq "formatted address" - end - - it "as Hash" do - hash = contrib.to_hash - expect(hash["address"]["formatted_address"]).to eq "formatted address" - end - - it "as AsciiBib" do - expect(contrib.to_asciibib).to eq "address.formatted_address:: formatted address\n" - end - end - - context "render address" do - let(:contrib) do - RelatonBib::Address.new( - street: ["street1", "street2"], - city: "city", - state: "state", - country: "country", - postcode: "postcode", - ) - end - - it "as XML" do - xml = Nokogiri::XML::Builder.new { |b| contrib.to_xml(b) }.doc.root - street = xml.xpath("/address/street").map(&:text) - expect(street).to eq %w[street1 street2] - expect(xml.xpath("/address/city").text).to eq "city" - expect(xml.xpath("/address/state").text).to eq "state" - expect(xml.xpath("/address/country").text).to eq "country" - expect(xml.xpath("/address/postcode").text).to eq "postcode" - end - - it "as Hash" do - hash = contrib.to_hash - expect(hash["address"]["street"]).to eq %w[street1 street2] - expect(hash["address"]["city"]).to eq "city" - expect(hash["address"]["state"]).to eq "state" - expect(hash["address"]["country"]).to eq "country" - expect(hash["address"]["postcode"]).to eq "postcode" - end - - it "as AsciiBib" do - expect(contrib.to_asciibib).to eq <<~ASCIIBIB - address.street:: street1 - address.street:: street2 - address.city:: city - address.state:: state - address.country:: country - address.postcode:: postcode - ASCIIBIB - end - end -end - -describe RelatonBib::Affiliation do - let(:org) { RelatonBib::Organization.new(name: "Org") } - let(:name) { RelatonBib::LocalizedString.new("Name", "en") } - let(:desc) { RelatonBib::FormattedString.new(content: "Description", language: "en") } - subject do - description = desc ? [desc] : [] - described_class.new(organization: org, name: name, description: description) - end - - context "==" do - it "same content" do - other = described_class.new(organization: org, name: name, description: [desc]) - expect(subject).to eq other - end - - it "different content" do - name = RelatonBib::LocalizedString.new("Other", "en") - other = described_class.new(organization: org, name: name, description: [desc]) - expect(subject).not_to eq other - end - end - - context "render affiliation" do - context "with all fields" do - it "as XML" do - xml = Nokogiri::XML::Builder.new { |b| subject.to_xml(builder: b) }.doc.root - expect(xml.to_s).to be_equivalent_to <<~XML - <affiliation> - <name language="en">Name</name> - <description format="text/plain" language="en">Description</description> - <organization> - <name>Org</name> - </organization> - </affiliation> - XML - end - - it "as Hash" do - hash = subject.to_hash - expect(hash["organization"]["name"][0]["content"]).to eq "Org" - expect(hash["name"]["content"]).to eq "Name" - expect(hash["name"]["language"]).to eq ["en"] - expect(hash["description"][0]["content"]).to eq "Description" - expect(hash["description"][0]["language"]).to eq ["en"] - end - - it "as AsciiBib" do - expect(subject.to_asciibib).to eq <<~ASCIIBIB - affiliation.name.content:: Name - affiliation.name.language:: en - affiliation.description.content:: Description - affiliation.description.language:: en - affiliation.description.format:: text/plain - affiliation.organization.name:: Org - ASCIIBIB - end - end - - context "without organization" do - let(:org) { nil } - - it "as XML" do - xml = Nokogiri::XML::Builder.new { |b| subject.to_xml(builder: b) }.doc.root - expect(xml.to_s).to be_equivalent_to <<~XML - <affiliation> - <name language="en">Name</name> - <description format="text/plain" language="en">Description</description> - </affiliation> - XML - end - - it "as Hash" do - hash = subject.to_hash - expect(hash).not_to have_key "organization" - end - - it "as AsciiBib" do - expect(subject.to_asciibib).not_to include "affiliation.organization" - end - end - - context "without name" do - let(:name) { nil } - - it "as XML" do - xml = Nokogiri::XML::Builder.new { |b| subject.to_xml(builder: b) }.doc.root - expect(xml.to_s).to be_equivalent_to <<~XML - <affiliation> - <description format="text/plain" language="en">Description</description> - <organization> - <name>Org</name> - </organization> - </affiliation> - XML - end - - it "as Hash" do - hash = subject.to_hash - expect(hash).not_to have_key "name" - end - - it "as AsciiBib" do - expect(subject.to_asciibib).not_to include "affiliation.name" - end - end - - context "without description" do - let(:desc) { nil } - - it "as XML" do - xml = Nokogiri::XML::Builder.new { |b| subject.to_xml(builder: b) }.doc.root - expect(xml.to_s).to be_equivalent_to <<~XML - <affiliation> - <name language="en">Name</name> - <organization> - <name>Org</name> - </organization> - </affiliation> - XML - end - - it "as Hash" do - expect(subject.to_hash).not_to have_key "description" - end - - it "as AsciiBib" do - expect(subject.to_asciibib).not_to include "affiliation.description" - end - end - - it "without any fields" do - xml = Nokogiri::XML::Builder.new { |b| described_class.new.to_xml(builder: b) }.doc.root - expect(xml.to_s).to eq "" - end - end - - context "desctiption" do - it "returns all descriptions if language is not specified" do - expect(subject.description).to eq [desc] - end - - it "returns description with specified language" do - expect(subject.description("en")).to eq [desc] - expect(subject.description("fr")).to be_empty - end - end -end diff --git a/spec/relaton_bib/copyright_association_spec.rb b/spec/relaton_bib/copyright_association_spec.rb deleted file mode 100644 index 2f1acac..0000000 --- a/spec/relaton_bib/copyright_association_spec.rb +++ /dev/null @@ -1,7 +0,0 @@ -RSpec.describe RelatonBib::CopyrightAssociation do - it "raise error if owners is empty" do - expect do - RelatonBib::CopyrightAssociation.new owner: [], from: "2019" - end.to raise_error ArgumentError - end -end diff --git a/spec/relaton_bib/document_identifier_spec.rb b/spec/relaton_bib/document_identifier_spec.rb deleted file mode 100644 index c0a30a9..0000000 --- a/spec/relaton_bib/document_identifier_spec.rb +++ /dev/null @@ -1,84 +0,0 @@ -RSpec.describe RelatonBib::DocumentIdentifier do - context "ISO" do - subject do - RelatonBib::DocumentIdentifier.new(id: "1111-2:2014", type: "ISO") - end - - it "remove part" do - subject.remove_part - expect(subject.id).to eq "1111:2014" - subject.all_parts - expect(subject.id).to eq "1111:2014 (all parts)" - end - - it "remove date" do - subject.remove_date - expect(subject.id).to eq "1111-2" - end - end - - context "URN" do - context "ISO" do - subject do - RelatonBib::DocumentIdentifier.new( - type: "URN", id: "urn:iso:std:iso:1111:-1:stage-60.60:ed-1:v1:en,fr", - ) - end - - it "remove part" do - subject.remove_part - expect(subject.id).to eq "urn:iso:std:iso:1111" - end - end - - context "IEC" do - subject do - RelatonBib::DocumentIdentifier.new( - type: "URN", - id: "urn:iec:std:iec:61058-2-4:1995::csv:en:plus:amd:1:2003", - ) - end - - it "remove part" do - subject.remove_part - expect(subject.id).to eq "urn:iec:std:iec:61058:1995::csv:en:plus:amd:1:2003" - end - - it "remove date" do - subject.remove_date - expect(subject.id).to eq "urn:iec:std:iec:61058-2-4:::csv:en:plus:amd:1:2003" - end - - it "set all parts" do - subject.all_parts - expect(subject.id).to eq "urn:iec:std:iec:61058-2-4:1995::ser" - end - end - end - - context "GB" do - subject do - RelatonBib::DocumentIdentifier.new(id: "1111.2-2014", type: "Chinese Standard") - end - - it "remove part" do - subject.remove_part - expect(subject.id).to eq "1111-2014" - end - - it "remove date" do - subject.remove_date - expect(subject.id).to eq "1111.2" - end - end - - context "#to_xml" do - it "with superscription" do - subject = RelatonBib::DocumentIdentifier.new(id: "CIPM 43<sup>e</sup> réunion (1950)", type: "BIPM") - xml = Nokogiri::XML::Builder.new do |builder| - subject.to_xml(builder: builder, lang: "en") - end.doc.root - expect(xml.to_xml).to eq "<docidentifier type=\"BIPM\">CIPM 43<sup>e</sup> réunion (1950)</docidentifier>" - end - end -end diff --git a/spec/relaton_bib/document_relation_collection_spec.rb b/spec/relaton_bib/document_relation_collection_spec.rb deleted file mode 100644 index f401294..0000000 --- a/spec/relaton_bib/document_relation_collection_spec.rb +++ /dev/null @@ -1,27 +0,0 @@ -RSpec.describe RelatonBib::DocRelationCollection do - context "instance" do - subject do - RelatonBib::DocRelationCollection.new( - [ - RelatonBib::DocumentRelation.new( - type: "replace", - bibitem: RelatonBib::BibliographicItem.new( - formattedref: RelatonBib::FormattedRef.new(content: "realtion1"), - ), - ), - RelatonBib::DocumentRelation.new( - type: "obsoletes", bibitem: "realtion1", - ), - ], - ) - end - - it "returns one replace" do - expect(subject.replaces.size).to eq 1 - end - - it "#select" do - expect(subject.select { |r| r.type == "replace" }.size).to eq 1 - end - end -end diff --git a/spec/relaton_bib/document_relation_spec.rb b/spec/relaton_bib/document_relation_spec.rb deleted file mode 100644 index d60da8f..0000000 --- a/spec/relaton_bib/document_relation_spec.rb +++ /dev/null @@ -1,7 +0,0 @@ -RSpec.describe RelatonBib::DocumentRelation do - it "warn when type is invalid" do - expect do - RelatonBib::DocumentRelation.new type: "invalid", bibitem: nil - end.to output(/Invalid relation type/).to_stderr_from_any_process - end -end diff --git a/spec/relaton_bib/document_status_spec.rb b/spec/relaton_bib/document_status_spec.rb deleted file mode 100644 index d8c69ff..0000000 --- a/spec/relaton_bib/document_status_spec.rb +++ /dev/null @@ -1,14 +0,0 @@ -RSpec.describe RelatonBib::DocumentStatus do - it "create with hash" do - ds = RelatonBib::DocumentStatus.new stage: { value: "30", abbreviation: "CD" } - expect(ds.stage).to be_instance_of RelatonBib::DocumentStatus::Stage - expect(ds.stage.value).to eq "30" - expect(ds.stage.abbreviation).to eq "CD" - end - - it "create with string" do - ds = RelatonBib::DocumentStatus.new stage: "30-CD" - expect(ds.stage).to be_instance_of RelatonBib::DocumentStatus::Stage - expect(ds.stage.value).to eq "30-CD" - end -end diff --git a/spec/relaton_bib/forename_spec.rb b/spec/relaton_bib/forename_spec.rb deleted file mode 100644 index 28463d1..0000000 --- a/spec/relaton_bib/forename_spec.rb +++ /dev/null @@ -1,53 +0,0 @@ -describe RelatonBib::Forename do - subject do - described_class.new content: "John", language: "en", script: "Latn", initial: "J" - end - - it "initialize" do - expect(subject.content).to eq "John" - expect(subject.language).to eq ["en"] - expect(subject.script).to eq ["Latn"] - expect(subject.initial).to eq "J" - end - - context "instance methods" do - it "#to_xml" do - doc = Nokogiri::XML::Builder.new do |builder| - builder.name { subject.to_xml builder } - end.doc.root - expect(doc.to_xml).to be_equivalent_to <<-XML - <name> - <forename language="en" script="Latn" initial="J">John</forename> - </name> - XML - end - - it "#to_hash" do - expect(subject.to_hash).to eq( - { "content" => "John", "language" => ["en"], "script" => ["Latn"], - "initial" => "J" }, - ) - end - - context "#to_asciibib" do - it "single forename" do - expect(subject.to_asciibib("name", 1)).to eq <<~ASCIIDOC - name.forename.content:: John - name.forename.language:: en - name.forename.script:: Latn - name.forename.initial:: J - ASCIIDOC - end - - it "multiple forenames" do - expect(subject.to_asciibib("name", 2)).to eq <<~ASCIIDOC - name.forename:: - name.forename.content:: John - name.forename.language:: en - name.forename.script:: Latn - name.forename.initial:: J - ASCIIDOC - end - end - end -end diff --git a/spec/relaton_bib/formatted_string_spec.rb b/spec/relaton_bib/formatted_string_spec.rb deleted file mode 100644 index 93aeb24..0000000 --- a/spec/relaton_bib/formatted_string_spec.rb +++ /dev/null @@ -1,118 +0,0 @@ -describe RelatonBib::FormattedString do - context "instance" do - subject do - RelatonBib::FormattedString.new(content: <<-XML, language: "en", script: "Latn", format: "text/html") - prefix <p>content <p>< & > characters</p> to escape</p> - <p>Text \xC2\xB1 10-4 K</p> suffix - XML - end - - context "==" do - it "same content" do - other = RelatonBib::FormattedString.new content: subject.content, language: "en", script: "Latn", format: "text/html" - expect(subject).to eq other - end - - it "different content" do - other = RelatonBib::FormattedString.new content: "other", language: "en", script: "Latn", format: "text/html" - expect(subject).not_to eq other - end - end - - context "escape" do - it "&" do - xml = Nokogiri::XML::Builder.new do |b| - b.formatted_string { subject.to_xml(b) } - end - expect(xml.doc.root.to_s).to be_equivalent_to <<~XML - <formatted_string format="text/html" language="en" script="Latn"> - prefix<p>content<p>< & > characters</p>to escape</p><p>Text ± 10-4 K</p> suffix - </formatted_string> - XML - end - - it "incorrect HTML" do - ls = RelatonBib::FormattedString.new content: <<~XML, language: "en", script: "Latn", format: "text/html" - <p><p>Content</tt></p> - XML - xml = Nokogiri::XML::Builder.new do |b| - b.formatted_string { ls.to_xml(b) } - end - expect(xml.doc.root.to_s).to be_equivalent_to <<~XML - <formatted_string format="text/html" language="en" script="Latn"> - <p><p>Content</tt></p> - </formatted_string> - XML - end - - it "content with 2 root elements" do - ls = RelatonBib::FormattedString.new content: <<~XML, format: "text/html" - <p>Content &</p><p>Content</p> - XML - xml = Nokogiri::XML::Builder.new do |b| - b.formatted_string { ls.to_xml(b) } - end - expect(xml.doc.root.to_s).to be_equivalent_to <<~XML - <formatted_string format="text/html"> - <p>Content &</p><p>Content</p> - </formatted_string> - XML - end - - it "tag with attributes" do - ls = RelatonBib::FormattedString.new content: <<~XML, format: "text/html" - <p>Content <p id="1">Content</p></p> - XML - xml = Nokogiri::XML::Builder.new do |b| - b.formatted_string { ls.to_xml(b) } - end - expect(xml.doc.root.to_s).to be_equivalent_to <<~XML - <formatted_string format="text/html"> - <p>Content <p id="1">Content</p></p> - </formatted_string> - XML - end - - it "tag without content" do - ls = RelatonBib::FormattedString.new content: <<~XML, format: "text/html" - <br/><br /> - XML - xml = Nokogiri::XML::Builder.new do |b| - b.formatted_string { ls.to_xml(b) } - end - expect(xml.doc.root.to_s).to be_equivalent_to <<~XML - <formatted_string format="text/html"> - <br/><br/> - </formatted_string> - XML - end - - it "HTML comment" do - ls = RelatonBib::FormattedString.new content: <<~XML, format: "text/html" - <p>Content <!-- comment --> Content</p> - XML - xml = Nokogiri::XML::Builder.new do |b| - b.formatted_string { ls.to_xml(b) } - end - expect(xml.doc.root.to_s).to be_equivalent_to <<~XML - <formatted_string format="text/html"> - <p>Content <!-- comment --> Content</p> - </formatted_string> - XML - end - end - - it "cleanup" do - fs = described_class.new content: <<~XML, format: "text/html" - <i>Italic</i> <b>Bold</b> <u>Underline</u> <sup>Superscript</sup> <sub>Subscript</sub><br/> - <jats:p>Paragraph</jats:p><tt>Monospace</tt><a href="http://example.com">Link</a> - <italic>Italic</italic>. - XML - expect(fs.content).to be_equivalent_to <<~XML - <em>Italic</em> <strong>Bold</strong> Underline <sup>Superscript</sup> <sub>Subscript</sub><br/> - <p>Paragraph</p><tt>Monospace</tt>Link - Italic. - XML - end - end -end diff --git a/spec/relaton_bib/full_name_spec.rb b/spec/relaton_bib/full_name_spec.rb deleted file mode 100644 index 9116b6b..0000000 --- a/spec/relaton_bib/full_name_spec.rb +++ /dev/null @@ -1,131 +0,0 @@ -describe RelatonBib::FullName do - context "using name parts" do - subject do - described_class.new( - surname: RelatonBib::LocalizedString.new("Doe"), - abbreviation: RelatonBib::LocalizedString.new("DJ"), - forename: [RelatonBib::Forename.new(content: "John", initial: "J")], - initials: RelatonBib::LocalizedString.new("J.D."), - addition: [RelatonBib::LocalizedString.new("Jr.")], - prefix: [RelatonBib::LocalizedString.new("Dr.")], - ) - end - - context "==" do - it "same content" do - other = described_class.new( - surname: RelatonBib::LocalizedString.new("Doe"), - abbreviation: RelatonBib::LocalizedString.new("DJ"), - forename: [RelatonBib::Forename.new(content: "John", initial: "J")], - initials: RelatonBib::LocalizedString.new("J.D."), - addition: [RelatonBib::LocalizedString.new("Jr.")], - prefix: [RelatonBib::LocalizedString.new("Dr.")], - ) - expect(subject).to eq other - end - - it "different content" do - other = described_class.new( - surname: RelatonBib::LocalizedString.new("Doe"), - abbreviation: RelatonBib::LocalizedString.new("DJ"), - forename: [RelatonBib::Forename.new(content: "John", initial: "J")], - initials: RelatonBib::LocalizedString.new("J.D."), - prefix: [RelatonBib::LocalizedString.new("Dr.")], - ) - expect(subject).not_to eq other - end - end - - it "to_xml" do - builder = Nokogiri::XML::Builder.new - subject.to_xml(builder: builder) - expect(builder.to_xml).to be_equivalent_to <<~XML - <name> - <abbreviation>DJ</abbreviation> - <prefix>Dr.</prefix> - <forename initial="J">John</forename> - <formatted-initials>J.D.</formatted-initials> - <surname>Doe</surname> - <addition>Jr.</addition> - </name> - XML - end - - it "to_hash" do - expect(subject.to_hash).to eq( - "abbreviation" => { "content" => "DJ" }, - "given" => { - "forename" => [{ "content" => "John", "initial" => "J" }], - "formatted_initials" => { "content" => "J.D." }, - }, - "surname" => { "content" => "Doe" }, - "addition" => [{ "content" => "Jr." }], - "prefix" => [{ "content" => "Dr." }], - ) - end - - it "to_asciibib" do - expect(subject.to_asciibib("name")).to eq <<~ASCIIBIB - name.name.abbreviation:: DJ - name.given.forename:: John - name.given.forename.initial:: J - name.given.formatted-initials:: J.D. - name.name.surname:: Doe - name.name.addition:: Jr. - name.name.prefix:: Dr. - ASCIIBIB - end - end - - context "using completename" do - subject do - described_class.new( - completename: RelatonBib::LocalizedString.new("John Doe"), - ) - end - - context "==" do - it "same content" do - other = described_class.new( - completename: RelatonBib::LocalizedString.new("John Doe"), - ) - expect(subject).to eq other - end - - it "different content" do - other = described_class.new( - completename: RelatonBib::LocalizedString.new("Jane Doe"), - ) - expect(subject).not_to eq other - end - end - - it "to_xml" do - builder = Nokogiri::XML::Builder.new - subject.to_xml(builder: builder, lang: "en") - expect(builder.to_xml).to be_equivalent_to <<~XML - <name> - <completename>John Doe</completename> - </name> - XML - end - - it "to_hash" do - expect(subject.to_hash).to eq( - "completename" => { "content" => "John Doe" }, - ) - end - - it "to_asciibib" do - expect(subject.to_asciibib("name")).to eq <<~ASCIIBIB - name.name.completename:: John Doe - ASCIIBIB - end - end - - it "raise ArgumentError" do - expect do - described_class.new - end.to raise_error ArgumentError, "Should be given :surname or :completename" - end -end diff --git a/spec/relaton_bib/hash_converter_spec.rb b/spec/relaton_bib/hash_converter_spec.rb deleted file mode 100644 index dd67e32..0000000 --- a/spec/relaton_bib/hash_converter_spec.rb +++ /dev/null @@ -1,136 +0,0 @@ -RSpec.describe RelatonBib::HashConverter do - it "warn if bibitem missig" do - expect do - ret = { relation: [type: "updates"] } - RelatonBib::HashConverter.relation_bibitem_hash_to_bib ret[:relation][0] - end.to output(/Bibitem missing/).to_stderr_from_any_process - end - - it "make affiliation description from string" do - affiliation = RelatonBib::HashConverter.affiliation_hash_to_bib( - affiliation: { - description: "Description", organization: { name: "Org" } - }, - ) - expect(affiliation).to be_instance_of Array - expect(affiliation.first).to be_instance_of RelatonBib::Affiliation - end - - it "make localized string from hash" do - ls = RelatonBib::HashConverter.localizedstring content: "string" - expect(ls).to be_instance_of RelatonBib::LocalizedString - end - - # it "make localityStack from unwrapped loclaity" do - # hash = { locality: [{ type: "section", reference_from: "1" }] } - # RelatonBib::HashConverter.relation_locality_hash_to_bib hash - # expect(hash[:locality].first).to be_instance_of RelatonBib::LocalityStack - # end - - # it "make sourceLocalityStack from unwrapped sourceLoclaity" do - # hash = { source_locality: [{ type: "section", reference_from: "1" }] } - # RelatonBib::HashConverter.relation_source_locality_hash_to_bib hash - # expect(hash[:source_locality].first).to be_instance_of( - # RelatonBib::SourceLocalityStack, - # ) - # end - - it "parse validity time" do - r = RelatonBib::HashConverter.parse_validity_time({ begins: 1999 }, :begins) - expect(r.to_s).to match(/^1999-01-01/) - r = RelatonBib::HashConverter.parse_validity_time({ ends: 1999 }, :ends) - expect(r.to_s).to match(/^1999-12-31/) - r = RelatonBib::HashConverter.parse_validity_time( - { begins: "1999-02" }, :begins - ) - expect(r.to_s).to match(/^1999-02-01/) - r = RelatonBib::HashConverter.parse_validity_time( - { ends: "1999-02" }, :ends - ) - expect(r.to_s).to match(/^1999-02-28/) - end - - context "contacts_hash_to_bib" do - it "create address from old hash" do - hash = { contact: [{ street: "Street", city: "City", country: "Country" }] } - address = described_class.contacts_hash_to_bib hash - expect(address).to be_instance_of Array - expect(address.first).to be_instance_of RelatonBib::Address - expect(address.first.street).to eq ["Street"] - expect(address.first.city).to eq "City" - expect(address.first.country).to eq "Country" - end - - it "create formatted address" do - entity = { contact: [{ address: { formatted_address: "Address" } }] } - address = RelatonBib::HashConverter.contacts_hash_to_bib entity - expect(address).to be_instance_of Array - expect(address.first).to be_instance_of RelatonBib::Address - expect(address.first.formatted_address).to eq "Address" - end - - it "create formatted address from string" do - entity = { contact: [{ address: "Address" }] } - address = RelatonBib::HashConverter.contacts_hash_to_bib entity - expect(address).to be_instance_of Array - expect(address.first).to be_instance_of RelatonBib::Address - expect(address.first.formatted_address).to eq "Address" - end - - it "create contact from old hash" do - hash = { contact: [{ type: "phone", value: "123" }] } - contact = described_class.contacts_hash_to_bib hash - expect(contact).to be_instance_of Array - expect(contact.first).to be_instance_of RelatonBib::Contact - expect(contact.first.type).to eq "phone" - expect(contact.first.value).to eq "123" - end - - it "create phone" do - hash = { contact: [{ phone: "223322", type: "mobile" }] } - contact = described_class.contacts_hash_to_bib hash - expect(contact).to be_instance_of Array - expect(contact.first).to be_instance_of RelatonBib::Contact - expect(contact.first.type).to eq "phone" - expect(contact.first.subtype).to eq "mobile" - expect(contact.first.value).to eq "223322" - end - end - - it "create copyright" do - ret = { - copyright: { - owner: { - name: [{ content: "Owner Name" }], abbreviation: { content: "ABBR" }, - contact: [{ uri: "http://example.com" }] - }, - from: "2022", - }, - } - copyright = described_class.copyright_hash_to_bib ret - expect(copyright).to be_instance_of Array - expect(copyright[0][:owner][0][:name][0][:content]).to eq "Owner Name" - expect(copyright[0][:owner][0][:abbreviation][:content]).to eq "ABBR" - expect(copyright[0][:owner][0][:contact][0]).to be_instance_of RelatonBib::Contact - expect(copyright[0][:owner][0][:contact][0].type).to eq "uri" - expect(copyright[0][:owner][0][:contact][0].value).to eq "http://example.com" - end - - context "create doctype" do - it "from string" do - ret = { ext: { doctype: "Doctype" } } - described_class.doctype_hash_to_bib ret - expect(ret[:doctype]).to be_instance_of RelatonBib::DocumentType - expect(ret[:doctype].type).to eq "Doctype" - expect(ret[:doctype].abbreviation).to be_nil - end - - it "from hash" do - ret = { ext: { doctype: { type: "Doctype", abbreviation: "DCT" } } } - described_class.doctype_hash_to_bib ret - expect(ret[:doctype]).to be_instance_of RelatonBib::DocumentType - expect(ret[:doctype].type).to eq "Doctype" - expect(ret[:doctype].abbreviation).to eq "DCT" - end - end -end diff --git a/spec/relaton_bib/hit_collection_spec.rb b/spec/relaton_bib/hit_collection_spec.rb deleted file mode 100644 index bf2b3db..0000000 --- a/spec/relaton_bib/hit_collection_spec.rb +++ /dev/null @@ -1,33 +0,0 @@ -RSpec.describe RelatonBib::HitCollection do - subject do - hits = RelatonBib::HitCollection.new("ref") - hit = RelatonBib::Hit.new({}) - item = double "bibitem" - expect(item).to receive(:to_xml).at_most :once - expect(hit).to receive(:fetch).and_return(item).at_most :twice - hits << hit - hits - end - - it("fetches all hits") { subject.fetch } - - it "select hits" do - expect(subject.select).to be_instance_of RelatonBib::HitCollection - end - - it "collection to xml" do - expect(subject.to_xml).to eq %{<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<documents/>\n} - end - - it "reduce collection" do - subject.reduce!([]) { |sum, hit| sum << hit } - expect(subject).to be_instance_of RelatonBib::HitCollection - end - - it "returns string" do - expect(subject.to_s).to eq( - "<RelatonBib::HitCollection:#{format('%#.14x', subject.object_id << 1)} "\ - "@ref=ref @fetched=false>", - ) - end -end diff --git a/spec/relaton_bib/hit_spec.rb b/spec/relaton_bib/hit_spec.rb deleted file mode 100644 index 301cc35..0000000 --- a/spec/relaton_bib/hit_spec.rb +++ /dev/null @@ -1,20 +0,0 @@ -RSpec.describe RelatonBib::Hit do - subject { RelatonBib::Hit.new({}) } - - it "returns string" do - expect(subject.to_s).to eq( - "<RelatonBib::Hit:#{format('%#.14x', subject.object_id << 1)} " \ - '@text="" @fetched="false" @fullIdentifier="" @title="">', - ) - end - - it "to xml" do - item = RelatonBib::BibliographicItem.new - expect(subject).to receive(:fetch).and_return item - expect(subject.to_xml).to match(/<bibitem schema-version="v\d+\.\d+\.\d+"\/>/) - end - - it "raise not implemented" do - expect { subject.fetch }.to raise_error "Not implemented" - end -end diff --git a/spec/relaton_bib/image_spec.rb b/spec/relaton_bib/image_spec.rb deleted file mode 100644 index 30d7638..0000000 --- a/spec/relaton_bib/image_spec.rb +++ /dev/null @@ -1,67 +0,0 @@ -describe RelatonBib::Image do - subject do - described_class.new( - id: "id", - src: "src", - mimetype: "mime type", - filename: "file name", - width: "60%", - height: "40%", - alt: "Alt", - title: "Title", - longdesc: "long description", - ) - end - - it "initialize" do - expect(subject.id).to eq "id" - expect(subject.src).to eq "src" - expect(subject.mimetype).to eq "mime type" - expect(subject.filename).to eq "file name" - expect(subject.width).to eq "60%" - expect(subject.height).to eq "40%" - expect(subject.alt).to eq "Alt" - expect(subject.title).to eq "Title" - expect(subject.longdesc).to eq "long description" - end - - it "to_xml" do - builder = Nokogiri::XML::Builder.new(encoding: "UTF-8") do |xml| - subject.to_xml xml - end - xml = builder.doc.root.to_xml - expect(xml).to be_equivalent_to <<~XML - <image id="id" src="src" mimetype="mime type" filename="file name" width="60%" height="40%" alt="Alt" title="Title" longdesc="long description"/> - XML - end - - it "to_hash" do - expect(subject.to_hash).to eq( - "image" => { - "id" => "id", - "src" => "src", - "mimetype" => "mime type", - "filename" => "file name", - "width" => "60%", - "height" => "40%", - "alt" => "Alt", - "title" => "Title", - "longdesc" => "long description", - }, - ) - end - - it "to_asciibib" do - expect(subject.to_asciibib).to eq <<~BIB - image.id:: id - image.src:: src - image.mimetype:: mime type - image.filename:: file name - image.width:: 60% - image.height:: 40% - image.alt:: Alt - image.title:: Title - image.longdesc:: long description - BIB - end -end diff --git a/spec/relaton_bib/localized_string_spec.rb b/spec/relaton_bib/localized_string_spec.rb deleted file mode 100644 index 5feda89..0000000 --- a/spec/relaton_bib/localized_string_spec.rb +++ /dev/null @@ -1,59 +0,0 @@ -RSpec.describe RelatonBib::LocalizedString do - it "raise ArgumentError" do - expect do - RelatonBib::LocalizedString.new [] - end.to raise_error ArgumentError, "LocalizedString content is empty" - end - - it "create with Aray<String> content" do - ls = RelatonBib::LocalizedString.new ["Content"] - expect(ls.content[0].content).to eq "Content" - end - - context "instance" do - subject do - described_class.new(<<-XML, "en", "Latn") - prefix <p>content <p>< & > characters</p> to escape</p> - <p>Text</p> suffix - XML - end - - it "returns false" do - expect(subject.empty?).to be false - end - - it "escape HTML" do - xml = Nokogiri::XML::Builder.new do |b| - b.localized_string { subject.to_xml(b) } - end - expect(xml.doc.root.to_s).to be_equivalent_to <<~XML - <localized_string language="en" script="Latn"> - prefix <p>content <p>< & > characters</p> to escape</p> - <p>Text</p> suffix - </localized_string> - XML - end - - it "don't escape HTML entities" do - ls = described_class.new "Content &", "en", "Latn" - xml = Nokogiri::XML::Builder.new do |b| - b.localized_string { ls.to_xml(b) } - end - expect(xml.doc.root.to_s).to be_equivalent_to <<~XML - <localized_string language="en" script="Latn">Content &</localized_string> - XML - end - - it "escape String content only" do - ls = described_class.new [described_class.new("Content <p>Text</p>", "en", "Latn")] - xml = Nokogiri::XML::Builder.new do |b| - b.localized_string { ls.to_xml(b) } - end - expect(xml.doc.root.to_s).to be_equivalent_to <<~XML - <localized_string> - <variant language="en" script="Latn">Content <p>Text</p></variant> - </localized_string> - XML - end - end -end diff --git a/spec/relaton_bib/organization_spec.rb b/spec/relaton_bib/organization_spec.rb deleted file mode 100644 index dd06f51..0000000 --- a/spec/relaton_bib/organization_spec.rb +++ /dev/null @@ -1,46 +0,0 @@ -describe RelatonBib::Organization do - subject do - described_class.new( - name: "Org", - abbreviation: "ORG", - subdivision: [RelatonBib::LocalizedString.new("Subdivision", "en")], - url: "http://example.com", - identifier: [RelatonBib::OrgIdentifier.new("uri", "http://example.com")], - contact: [RelatonBib::Contact.new(type: "work", value: "http://example.com")], - logo: RelatonBib::Image.new(id: "IMG", src: "http://example.com/logo.png", mimetype: "image/png") - ) - end - - context "==" do - it "same content" do - other = described_class.new( - name: "Org", - abbreviation: "ORG", - subdivision: [RelatonBib::LocalizedString.new("Subdivision", "en")], - url: "http://example.com", - identifier: [RelatonBib::OrgIdentifier.new("uri", "http://example.com")], - contact: [RelatonBib::Contact.new(type: "work", value: "http://example.com")], - logo: RelatonBib::Image.new(id: "IMG", src: "http://example.com/logo.png", mimetype: "image/png") - ) - expect(subject).to eq other - end - - it "different content" do - other = described_class.new( - name: "Org", - abbreviation: "ORG", - subdivision: [RelatonBib::LocalizedString.new("Subdivision", "en")], - url: "http://example.com", - identifier: [RelatonBib::OrgIdentifier.new("uri", "http://example.com")], - contact: [RelatonBib::Contact.new(type: "work", value: "http://example.com")] - ) - expect(subject).not_to eq other - end - end -end - -describe RelatonBib::OrgIdentifier do - # it "raises invalid type argument error" do - # expect { RelatonBib::OrgIdentifier.new "type", "value" }.to raise_error ArgumentError - # end -end diff --git a/spec/relaton_bib/person_spec.rb b/spec/relaton_bib/person_spec.rb deleted file mode 100644 index 6712ee0..0000000 --- a/spec/relaton_bib/person_spec.rb +++ /dev/null @@ -1,20 +0,0 @@ -RSpec.describe RelatonBib::Person do - context RelatonBib::FullName do - it "rises name error" do - expect do - RelatonBib::FullName.new - end.to raise_error ArgumentError - end - end - - context RelatonBib::PersonIdentifier do - it "raises type error" do - expect do - RelatonBib::Person.new( - name: RelatonBib::FullName.new(completename: "John Lennon"), - identifier: RelatonBib::PersonIdentifier.new("wrong_type", "value"), - ) - end.to raise_error ArgumentError - end - end -end diff --git a/spec/relaton_bib/place_spec.rb b/spec/relaton_bib/place_spec.rb deleted file mode 100644 index d543de2..0000000 --- a/spec/relaton_bib/place_spec.rb +++ /dev/null @@ -1,41 +0,0 @@ -describe RelatonBib::Place do - it "raise ArgumentError" do - expect do - described_class.new - end.to raise_error ArgumentError - end - - describe RelatonBib::Place::RegionType do - context "raise ArgumentError" do - it "when name is nil adn ISO code is nil" do - expect do - described_class.new - end.to raise_error ArgumentError - end - - it "when name is nil and ISO code is invalid" do - expect do - described_class.new iso: "invalid" - end.to raise_error ArgumentError - end - end - - context "create instance" do - it "with name" do - expect(described_class.new(name: "name").name).to eq "name" - end - - it "with name and ISO code" do - region = described_class.new(name: "name", iso: "WA") - expect(region.name).to eq "name" - expect(region.iso).to eq "WA" - end - - it "with valid ISO code" do - region = described_class.new(iso: "WA") - expect(region.iso).to eq "WA" - expect(region.name).to eq "Washington" - end - end - end -end diff --git a/spec/relaton_bib/renderer/bibxml_spec.rb b/spec/relaton_bib/renderer/bibxml_spec.rb deleted file mode 100644 index 4a3f3cc..0000000 --- a/spec/relaton_bib/renderer/bibxml_spec.rb +++ /dev/null @@ -1,28 +0,0 @@ -describe RelatonBib::Renderer::BibXML do - context "instance methods" do - context "ref_attrs" do - it "upcase anchor for IANA" do - docid = RelatonBib::DocumentIdentifier.new id: "IANA dns-parameters", type: "IANA" - bib = RelatonBib::BibliographicItem.new(docid: [docid]) - renderer = RelatonBib::Renderer::BibXML.new bib - ref_attrs = renderer.ref_attrs - expect(ref_attrs).to be_instance_of Hash - expect(ref_attrs[:anchor]).to eq "DNS-PARAMETERS" - end - end - - context "render_seriesinfo" do - it "do not render trademark" do - docid = [ - RelatonBib::DocumentIdentifier.new(id: "IEEE 123", type: "IEEE"), - RelatonBib::DocumentIdentifier.new(id: "IEEE 123", type: "IEEE", scope: "trademark"), - ] - bib = RelatonBib::BibliographicItem.new docid: docid - renderer = RelatonBib::Renderer::BibXML.new bib - builder = double "builder" - # expect(builder).to receive(:seriesInfo).with(name: "IEEE", value: "IEEE 123").once - renderer.render_seriesinfo builder - end - end - end -end diff --git a/spec/relaton_bib/series_spec.rb b/spec/relaton_bib/series_spec.rb deleted file mode 100644 index 2e66778..0000000 --- a/spec/relaton_bib/series_spec.rb +++ /dev/null @@ -1,14 +0,0 @@ -# frozen_string_literal: true - -RSpec.describe RelatonBib::Series do - it "raise argument error when title argument missed" do - expect { RelatonBib::Series.new }.to raise_error ArgumentError - end - - # it "raises invalid type atgument error" do - # expect do - # title = RelatonBib::TypedTitleString.new(content: "title") - # RelatonBib::Series.new title: title, type: "type" - # end.to output(/Series type is invalid: type/).to_stderr - # end -end diff --git a/spec/relaton_bib/structured_identifier_spec.rb b/spec/relaton_bib/structured_identifier_spec.rb deleted file mode 100644 index 0b421c1..0000000 --- a/spec/relaton_bib/structured_identifier_spec.rb +++ /dev/null @@ -1,7 +0,0 @@ -RSpec.describe RelatonBib::StructuredIdentifier do - it "remove data for Chinise Standard" do - sid = RelatonBib::StructuredIdentifier.new docnumber: "TEST-1999", type: "Chinese Standard" - sid.remove_date - expect(sid.docnumber).to eq "TEST" - end -end diff --git a/spec/relaton_bib/typed_title_string_spec.rb b/spec/relaton_bib/typed_title_string_spec.rb deleted file mode 100644 index 308197e..0000000 --- a/spec/relaton_bib/typed_title_string_spec.rb +++ /dev/null @@ -1,107 +0,0 @@ -RSpec.describe RelatonBib::TypedTitleString do - # it "raises invalid type argument error" do - # expect do - # RelatonBib::TypedTitleString.new type: "type", content: "title" - # end.to output(/title type "type" is invalid/).to_stderr - # end - - it "raises missed title or content argument error" do - expect { RelatonBib::TypedTitleString.new }.to raise_error ArgumentError - end - - context "instance" do - subject do - RelatonBib::TypedTitleString.new( - type: "main", - title: RelatonBib::FormattedString.new(content: "Title", format: nil), - ) - end - - it "create instance without exeption" do - expect(subject).to be_instance_of RelatonBib::TypedTitleString - end - - it "create instance with title as hash" do - subj = RelatonBib::TypedTitleString.new( - title: { content: "Title", language: "en", script: "Latn", format: "text/plain" }, - ) - expect(subj.title).to be_instance_of RelatonBib::FormattedString - expect(subj.title.content).to eq "Title" - expect(subj.title.language).to eq ["en"] - expect(subj.title.script).to eq ["Latn"] - expect(subj.title.format).to eq "text/plain" - end - - it "return hash when title is string" do - expect(subject.to_hash).to eq("type" => "main", "content" => "Title") - end - end - - context "create title-intro, title-main, title-part from string" do - it "empty" do - t = RelatonBib::TypedTitleString.from_string "" - expect(t.size).to eq 2 - expect(t[0].title.content).to eq "" - expect(t[0].type).to eq "title-main" - expect(t[1].title.content).to eq "" - expect(t[1].type).to eq "main" - end - - it "with main" do - t = RelatonBib::TypedTitleString.from_string "Main" - expect(t.size).to eq 2 - expect(t[0].title.content).to eq "Main" - expect(t[0].type).to eq "title-main" - expect(t[1].title.content).to eq "Main" - expect(t[1].type).to eq "main" - end - - it "with main & part" do - t = RelatonBib::TypedTitleString.from_string "Main - Part 1:" - expect(t.size).to eq 3 - expect(t[0].title.content).to eq "Main" - expect(t[0].type).to eq "title-main" - expect(t[1].title.content).to eq "Part 1:" - expect(t[1].type).to eq "title-part" - expect(t[2].title.content).to eq "Main - Part 1:" - expect(t[2].type).to eq "main" - end - - it "with intro & main" do - t = RelatonBib::TypedTitleString.from_string "Intro - Main" - expect(t.size).to eq 3 - expect(t[0].title.content).to eq "Intro" - expect(t[0].type).to eq "title-intro" - expect(t[1].title.content).to eq "Main" - expect(t[1].type).to eq "title-main" - expect(t[2].title.content).to eq "Intro - Main" - expect(t[2].type).to eq "main" - end - - it "with intro & main & part" do - t = RelatonBib::TypedTitleString.from_string "Intro - Main - Part 1:" - expect(t.size).to eq 4 - expect(t[0].title.content).to eq "Intro" - expect(t[0].type).to eq "title-intro" - expect(t[1].title.content).to eq "Main" - expect(t[1].type).to eq "title-main" - expect(t[2].title.content).to eq "Part 1:" - expect(t[2].type).to eq "title-part" - expect(t[3].title.content).to eq "Intro - Main - Part 1:" - expect(t[3].type).to eq "main" - end - - it "with extra part" do - t = RelatonBib::TypedTitleString.from_string "Intro - Main - Part 1: - Extra" - expect(t.size).to eq 4 - expect(t[0].title.content).to eq "Intro" - expect(t[0].type).to eq "title-intro" - expect(t[1].title.content).to eq "Main" - expect(t[1].type).to eq "title-main" - expect(t[2].title.content).to eq "Part 1: -- Extra" - expect(t[2].type).to eq "title-part" - expect(t[3].title.content).to eq "Intro - Main - Part 1: -- Extra" - expect(t[3].type).to eq "main" - end - end -end diff --git a/spec/relaton_bib/typed_uri_spec.rb b/spec/relaton_bib/typed_uri_spec.rb deleted file mode 100644 index 2da52bc..0000000 --- a/spec/relaton_bib/typed_uri_spec.rb +++ /dev/null @@ -1,40 +0,0 @@ -RSpec.describe RelatonBib::TypedUri do - it "set content" do - uri = RelatonBib::TypedUri.new type: "src", content: nil - uri.content = "http://example.com" - expect(uri.content).to be_instance_of Addressable::URI - expect(uri.content.to_s).to eq "http://example.com" - end - - context "instance methods" do - subject do - described_class.new type: "src", content: "http://example.com", language: "en", script: "Latn" - end - - it "#to_xml" do - builder = Nokogiri::XML::Builder.new - subject.to_xml(builder) - expect(builder.doc.root.to_xml).to be_equivalent_to <<~XML - <uri type="src" language="en" script="Latn">http://example.com</uri> - XML - end - - it "#to_asciibib" do - expect(subject.to_asciibib("org")).to eq <<~OUTPUT - org.link.type:: src - org.link.content:: http://example.com - org.link.language:: en - org.link.script:: Latn - OUTPUT - end - - it "#to_hash" do - expect(subject.to_hash).to eq( - "content" => "http://example.com", - "type" => "src", - "language" => "en", - "script" => "Latn", - ) - end - end -end diff --git a/spec/relaton_bib/workers_pool_spec.rb b/spec/relaton_bib/workers_pool_spec.rb deleted file mode 100644 index 1cbbf89..0000000 --- a/spec/relaton_bib/workers_pool_spec.rb +++ /dev/null @@ -1,14 +0,0 @@ -RSpec.describe RelatonBib::WorkersPool do - subject { RelatonBib::WorkersPool.new } - - it { expect(subject).to be_instance_of RelatonBib::WorkersPool } - - it "do jobs" do - subject.worker { |n| n * 2 } - (1..5).entries.each { |n| subject << n } - expect(subject.size).to be_instance_of Integer - subject.end - result = subject.result - expect(result.sort).to eq [2, 4, 6, 8, 10] - end -end diff --git a/spec/relaton_bib/xml_parser_spec.rb b/spec/relaton_bib/xml_parser_spec.rb deleted file mode 100644 index 9e96e46..0000000 --- a/spec/relaton_bib/xml_parser_spec.rb +++ /dev/null @@ -1,115 +0,0 @@ -RSpec.describe RelatonBib::XMLParser do - it "creates item from xml" do - xml = File.read "spec/examples/bib_item.xml", encoding: "UTF-8" - item = RelatonBib::XMLParser.from_xml xml - expect(item.to_xml).to be_equivalent_to xml - end - - it "creates item from bibdata xml" do - xml = File.read "spec/examples/bibdata_item.xml", encoding: "UTF-8" - item = RelatonBib::XMLParser.from_xml xml - expect(item.to_xml(bibdata: true)).to be_equivalent_to xml - end - - it "parse date from" do - xml = <<~XML - <bibitem id="id"> - <title type="main">Title</title> - <date type="circulated"><from>2001-02-03</from></date> - </bibitem> - XML - item = RelatonBib::XMLParser.from_xml xml - expect(item.date.first.from.to_s).to eq "2001-02-03" - end - - it "parse locality not inclosed in localityStack" do - xml = <<~XML - <bibitem id="id"> - <title type="main">Title</title> - <relation type="updates"> - <bibitem> - <formattedref format="text/plain">ISO 19115</formattedref> - </bibitem> - <locality type="section"> - <referenceFrom>Reference from</referenceFrom> - </locality> - </relation> - </bibitem> - XML - item = RelatonBib::XMLParser.from_xml xml - expect(item.relation.first.locality.first).to be_instance_of( - RelatonBib::Locality, - ) - end - - it "parse sourceLocality not inclosed in sourceLocalityStack" do - xml = <<~XML - <bibitem id="id"> - <title type="main">Title</title> - <relation type="updates"> - <bibitem> - <formattedref format="text/plain">ISO 19115</formattedref> - </bibitem> - <sourceLocality type="section"> - <referenceFrom>Reference from</referenceFrom> - </sourceLocality> - </relation> - </bibitem> - XML - item = RelatonBib::XMLParser.from_xml xml - expect(item.relation.first.source_locality.first).to be_instance_of( - RelatonBib::SourceLocality, - ) - end - - context "parse abstract" do - it "with <br/> tag" do - xml = <<~XML - <bibitem id="id"> - <title type="main">Title</title> - <abstract>Content<br/>Content</abstract> - </bibitem> - XML - doc = Nokogiri::XML(xml).at "/bibitem" - abstract = RelatonBib::XMLParser.send :fetch_abstract, doc - expect(abstract[0].content).to eq "Content<br/>Content" - end - end - - it "ignore empty dates" do - xml = <<~XML - <bibitem id="id"> - <title type="main">Title</title> - <date type="circulated" /> - </bibitem> - XML - item = RelatonBib::XMLParser.from_xml xml - expect(item.date).to be_empty - end - - it "parse formatted address" do - xml = <<~XML - <bibitem id="id"> - <title type="main">Title</title> - <contributor> - <organization> - <name>Organization</name> - <address> - <formattedAddress>Address</formattedAddress> - </address> - </organization> - </contributor> - </bibitem> - XML - item = RelatonBib::XMLParser.from_xml xml - expect(item.contributor.first.entity.contact.first.formatted_address).to eq "Address" - end - - it "warn if XML doesn't have bibitem or bibdata element" do - item = "" - expect { item = RelatonBib::XMLParser.from_xml "" }.to output( - /Can't find bibitem/, - ).to_stderr_from_any_process - expect(item).to be_nil - end -end diff --git a/spec/relaton_bib_spec.rb b/spec/relaton_bib_spec.rb deleted file mode 100644 index 8f9279d..0000000 --- a/spec/relaton_bib_spec.rb +++ /dev/null @@ -1,67 +0,0 @@ -RSpec.describe RelatonBib do - it "has a version number" do - expect(RelatonBib::VERSION).not_to be nil - end - - it "returns grammar hash" do - hash = RelatonBib.grammar_hash - expect(hash).to be_instance_of String - expect(hash.size).to eq 32 - end - - context "parse date" do - it "February 2012" do - expect(RelatonBib.parse_date("February 2012")).to eq "2012-02" - expect(RelatonBib.parse_date("February 2012", false)).to eq Date.new(2012, 2, 1) - end - - it "February 11, 2012" do - expect(RelatonBib.parse_date("February 11, 2012")).to eq "2012-02-11" - expect(RelatonBib.parse_date("February 11, 2012", false)).to eq Date.new(2012, 2, 11) - end - - it "2012-02-11" do - expect(RelatonBib.parse_date("2012-02-11")).to eq "2012-02-11" - expect(RelatonBib.parse_date("2012-02-11", false)).to eq Date.new(2012, 2, 11) - end - - it "2012-2-3" do - expect(RelatonBib.parse_date("2012-2-3")).to eq "2012-02-03" - expect(RelatonBib.parse_date("2012-2-3", false)).to eq Date.new(2012, 2, 3) - end - - it "2012-02" do - expect(RelatonBib.parse_date("2012-02")).to eq "2012-02" - expect(RelatonBib.parse_date("2012-02", false)).to eq Date.new(2012, 2, 1) - end - - it "2012-2" do - expect(RelatonBib.parse_date("2012-2")).to eq "2012-02" - expect(RelatonBib.parse_date("2012-2", false)).to eq Date.new(2012, 2, 1) - end - - it "invalid date" do - expect do - expect(RelatonBib.parse_date("2012-02-31")).to eq "2012-02-31" - end.to output(/invalid date/).to_stderr_from_any_process - end - end - - it "parse YAML with an old version of Psych" do - method = double "params" - expect(method).to receive(:parameters).and_return [%i[req yaml]] - expect(YAML).to receive(:method).with(:safe_load).and_return method - expect(YAML).to receive(:safe_load).with(kind_of(String), [], symbolize_names: false).and_return({}) - RelatonBib.parse_yaml "key: value" - end - - it "parse YAML with a new version of Psych" do - method = double "params" - expect(method).to receive(:parameters).and_return [%i[req yaml permitted_classes]] - expect(YAML).to receive(:method).with(:safe_load).and_return method - expect(YAML).to receive(:safe_load) - .with(kind_of(String), permitted_classes: [], symbolize_names: false) - .and_return({}) - RelatonBib.parse_yaml "key: value" - end -end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index c683247..e78b555 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -2,9 +2,10 @@ SimpleCov.start { add_filter "/spec/" } require "bundler/setup" -require "relaton_bib" +require "relaton/bib" require "rspec/matchers" require "equivalent-xml" +require "jing" RSpec.configure do |config| # Enable flags like --only-failures and --next-failure