pubid 2.0.0.pre.alpha.9 → 2.0.0.pre.alpha.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.adoc +33 -11
- data/conformance/pending.yaml +4 -0
- data/lib/pubid/adobe/identifier.rb +1 -3
- data/lib/pubid/adobe/parser.rb +10 -2
- data/lib/pubid/adobe.rb +1 -0
- data/lib/pubid/amca/builder.rb +2 -2
- data/lib/pubid/amca/identifiers/base.rb +49 -27
- data/lib/pubid/amca/identifiers/interpretation.rb +17 -9
- data/lib/pubid/amca/identifiers/publication.rb +13 -9
- data/lib/pubid/amca/identifiers/standard.rb +2 -0
- data/lib/pubid/amca/parser.rb +1 -1
- data/lib/pubid/amca/renderer.rb +4 -4
- data/lib/pubid/amca/urn_generator.rb +2 -2
- data/lib/pubid/amca.rb +2 -1
- data/lib/pubid/ansi/builder.rb +2 -2
- data/lib/pubid/ansi/identifier.rb +18 -0
- data/lib/pubid/ansi/parser.rb +1 -1
- data/lib/pubid/ansi/renderer.rb +2 -2
- data/lib/pubid/ansi.rb +5 -5
- data/lib/pubid/api/builder.rb +16 -2
- data/lib/pubid/api/identifier.rb +25 -4
- data/lib/pubid/api/identifiers/mpms.rb +10 -8
- data/lib/pubid/api/parser.rb +1 -1
- data/lib/pubid/api/renderer.rb +16 -7
- data/lib/pubid/api/single_identifier.rb +5 -12
- data/lib/pubid/api.rb +1 -0
- data/lib/pubid/ashrae/builder.rb +31 -10
- data/lib/pubid/ashrae/identifiers/addenda_package.rb +6 -0
- data/lib/pubid/ashrae/identifiers/addendum.rb +8 -0
- data/lib/pubid/ashrae/identifiers/base.rb +81 -5
- data/lib/pubid/ashrae/identifiers/combined_addenda.rb +7 -0
- data/lib/pubid/ashrae/identifiers/errata.rb +9 -0
- data/lib/pubid/ashrae/identifiers/guideline.rb +3 -0
- data/lib/pubid/ashrae/identifiers/interpretation.rb +16 -0
- data/lib/pubid/ashrae/identifiers/standard.rb +3 -0
- data/lib/pubid/ashrae/parser.rb +23 -8
- data/lib/pubid/ashrae/renderer.rb +6 -6
- data/lib/pubid/ashrae/supplement_identifier.rb +17 -2
- data/lib/pubid/ashrae/urn_generator.rb +8 -2
- data/lib/pubid/ashrae.rb +7 -1
- data/lib/pubid/asme/builder.rb +11 -2
- data/lib/pubid/asme/identifier.rb +9 -0
- data/lib/pubid/asme/identifiers/standard.rb +86 -2
- data/lib/pubid/asme/parser.rb +1 -1
- data/lib/pubid/asme/renderer.rb +3 -3
- data/lib/pubid/asme/single_identifier.rb +8 -1
- data/lib/pubid/asme/urn_generator.rb +2 -2
- data/lib/pubid/asme.rb +1 -0
- data/lib/pubid/astm/builder.rb +10 -3
- data/lib/pubid/astm/identifier.rb +9 -0
- data/lib/pubid/astm/identifiers/adjunct.rb +16 -1
- data/lib/pubid/astm/identifiers/code_number.rb +81 -0
- data/lib/pubid/astm/identifiers/data_series.rb +2 -0
- data/lib/pubid/astm/identifiers/iso_dual_published.rb +16 -0
- data/lib/pubid/astm/identifiers/manual.rb +10 -0
- data/lib/pubid/astm/identifiers/monograph.rb +2 -0
- data/lib/pubid/astm/identifiers/research_report.rb +10 -0
- data/lib/pubid/astm/identifiers/standard.rb +10 -0
- data/lib/pubid/astm/identifiers/technical_report.rb +2 -0
- data/lib/pubid/astm/identifiers/work_in_progress.rb +2 -0
- data/lib/pubid/astm/identifiers.rb +1 -0
- data/lib/pubid/astm/parser.rb +1 -1
- data/lib/pubid/astm/renderer.rb +1 -1
- data/lib/pubid/astm/single_identifier.rb +31 -1
- data/lib/pubid/astm/urn_generator.rb +7 -5
- data/lib/pubid/astm.rb +1 -0
- data/lib/pubid/bipm/builder.rb +66 -10
- data/lib/pubid/bipm/identifier.rb +134 -9
- data/lib/pubid/bipm/identifiers/committee_document.rb +12 -0
- data/lib/pubid/bipm/identifiers/guide.rb +11 -0
- data/lib/pubid/bipm/identifiers/meeting.rb +12 -0
- data/lib/pubid/bipm/identifiers/mep.rb +12 -0
- data/lib/pubid/bipm/identifiers/metrologia_article.rb +24 -0
- data/lib/pubid/bipm/identifiers/si_brochure.rb +13 -0
- data/lib/pubid/bipm/parser.rb +65 -12
- data/lib/pubid/bipm/renderer.rb +8 -0
- data/lib/pubid/bipm/urn_parser.rb +11 -3
- data/lib/pubid/bipm.rb +7 -1
- data/lib/pubid/bsi/builder.rb +48 -38
- data/lib/pubid/bsi/identifiers/adopted_european_norm.rb +36 -7
- data/lib/pubid/bsi/identifiers/adopted_international_standard.rb +7 -6
- data/lib/pubid/bsi/identifiers/british_industrial_practice.rb +0 -1
- data/lib/pubid/bsi/identifiers/bundled_identifier.rb +10 -0
- data/lib/pubid/bsi/identifiers/committee_document.rb +10 -1
- data/lib/pubid/bsi/identifiers/handbook.rb +0 -2
- data/lib/pubid/bsi/identifiers/practice_guide.rb +0 -1
- data/lib/pubid/bsi/identifiers/set.rb +11 -0
- data/lib/pubid/bsi/identifiers/standalone_amendment.rb +10 -1
- data/lib/pubid/bsi/parser.rb +1 -1
- data/lib/pubid/bsi/renderer.rb +63 -51
- data/lib/pubid/bsi/single_identifier.rb +16 -7
- data/lib/pubid/bsi/urn_generator.rb +11 -2
- data/lib/pubid/bsi.rb +7 -1
- data/lib/pubid/builder/base.rb +18 -8
- data/lib/pubid/bundled_identifier.rb +16 -6
- data/lib/pubid/calconnect/identifier.rb +9 -5
- data/lib/pubid/calconnect/parser.rb +1 -1
- data/lib/pubid/calconnect.rb +7 -1
- data/lib/pubid/ccsds/identifier.rb +9 -2
- data/lib/pubid/ccsds/identifiers/base.rb +4 -2
- data/lib/pubid/ccsds/identifiers/corrigendum.rb +2 -2
- data/lib/pubid/ccsds/parser.rb +1 -1
- data/lib/pubid/ccsds/single_identifier.rb +2 -2
- data/lib/pubid/ccsds.rb +1 -0
- data/lib/pubid/cen_cenelec/builder.rb +101 -76
- data/lib/pubid/cen_cenelec/identifier.rb +115 -3
- data/lib/pubid/cen_cenelec/identifiers/adopted_european_norm.rb +27 -16
- data/lib/pubid/cen_cenelec/identifiers/amendment.rb +46 -6
- data/lib/pubid/cen_cenelec/identifiers/base.rb +8 -9
- data/lib/pubid/cen_cenelec/identifiers/cen_report.rb +1 -1
- data/lib/pubid/cen_cenelec/identifiers/cen_workshop_agreement.rb +1 -1
- data/lib/pubid/cen_cenelec/identifiers/cenelec_harmonization_document.rb +1 -1
- data/lib/pubid/cen_cenelec/identifiers/consolidated_identifier.rb +29 -20
- data/lib/pubid/cen_cenelec/identifiers/corrigendum.rb +47 -8
- data/lib/pubid/cen_cenelec/identifiers/european_prestandard.rb +27 -2
- data/lib/pubid/cen_cenelec/identifiers/european_specification.rb +1 -1
- data/lib/pubid/cen_cenelec/identifiers/fragment.rb +15 -5
- data/lib/pubid/cen_cenelec/identifiers/guide.rb +1 -1
- data/lib/pubid/cen_cenelec/identifiers/harmonization_document.rb +1 -1
- data/lib/pubid/cen_cenelec/identifiers/technical_report.rb +1 -1
- data/lib/pubid/cen_cenelec/identifiers/technical_specification.rb +1 -1
- data/lib/pubid/cen_cenelec/parser.rb +1 -1
- data/lib/pubid/cen_cenelec/renderer.rb +55 -60
- data/lib/pubid/cen_cenelec/single_identifier.rb +20 -2
- data/lib/pubid/cen_cenelec/urn_generator.rb +66 -44
- data/lib/pubid/cen_cenelec.rb +28 -10
- data/lib/pubid/cie/builder.rb +10 -0
- data/lib/pubid/cie/identifier.rb +6 -1
- data/lib/pubid/cie/identifiers/bundle.rb +4 -2
- data/lib/pubid/cie/identifiers/conference.rb +2 -2
- data/lib/pubid/cie/identifiers/corrigendum.rb +2 -2
- data/lib/pubid/cie/identifiers/dual_published.rb +2 -2
- data/lib/pubid/cie/identifiers/identical.rb +2 -2
- data/lib/pubid/cie/identifiers/joint_published.rb +2 -2
- data/lib/pubid/cie/identifiers/proceedings.rb +8 -6
- data/lib/pubid/cie/identifiers/standard.rb +22 -13
- data/lib/pubid/cie/identifiers/supplement.rb +2 -2
- data/lib/pubid/cie/identifiers/tutorial_bundle.rb +2 -2
- data/lib/pubid/cie/parser.rb +1 -1
- data/lib/pubid/cie.rb +7 -1
- data/lib/pubid/conformance/checks.rb +72 -0
- data/lib/pubid/conformance/corpus/case.rb +55 -0
- data/lib/pubid/conformance/corpus.rb +36 -0
- data/lib/pubid/conformance/generator.rb +212 -0
- data/lib/pubid/conformance/pending.rb +63 -0
- data/lib/pubid/conformance/runner.rb +153 -0
- data/lib/pubid/conformance.rb +55 -0
- data/lib/pubid/core.rb +2 -0
- data/lib/pubid/csa/builder.rb +47 -47
- data/lib/pubid/csa/composite_identifier.rb +14 -19
- data/lib/pubid/csa/identifier.rb +143 -81
- data/lib/pubid/csa/identifiers/bundled.rb +23 -13
- data/lib/pubid/csa/identifiers/canadian_adopted.rb +13 -13
- data/lib/pubid/csa/identifiers/cec.rb +44 -4
- data/lib/pubid/csa/identifiers/combined.rb +95 -73
- data/lib/pubid/csa/identifiers/csa_adopted.rb +4 -4
- data/lib/pubid/csa/identifiers/package.rb +2 -2
- data/lib/pubid/csa/parser.rb +6 -2
- data/lib/pubid/csa/renderer.rb +13 -5
- data/lib/pubid/csa/single_identifier.rb +93 -4
- data/lib/pubid/csa/urn_generator.rb +9 -2
- data/lib/pubid/csa/wrapper_identifier.rb +39 -23
- data/lib/pubid/csa.rb +7 -1
- data/lib/pubid/doi/identifier.rb +6 -3
- data/lib/pubid/doi/parser.rb +1 -1
- data/lib/pubid/doi.rb +1 -0
- data/lib/pubid/easc/identifier.rb +0 -2
- data/lib/pubid/easc/parser.rb +10 -2
- data/lib/pubid/easc.rb +1 -0
- data/lib/pubid/ecma/builder.rb +23 -9
- data/lib/pubid/ecma/identifier.rb +81 -10
- data/lib/pubid/ecma/parser.rb +39 -4
- data/lib/pubid/ecma/renderer.rb +29 -8
- data/lib/pubid/ecma/urn_generator.rb +34 -13
- data/lib/pubid/ecma/urn_parser.rb +30 -14
- data/lib/pubid/ecma.rb +1 -0
- data/lib/pubid/errors.rb +80 -0
- data/lib/pubid/etsi/builder.rb +6 -1
- data/lib/pubid/etsi/identifiers/base.rb +34 -20
- data/lib/pubid/etsi/identifiers/etsi_standard.rb +120 -41
- data/lib/pubid/etsi/identifiers/supplement_identifier.rb +10 -0
- data/lib/pubid/etsi/parser.rb +1 -1
- data/lib/pubid/etsi.rb +1 -0
- data/lib/pubid/evs/builder.rb +26 -0
- data/lib/pubid/evs/identifier.rb +37 -0
- data/lib/pubid/evs/identifiers/national_adoption.rb +17 -0
- data/lib/pubid/evs/identifiers.rb +9 -0
- data/lib/pubid/evs/parser.rb +27 -0
- data/lib/pubid/evs/renderer.rb +30 -0
- data/lib/pubid/evs/urn_generator.rb +30 -0
- data/lib/pubid/evs/urn_parser.rb +80 -0
- data/lib/pubid/evs.rb +90 -0
- data/lib/pubid/export.rb +1 -0
- data/lib/pubid/format_detector.rb +1 -0
- data/lib/pubid/gb/identifier.rb +6 -3
- data/lib/pubid/gb/parser.rb +1 -1
- data/lib/pubid/gb.rb +1 -0
- data/lib/pubid/gost/builder.rb +46 -9
- data/lib/pubid/gost/identifier.rb +0 -2
- data/lib/pubid/gost/identifiers/foreign_reference.rb +1 -1
- data/lib/pubid/gost/parser.rb +10 -2
- data/lib/pubid/gost.rb +1 -0
- data/lib/pubid/iala/identifier.rb +9 -6
- data/lib/pubid/iala/parser.rb +10 -2
- data/lib/pubid/iala/urn_parser.rb +6 -2
- data/lib/pubid/iala.rb +1 -0
- data/lib/pubid/iana/builder.rb +3 -1
- data/lib/pubid/iana/identifier.rb +74 -6
- data/lib/pubid/iana/identifiers/registry.rb +36 -0
- data/lib/pubid/iana/parser.rb +1 -1
- data/lib/pubid/iana/renderer.rb +3 -0
- data/lib/pubid/iana/urn_generator.rb +5 -1
- data/lib/pubid/iana.rb +1 -0
- data/lib/pubid/identifier.rb +594 -10
- data/lib/pubid/identifier_metadata.rb +1 -0
- data/lib/pubid/idf/builder.rb +3 -3
- data/lib/pubid/idf/identifier.rb +18 -9
- data/lib/pubid/idf/parser.rb +1 -1
- data/lib/pubid/idf/renderer.rb +4 -4
- data/lib/pubid/idf/urn_generator.rb +1 -1
- data/lib/pubid/idf.rb +7 -1
- data/lib/pubid/iec/builder.rb +14 -7
- data/lib/pubid/iec/components.rb +0 -1
- data/lib/pubid/iec/identifier.rb +73 -83
- data/lib/pubid/iec/identifiers/amendment.rb +6 -2
- data/lib/pubid/iec/identifiers/component_specification.rb +0 -10
- data/lib/pubid/iec/identifiers/conformity_assessment.rb +0 -10
- data/lib/pubid/iec/identifiers/corrigendum.rb +2 -2
- data/lib/pubid/iec/identifiers/fragment_identifier.rb +2 -4
- data/lib/pubid/iec/identifiers/guide.rb +0 -16
- data/lib/pubid/iec/identifiers/international_standard.rb +15 -2
- data/lib/pubid/iec/identifiers/operational_document.rb +0 -10
- data/lib/pubid/iec/identifiers/publicly_available_specification.rb +0 -12
- data/lib/pubid/iec/identifiers/societal_technology_trend_report.rb +0 -10
- data/lib/pubid/iec/identifiers/systems_reference_document.rb +0 -10
- data/lib/pubid/iec/identifiers/technical_report.rb +0 -17
- data/lib/pubid/iec/identifiers/technical_specification.rb +0 -17
- data/lib/pubid/iec/identifiers/technology_report.rb +0 -10
- data/lib/pubid/iec/identifiers/test_report_form.rb +0 -11
- data/lib/pubid/iec/identifiers/white_paper.rb +0 -10
- data/lib/pubid/iec/identifiers/working_document.rb +24 -10
- data/lib/pubid/iec/parser.rb +2 -18
- data/lib/pubid/iec/renderer.rb +13 -10
- data/lib/pubid/iec/single_identifier.rb +33 -10
- data/lib/pubid/iec/urn_generator.rb +227 -61
- data/lib/pubid/iec/urn_parser.rb +42 -4
- data/lib/pubid/iec.rb +1 -0
- data/lib/pubid/ieee/aiee/identifier.rb +2 -2
- data/lib/pubid/ieee/aiee/parser.rb +1 -1
- data/lib/pubid/ieee/builder.rb +45 -1
- data/lib/pubid/ieee/identifiers/adopted_standard.rb +32 -0
- data/lib/pubid/ieee/identifiers/base.rb +42 -5
- data/lib/pubid/ieee/identifiers/csa_dual_published.rb +21 -0
- data/lib/pubid/ieee/identifiers/dual_published.rb +55 -0
- data/lib/pubid/ieee/identifiers/interpretation_identifier.rb +23 -0
- data/lib/pubid/ieee/identifiers/joint_development.rb +11 -7
- data/lib/pubid/ieee/identifiers/multi_numbered_identifier.rb +57 -5
- data/lib/pubid/ieee/identifiers/nesc/base.rb +2 -2
- data/lib/pubid/ieee/identifiers/nesc/draft.rb +2 -2
- data/lib/pubid/ieee/identifiers/nesc/handbook.rb +2 -2
- data/lib/pubid/ieee/identifiers/nesc/redline.rb +2 -2
- data/lib/pubid/ieee/identifiers/nesc/standard.rb +2 -2
- data/lib/pubid/ieee/ire/identifier.rb +2 -2
- data/lib/pubid/ieee/ire/parser.rb +1 -1
- data/lib/pubid/ieee/nesc/parser.rb +1 -1
- data/lib/pubid/ieee/parser.rb +1 -1
- data/lib/pubid/ieee/renderer.rb +5 -1
- data/lib/pubid/ieee/urn_generator.rb +32 -3
- data/lib/pubid/ieee.rb +7 -1
- data/lib/pubid/ieee_debug.rb +1 -0
- data/lib/pubid/ietf/builder.rb +24 -8
- data/lib/pubid/ietf/identifiers/base.rb +25 -28
- data/lib/pubid/ietf/identifiers/bcp.rb +11 -0
- data/lib/pubid/ietf/identifiers/fyi.rb +11 -0
- data/lib/pubid/ietf/identifiers/internet_draft.rb +18 -2
- data/lib/pubid/ietf/identifiers/rfc.rb +2 -0
- data/lib/pubid/ietf/identifiers/serialization.rb +51 -0
- data/lib/pubid/ietf/identifiers/std.rb +11 -0
- data/lib/pubid/ietf/identifiers.rb +1 -0
- data/lib/pubid/ietf/parser.rb +27 -9
- data/lib/pubid/ietf/renderer.rb +44 -6
- data/lib/pubid/ietf/urn_generator.rb +20 -6
- data/lib/pubid/ietf/urn_parser.rb +10 -2
- data/lib/pubid/ietf.rb +12 -2
- data/lib/pubid/iho/identifiers/base.rb +10 -3
- data/lib/pubid/iho/parser.rb +1 -1
- data/lib/pubid/iho.rb +1 -0
- data/lib/pubid/isbn/identifier.rb +25 -7
- data/lib/pubid/isbn/parser.rb +1 -1
- data/lib/pubid/isbn.rb +1 -0
- data/lib/pubid/iso/bundled_identifier.rb +5 -3
- data/lib/pubid/iso/combined_identifier.rb +5 -3
- data/lib/pubid/iso/identifier.rb +12 -7
- data/lib/pubid/iso/identifiers/directives_supplement.rb +4 -4
- data/lib/pubid/iso/parser.rb +1 -1
- data/lib/pubid/iso.rb +7 -1
- data/lib/pubid/itu/identifiers/addendum.rb +2 -2
- data/lib/pubid/itu/identifiers/amendment.rb +2 -2
- data/lib/pubid/itu/identifiers/base.rb +19 -5
- data/lib/pubid/itu/identifiers/corrigendum.rb +2 -2
- data/lib/pubid/itu/identifiers/errata.rb +2 -2
- data/lib/pubid/itu/identifiers/supplement.rb +2 -2
- data/lib/pubid/itu/parser.rb +1 -1
- data/lib/pubid/itu.rb +1 -0
- data/lib/pubid/jcgm/builder.rb +1 -1
- data/lib/pubid/jcgm/identifier.rb +10 -0
- data/lib/pubid/jcgm/identifiers/meeting.rb +1 -1
- data/lib/pubid/jcgm/parser.rb +10 -3
- data/lib/pubid/jcgm/renderer.rb +10 -3
- data/lib/pubid/jcgm/single_identifier.rb +24 -15
- data/lib/pubid/jcgm/urn_generator.rb +1 -1
- data/lib/pubid/jcgm/urn_parser.rb +156 -14
- data/lib/pubid/jcgm.rb +10 -0
- data/lib/pubid/jis/identifier.rb +10 -3
- data/lib/pubid/jis/parser.rb +1 -1
- data/lib/pubid/jis.rb +1 -0
- data/lib/pubid/nist/components/stage.rb +2 -2
- data/lib/pubid/nist/configuration.rb +6 -8
- data/lib/pubid/nist/identifiers/base.rb +12 -2
- data/lib/pubid/nist/identifiers/circular.rb +9 -2
- data/lib/pubid/nist/identifiers/circular_supplement.rb +14 -5
- data/lib/pubid/nist/identifiers/commercial_standards_monthly.rb +7 -1
- data/lib/pubid/nist/identifiers/crpl_report.rb +7 -1
- data/lib/pubid/nist/identifiers/handbook.rb +9 -2
- data/lib/pubid/nist/identifiers/internal_report.rb +12 -5
- data/lib/pubid/nist/identifiers/miscellaneous_publication.rb +14 -6
- data/lib/pubid/nist/identifiers/monograph.rb +14 -7
- data/lib/pubid/nist/identifiers/report.rb +14 -6
- data/lib/pubid/nist/parser.rb +1 -1
- data/lib/pubid/nist/supplement_identifier.rb +16 -1
- data/lib/pubid/nist.rb +7 -1
- data/lib/pubid/oasis/builder.rb +12 -10
- data/lib/pubid/oasis/identifier.rb +89 -11
- data/lib/pubid/oasis/parser.rb +1 -1
- data/lib/pubid/oasis.rb +7 -1
- data/lib/pubid/ogc/identifier.rb +9 -5
- data/lib/pubid/ogc/parser.rb +1 -1
- data/lib/pubid/ogc.rb +1 -0
- data/lib/pubid/oiml/builder.rb +5 -1
- data/lib/pubid/oiml/identifiers/basic_publication.rb +2 -0
- data/lib/pubid/oiml/identifiers/bulletin.rb +36 -0
- data/lib/pubid/oiml/identifiers/code_number.rb +90 -0
- data/lib/pubid/oiml/identifiers/document.rb +2 -0
- data/lib/pubid/oiml/identifiers/expert_report.rb +2 -0
- data/lib/pubid/oiml/identifiers/guide.rb +2 -0
- data/lib/pubid/oiml/identifiers/recommendation.rb +2 -0
- data/lib/pubid/oiml/identifiers/seminar_report.rb +2 -0
- data/lib/pubid/oiml/identifiers/vocabulary.rb +2 -0
- data/lib/pubid/oiml/identifiers.rb +1 -0
- data/lib/pubid/oiml/parser.rb +1 -1
- data/lib/pubid/oiml/single_identifier.rb +26 -42
- data/lib/pubid/oiml/supplement_identifier.rb +27 -0
- data/lib/pubid/oiml.rb +7 -1
- data/lib/pubid/omg/builder.rb +1 -0
- data/lib/pubid/omg/identifier.rb +20 -3
- data/lib/pubid/omg/parser.rb +64 -11
- data/lib/pubid/omg/renderer.rb +13 -1
- data/lib/pubid/omg.rb +2 -1
- data/lib/pubid/parser/grammar.rb +74 -0
- data/lib/pubid/parser.rb +2 -0
- data/lib/pubid/parsers/mr_string.rb +19 -0
- data/lib/pubid/plateau/parser.rb +1 -1
- data/lib/pubid/plateau.rb +10 -0
- data/lib/pubid/prefixes_support.rb +1 -0
- data/lib/pubid/renderers/annotator.rb +233 -0
- data/lib/pubid/renderers/base.rb +13 -0
- data/lib/pubid/renderers/directives_renderer.rb +3 -3
- data/lib/pubid/renderers/human_readable.rb +3 -3
- data/lib/pubid/renderers/mr_string.rb +15 -9
- data/lib/pubid/renderers.rb +1 -0
- data/lib/pubid/rendering/numbering.rb +25 -7
- data/lib/pubid/rendering.rb +1 -0
- data/lib/pubid/sae/identifiers/base.rb +9 -2
- data/lib/pubid/sae/parser.rb +1 -1
- data/lib/pubid/sae.rb +1 -0
- data/lib/pubid/schema/declaration.rb +33 -0
- data/lib/pubid/schema/error.rb +14 -0
- data/lib/pubid/schema/identifier_type.rb +23 -0
- data/lib/pubid/schema/loader.rb +117 -0
- data/lib/pubid/schema/typed_stage.rb +24 -0
- data/lib/pubid/schema.rb +25 -0
- data/lib/pubid/tgpp/builder.rb +1 -1
- data/lib/pubid/tgpp/identifier.rb +21 -5
- data/lib/pubid/tgpp/identifiers/technical_report.rb +2 -2
- data/lib/pubid/tgpp/identifiers/technical_specification.rb +2 -2
- data/lib/pubid/tgpp/parser.rb +22 -6
- data/lib/pubid/tgpp/renderer.rb +21 -5
- data/lib/pubid/tgpp/urn_generator.rb +27 -8
- data/lib/pubid/tgpp/urn_parser.rb +8 -6
- data/lib/pubid/tgpp.rb +7 -1
- data/lib/pubid/type_resolver.rb +16 -1
- data/lib/pubid/un/identifier.rb +6 -3
- data/lib/pubid/un/parser.rb +1 -1
- data/lib/pubid/un.rb +1 -0
- data/lib/pubid/urn_parser/errors.rb +8 -1
- data/lib/pubid/urn_parser.rb +1 -0
- data/lib/pubid/utils.rb +1 -0
- data/lib/pubid/version.rb +1 -1
- data/lib/pubid/w3c/builder.rb +5 -5
- data/lib/pubid/w3c/identifier.rb +38 -9
- data/lib/pubid/w3c/parser.rb +1 -1
- data/lib/pubid/w3c/renderer.rb +1 -1
- data/lib/pubid/w3c/urn_generator.rb +2 -2
- data/lib/pubid/w3c.rb +1 -0
- data/lib/pubid/xsf/identifier.rb +9 -5
- data/lib/pubid/xsf/parser.rb +17 -4
- data/lib/pubid/xsf.rb +7 -1
- data/lib/pubid.rb +399 -21
- data/lib/tasks/conformance.rake +34 -0
- data/lib/tasks/docs.rake +3 -3
- data/lib/tasks/schema.rake +88 -0
- data/schema/core/joint_prefixes.yaml +24 -0
- data/schema/iec.yaml +1017 -0
- data/schema/iso.yaml +1586 -0
- data/schema/schema.schema.yaml +96 -0
- metadata +38 -17
- data/archived-gems/pubid-ccsds/update_codes.yaml +0 -1
- data/archived-gems/pubid-iec/stages.yaml +0 -129
- data/archived-gems/pubid-iec/update_codes.yaml +0 -67
- data/archived-gems/pubid-ieee/update_codes.yaml +0 -104
- data/archived-gems/pubid-iso/stages.yaml +0 -106
- data/archived-gems/pubid-iso/update_codes.yaml +0 -4
- data/archived-gems/pubid-itu/i18n.yaml +0 -13
- data/archived-gems/pubid-itu/series.yaml +0 -42
- data/archived-gems/pubid-nist/publishers.yaml +0 -6
- data/archived-gems/pubid-nist/series.yaml +0 -121
- data/archived-gems/pubid-nist/update_codes.yaml +0 -93
- data/archived-gems/pubid-plateau/update_codes.yaml +0 -6
- data/lib/pubid/cen_cenelec/supplement_identifier.rb +0 -48
- data/lib/pubid/iec/components/code.rb +0 -36
- /data/{archived-gems/pubid-nist → data/nist}/stages.yaml +0 -0
|
@@ -5,16 +5,23 @@ require "lutaml/model"
|
|
|
5
5
|
module Pubid
|
|
6
6
|
module Csa
|
|
7
7
|
module Identifiers
|
|
8
|
-
#
|
|
8
|
+
# Combined represents CSA identifiers joined with "/" or ", "
|
|
9
9
|
# Examples:
|
|
10
10
|
# CSA A23.1:24/CSA A23.2:24
|
|
11
11
|
# CSA N285.0:23/CSA N285.6 SERIES:23
|
|
12
12
|
# CSA A123.1-05/A123.5-05 (R2015)
|
|
13
13
|
# CSA B44:19/B44.1:19/B44.2:19 (triple combined)
|
|
14
|
-
class Combined <
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
14
|
+
class Combined < Identifier
|
|
15
|
+
# The co-equal designations, in printed order.
|
|
16
|
+
#
|
|
17
|
+
# One polymorphic collection, the IEC ConsolidatedIdentifier shape —
|
|
18
|
+
# not the historical first/second/third triple, which hard-capped the
|
|
19
|
+
# form at three and froze a non-standard hash shape. The first member
|
|
20
|
+
# is the primary designation, which is what #root walks so the index
|
|
21
|
+
# key is non-empty. Typed cross-flavor for the same reason as
|
|
22
|
+
# WrapperIdentifier#base.
|
|
23
|
+
attribute :identifiers, ::Pubid::Identifier, polymorphic: true,
|
|
24
|
+
collection: true
|
|
18
25
|
attribute :reaffirmation, :string
|
|
19
26
|
attribute :original_reaffirmation_4digit, :boolean, default: -> {
|
|
20
27
|
false
|
|
@@ -23,67 +30,74 @@ module Pubid
|
|
|
23
30
|
attribute :year_format, :string # Dummy for compatibility
|
|
24
31
|
attribute :separator, :string, default: -> { "/" } # "/" or ", "
|
|
25
32
|
|
|
26
|
-
#
|
|
27
|
-
#
|
|
33
|
+
# A combined id stores its members in `identifiers`, not `base`, so
|
|
34
|
+
# walk the primary designation to the origin document
|
|
35
|
+
# (Iec::Identifiers::ConsolidatedIdentifier does the same).
|
|
28
36
|
def root
|
|
29
|
-
self
|
|
37
|
+
identifiers&.first&.root || self
|
|
30
38
|
end
|
|
31
39
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
parts = [first.to_s, second.to_s]
|
|
38
|
-
parts << third.to_s if third
|
|
39
|
-
else
|
|
40
|
-
# Slash: Second and third without CSA prefix (continuation)
|
|
41
|
-
parts = [first.to_s]
|
|
42
|
-
parts << render_continuation(second)
|
|
43
|
-
parts << render_continuation(third) if third
|
|
44
|
-
end
|
|
45
|
-
|
|
46
|
-
result = parts.join(separator || "/")
|
|
40
|
+
# Co-equal designations, so both matching primitives reduce to the
|
|
41
|
+
# primary one — the Iec::Identifiers::ConsolidatedIdentifier shape.
|
|
42
|
+
def base_document
|
|
43
|
+
identifiers&.first&.base_document || self
|
|
44
|
+
end
|
|
47
45
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
# to determine spacing
|
|
52
|
-
year_was_2digit = first.class.attributes.key?(:original_year_4digit) && !first.original_year_4digit
|
|
53
|
-
|
|
54
|
-
# Check if reaffirmation was originally 4-digit
|
|
55
|
-
# Note: We need to track this at the Combined level, but for now
|
|
56
|
-
# assume 4-digit if the value is 4 digits and starts with 19/20
|
|
57
|
-
reaffirmation_was_4digit = reaffirmation.to_s.length == 4 &&
|
|
58
|
-
reaffirmation.to_s.start_with?("19", "20")
|
|
59
|
-
|
|
60
|
-
# Determine spacing based on original formats
|
|
61
|
-
# Space needed if year is 2-digit and reaffirmation is 4-digit
|
|
62
|
-
result += if year_was_2digit && reaffirmation_was_4digit
|
|
63
|
-
" (R#{reaffirmation})"
|
|
64
|
-
else
|
|
65
|
-
"(R#{reaffirmation})"
|
|
66
|
-
end
|
|
67
|
-
end
|
|
46
|
+
def drop_supplements
|
|
47
|
+
identifiers&.first || self
|
|
48
|
+
end
|
|
68
49
|
|
|
50
|
+
def to_s(**opts)
|
|
51
|
+
parts = render_parts
|
|
52
|
+
result = parts.join(separator || "/")
|
|
53
|
+
result += render_reaffirmation if reaffirmation
|
|
69
54
|
result += package if package
|
|
70
|
-
result
|
|
55
|
+
annotate_plain_render(result, **opts)
|
|
71
56
|
end
|
|
72
57
|
|
|
73
58
|
private
|
|
74
59
|
|
|
60
|
+
# With a comma separator every designation carries its full prefix;
|
|
61
|
+
# with a slash the trailing ones are continuations printed bare.
|
|
62
|
+
def render_parts
|
|
63
|
+
return identifiers.map(&:to_s) if separator == ", "
|
|
64
|
+
|
|
65
|
+
identifiers.each_with_index.map do |identifier, index|
|
|
66
|
+
index.zero? ? identifier.to_s : render_continuation(identifier)
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
# Reaffirmation - preserve original format and determine spacing.
|
|
71
|
+
# A space is needed when the year was printed 2-digit and the
|
|
72
|
+
# reaffirmation 4-digit; the year format comes from the primary
|
|
73
|
+
# designation.
|
|
74
|
+
def render_reaffirmation
|
|
75
|
+
primary = identifiers&.first
|
|
76
|
+
year_was_2digit =
|
|
77
|
+
primary &&
|
|
78
|
+
primary.class.attributes.key?(:original_year_4digit) &&
|
|
79
|
+
!primary.original_year_4digit
|
|
80
|
+
|
|
81
|
+
reaffirmation_was_4digit = reaffirmation.to_s.length == 4 &&
|
|
82
|
+
reaffirmation.to_s.start_with?("19", "20")
|
|
83
|
+
|
|
84
|
+
if year_was_2digit && reaffirmation_was_4digit
|
|
85
|
+
" (R#{reaffirmation})"
|
|
86
|
+
else
|
|
87
|
+
"(R#{reaffirmation})"
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
|
|
75
91
|
# Render identifier without CSA prefix (unless has_publisher is true)
|
|
76
92
|
def render_continuation(identifier)
|
|
77
93
|
parts = []
|
|
78
94
|
|
|
79
95
|
# Add CSA prefix if present in original
|
|
80
96
|
if identifier.has_publisher
|
|
81
|
-
|
|
82
|
-
!prefix.end_with?("-")
|
|
83
|
-
parts << prefix
|
|
97
|
+
parts << (identifier.publisher_prefix || "CSA")
|
|
84
98
|
end
|
|
85
99
|
|
|
86
|
-
code_part = identifier.
|
|
100
|
+
code_part = identifier.number.to_s if identifier.number
|
|
87
101
|
|
|
88
102
|
# NO. keyword
|
|
89
103
|
if identifier.no_number
|
|
@@ -98,34 +112,42 @@ module Pubid
|
|
|
98
112
|
code_part += " SERIES"
|
|
99
113
|
end
|
|
100
114
|
|
|
101
|
-
|
|
102
|
-
if identifier.year
|
|
103
|
-
separator = identifier.year_format == "dash" ? "-" : ":"
|
|
104
|
-
year_part = separator
|
|
105
|
-
year_part += identifier.year_prefix if identifier.year_prefix # Add M or F prefix
|
|
106
|
-
year_part += "F" if identifier.french && identifier.year_format != "dash" && !identifier.year_prefix # Only add F if no prefix
|
|
107
|
-
# Convert 4-digit year back to 2-digit
|
|
108
|
-
year_str = identifier.year.to_s
|
|
109
|
-
year_part += if year_str.length == 4 && year_str.start_with?("20")
|
|
110
|
-
year_str[2..3]
|
|
111
|
-
else
|
|
112
|
-
year_str
|
|
113
|
-
end
|
|
114
|
-
code_part += year_part
|
|
115
|
-
end
|
|
115
|
+
code_part += render_continuation_year(identifier) if identifier.year
|
|
116
116
|
|
|
117
117
|
parts << code_part if code_part
|
|
118
118
|
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
119
|
+
join_continuation(identifier, parts)
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
# Year with proper format (colon or dash)
|
|
123
|
+
def render_continuation_year(identifier)
|
|
124
|
+
separator = identifier.year_format == "dash" ? "-" : ":"
|
|
125
|
+
year_part = separator
|
|
126
|
+
# Add M or F prefix
|
|
127
|
+
year_part += identifier.year_prefix if identifier.year_prefix
|
|
128
|
+
# Only add F if no prefix
|
|
129
|
+
if identifier.french && identifier.year_format != "dash" &&
|
|
130
|
+
!identifier.year_prefix
|
|
131
|
+
year_part += "F"
|
|
132
|
+
end
|
|
133
|
+
# Convert 4-digit year back to 2-digit
|
|
134
|
+
year_str = identifier.year.to_s
|
|
135
|
+
year_part + if year_str.length == 4 && year_str.start_with?("20")
|
|
136
|
+
year_str[2..3]
|
|
137
|
+
else
|
|
138
|
+
year_str
|
|
139
|
+
end
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
# Join with proper spacing based on prefix
|
|
143
|
+
def join_continuation(identifier, parts)
|
|
144
|
+
return parts.join(" ") unless identifier.has_publisher &&
|
|
145
|
+
parts.length > 1
|
|
146
|
+
|
|
147
|
+
prefix = parts[0]
|
|
148
|
+
if prefix.end_with?("-")
|
|
149
|
+
# No space after dash-ending prefix
|
|
150
|
+
prefix + parts[1..].join(" ")
|
|
129
151
|
else
|
|
130
152
|
parts.join(" ")
|
|
131
153
|
end
|
|
@@ -18,16 +18,16 @@ module Pubid
|
|
|
18
18
|
#
|
|
19
19
|
# This is a wrapper pattern where:
|
|
20
20
|
# - CSA prefix indicates adoption
|
|
21
|
-
# - The
|
|
21
|
+
# - The base is the external standard (ISO/IEC/CISPR)
|
|
22
22
|
# - Wrapped identifier is recursively parsed using external flavor parsers
|
|
23
23
|
class CsaAdopted < WrapperIdentifier
|
|
24
24
|
# Publisher prefix (e.g., "CSA-", "CAN3-") for rendering
|
|
25
25
|
# When set, uses dash format without space (e.g., "CSA-ISO" not "CSA ISO")
|
|
26
26
|
attribute :publisher_prefix, :string
|
|
27
27
|
|
|
28
|
-
def to_s
|
|
28
|
+
def to_s(**opts)
|
|
29
29
|
# Get string representation from wrapped identifier
|
|
30
|
-
base_str =
|
|
30
|
+
base_str = base.to_s
|
|
31
31
|
|
|
32
32
|
# Convert 4-digit years to 2-digit for CSA adoption format
|
|
33
33
|
# ISO/IEC TR 12785-3:2015 → ISO/IEC TR 12785-3:15
|
|
@@ -70,7 +70,7 @@ module Pubid
|
|
|
70
70
|
# Append reaffirmation if present
|
|
71
71
|
result += " (R#{reaffirmation})" if reaffirmation
|
|
72
72
|
|
|
73
|
-
result
|
|
73
|
+
annotate_plain_render(result, **opts)
|
|
74
74
|
end
|
|
75
75
|
end
|
|
76
76
|
end
|
|
@@ -33,7 +33,7 @@ module Pubid
|
|
|
33
33
|
# false = materials BEFORE: "CSA B149.1:25 Code, Handbook & Training Package"
|
|
34
34
|
attribute :materials_after_keyword, :boolean, default: -> { true }
|
|
35
35
|
|
|
36
|
-
def to_s
|
|
36
|
+
def to_s(**opts)
|
|
37
37
|
result = base.to_s
|
|
38
38
|
|
|
39
39
|
# Add package materials if present
|
|
@@ -57,7 +57,7 @@ module Pubid
|
|
|
57
57
|
result += " PACKAGE"
|
|
58
58
|
end
|
|
59
59
|
|
|
60
|
-
result
|
|
60
|
+
annotate_plain_render(result, **opts)
|
|
61
61
|
end
|
|
62
62
|
end
|
|
63
63
|
end
|
data/lib/pubid/csa/parser.rb
CHANGED
|
@@ -4,7 +4,7 @@ require "parslet"
|
|
|
4
4
|
|
|
5
5
|
module Pubid
|
|
6
6
|
module Csa
|
|
7
|
-
class Parser <
|
|
7
|
+
class Parser < ::Pubid::Parser::Grammar
|
|
8
8
|
# Basic building blocks
|
|
9
9
|
rule(:space) { str(" ") }
|
|
10
10
|
rule(:dash) { str("-") }
|
|
@@ -367,7 +367,11 @@ module Pubid
|
|
|
367
367
|
# Preprocessing to normalize input
|
|
368
368
|
def parse(input)
|
|
369
369
|
# Skip comment lines
|
|
370
|
-
|
|
370
|
+
if input.strip.start_with?("#")
|
|
371
|
+
raise Pubid::Errors::ParseError.new(
|
|
372
|
+
"Comment line", input: input, flavor: "csa"
|
|
373
|
+
)
|
|
374
|
+
end
|
|
371
375
|
|
|
372
376
|
# Remove CONSOLIDATED notation FIRST (before other processing)
|
|
373
377
|
normalized = input.gsub(/\s*\(\s*CONSOLIDATED\s*\)\s*/, " ")
|
data/lib/pubid/csa/renderer.rb
CHANGED
|
@@ -35,7 +35,7 @@ module Pubid
|
|
|
35
35
|
|
|
36
36
|
# Base rendering: "CSA B149.1:20", "CAN/CSA-C22.2-05"
|
|
37
37
|
def render_base(id)
|
|
38
|
-
prefix = id
|
|
38
|
+
prefix = publisher_prefix_for(id)
|
|
39
39
|
|
|
40
40
|
# Handle code_only identifiers (empty string means no prefix)
|
|
41
41
|
if prefix == ""
|
|
@@ -51,7 +51,7 @@ module Pubid
|
|
|
51
51
|
end
|
|
52
52
|
|
|
53
53
|
# Code and year together
|
|
54
|
-
code_part = id.
|
|
54
|
+
code_part = id.number.to_s if id.number
|
|
55
55
|
|
|
56
56
|
# NO. keyword
|
|
57
57
|
if id.no_number
|
|
@@ -131,7 +131,7 @@ module Pubid
|
|
|
131
131
|
parts = []
|
|
132
132
|
|
|
133
133
|
# Publisher prefix (CSA, CAN/CSA-, CAN3-)
|
|
134
|
-
prefix = id
|
|
134
|
+
prefix = publisher_prefix_for(id)
|
|
135
135
|
|
|
136
136
|
# Determine if we need space after prefix
|
|
137
137
|
# CAN/CSA- and CAN3- end with dash, so no space needed
|
|
@@ -203,7 +203,7 @@ module Pubid
|
|
|
203
203
|
result = series_publisher_prefix_portion(id)
|
|
204
204
|
|
|
205
205
|
# Add code FIRST (before SERIES keyword)
|
|
206
|
-
result += id.
|
|
206
|
+
result += id.number.to_s
|
|
207
207
|
|
|
208
208
|
# Add space before series prefix/SERIES keyword
|
|
209
209
|
result += " "
|
|
@@ -255,8 +255,16 @@ module Pubid
|
|
|
255
255
|
end
|
|
256
256
|
end
|
|
257
257
|
|
|
258
|
+
# The publisher prefix to print. A code_only identifier printed none, so
|
|
259
|
+
# it must not gain the default "CSA" — see SingleIdentifier#code_only.
|
|
260
|
+
def publisher_prefix_for(id)
|
|
261
|
+
return "" if id.respond_to?(:code_only) && id.code_only
|
|
262
|
+
|
|
263
|
+
id.publisher_prefix || "CSA"
|
|
264
|
+
end
|
|
265
|
+
|
|
258
266
|
def series_publisher_prefix_portion(id)
|
|
259
|
-
prefix = id
|
|
267
|
+
prefix = publisher_prefix_for(id)
|
|
260
268
|
|
|
261
269
|
# Handle code_only identifiers (empty string means no prefix)
|
|
262
270
|
return "" if prefix == ""
|
|
@@ -3,11 +3,18 @@
|
|
|
3
3
|
module Pubid
|
|
4
4
|
module Csa
|
|
5
5
|
class SingleIdentifier < Identifier
|
|
6
|
-
#
|
|
6
|
+
# The document code — "B149.1", "Z240", "C22.2" — and the relaton index
|
|
7
|
+
# key: Relaton::Index sorts and bsearches every row on
|
|
8
|
+
# `id.root.number.to_s`, so it must never be empty.
|
|
7
9
|
#
|
|
8
|
-
#
|
|
9
|
-
|
|
10
|
-
|
|
10
|
+
# It is the `number` INHERITED from ::Pubid::Identifier, not a
|
|
11
|
+
# redeclaration: Pubid::Csa::Components::Code is a bare alias of
|
|
12
|
+
# Pubid::Components::Code, which is exactly the parent's declared type.
|
|
13
|
+
# That matters. CSA's base is split across two files (csa/identifier.rb +
|
|
14
|
+
# csa/single_identifier.rb) — the IEEE shape in which a leaf can snapshot
|
|
15
|
+
# a half-built parent attribute table (CLAUDE.md, the `number`
|
|
16
|
+
# determinism landmine). Declaring nothing here keeps CSA clear of it.
|
|
17
|
+
# The attribute was named `code` before; there is no alias.
|
|
11
18
|
attribute :no_number, :string
|
|
12
19
|
attribute :year, :string
|
|
13
20
|
attribute :year_format, :string # "colon" or "dash"
|
|
@@ -25,6 +32,88 @@ module Pubid
|
|
|
25
32
|
attribute :series, :boolean # Track if SERIES keyword present
|
|
26
33
|
attribute :package, :string # Package portion (Code, Handbook, etc.)
|
|
27
34
|
attribute :publisher_prefix, :string # Original prefix: "CAN/CSA-", "CSA", "CAN3-"
|
|
35
|
+
|
|
36
|
+
# True when the reference printed no publisher at all ("C22.1-15"), so
|
|
37
|
+
# rendering must not supply the default "CSA".
|
|
38
|
+
#
|
|
39
|
+
# This used to be an empty-string `publisher_prefix` sentinel, which the
|
|
40
|
+
# canonical `to_hash` drops (it strips empty and default-valued
|
|
41
|
+
# attributes by design) — so a code-only identifier came back
|
|
42
|
+
# from `from_hash` with a nil prefix and re-rendered as
|
|
43
|
+
# "CSA C22.1-15". Named for the RARE case with a `false` default,
|
|
44
|
+
# per CLAUDE.md, so it is dropped from every ordinary row.
|
|
45
|
+
attribute :code_only, :boolean, default: -> { false }
|
|
46
|
+
|
|
47
|
+
# A flat, index-friendly serialized shape: the `Components::Code`
|
|
48
|
+
# attributes collapse to bare scalars (`number: C22.2-286`, not
|
|
49
|
+
# `number: {value: C22.2-286}`), the ISO/ETSI/ITU `key_value` pattern.
|
|
50
|
+
#
|
|
51
|
+
# This is deliberately a serialization mapping rather than an
|
|
52
|
+
# `attribute :number, :string` redeclaration. CSA's base is split across
|
|
53
|
+
# two files (csa/identifier.rb + csa/single_identifier.rb) — the IEEE
|
|
54
|
+
# shape in which a leaf can snapshot a half-built parent attribute table
|
|
55
|
+
# — so a retype here would reintroduce the `number` determinism landmine
|
|
56
|
+
# recorded in CLAUDE.md. The runtime attribute stays a Components::Code;
|
|
57
|
+
# only the hash is flat.
|
|
58
|
+
#
|
|
59
|
+
# A lutaml key_value block is EXHAUSTIVE — an unmapped attribute is
|
|
60
|
+
# dropped, `_type` included — so every attribute above appears here. It
|
|
61
|
+
# lives on SingleIdentifier, which only the single-document types
|
|
62
|
+
# inherit; the container types descend from Csa::Identifier directly and
|
|
63
|
+
# keep the default shape for their nested `base`/`identifiers`.
|
|
64
|
+
key_value do
|
|
65
|
+
map "_type", to: :_type
|
|
66
|
+
map "number", with: { to: :number_to_kv, from: :number_from_kv }
|
|
67
|
+
map "no_number",
|
|
68
|
+
with: { to: :no_number_to_kv, from: :no_number_from_kv }
|
|
69
|
+
map "year", to: :year
|
|
70
|
+
map "year_format", to: :year_format
|
|
71
|
+
map "year_prefix", to: :year_prefix
|
|
72
|
+
map "original_year_4digit", to: :original_year_4digit
|
|
73
|
+
map "french", to: :french
|
|
74
|
+
map "reaffirmation", to: :reaffirmation
|
|
75
|
+
map "original_reaffirmation_4digit", to: :original_reaffirmation_4digit
|
|
76
|
+
map "has_publisher", to: :has_publisher
|
|
77
|
+
map "series_prefix", to: :series_prefix
|
|
78
|
+
map "series", to: :series
|
|
79
|
+
map "package", to: :package
|
|
80
|
+
map "publisher_prefix", to: :publisher_prefix
|
|
81
|
+
map "code_only", to: :code_only
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
def number_to_kv(model, doc)
|
|
85
|
+
emit_kv(doc, "number", model.number)
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
def number_from_kv(model, value)
|
|
89
|
+
model.number = Components::Code.new(value: value.to_s)
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
# `no_number` is a plain :string here but a Components::Code on Cec, so
|
|
93
|
+
# the converter reads through whichever it is given.
|
|
94
|
+
def no_number_to_kv(model, doc)
|
|
95
|
+
emit_kv(doc, "no_number", model.no_number)
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
def no_number_from_kv(model, value)
|
|
99
|
+
model.no_number =
|
|
100
|
+
if model.class.attributes[:no_number].type == Components::Code
|
|
101
|
+
Components::Code.new(value: value.to_s)
|
|
102
|
+
else
|
|
103
|
+
value.to_s
|
|
104
|
+
end
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
# Emit a scalar, skipping a nil or empty value so the canonical
|
|
108
|
+
# no-defaults hash never gains an empty key.
|
|
109
|
+
def emit_kv(doc, key, value)
|
|
110
|
+
text = value.respond_to?(:value) ? value.value : value
|
|
111
|
+
return if text.nil? || text.to_s.empty?
|
|
112
|
+
|
|
113
|
+
doc.add_child(
|
|
114
|
+
Lutaml::KeyValue::DataModel::Element.new(key, text.to_s),
|
|
115
|
+
)
|
|
116
|
+
end
|
|
28
117
|
end
|
|
29
118
|
end
|
|
30
119
|
end
|
|
@@ -3,16 +3,23 @@
|
|
|
3
3
|
module Pubid
|
|
4
4
|
module Csa
|
|
5
5
|
class UrnGenerator < Pubid::UrnGenerator::Base
|
|
6
|
+
# A code_only identifier printed no publisher, so it keeps an empty
|
|
7
|
+
# publisher segment rather than falling back to "csa" in #generate.
|
|
6
8
|
def urn_publisher_prefix
|
|
9
|
+
return "" if code_only?
|
|
7
10
|
return nil unless identifier.publisher_prefix
|
|
8
11
|
|
|
9
12
|
identifier.publisher_prefix.to_s.downcase
|
|
10
13
|
end
|
|
11
14
|
|
|
15
|
+
def code_only?
|
|
16
|
+
identifier.respond_to?(:code_only) && identifier.code_only
|
|
17
|
+
end
|
|
18
|
+
|
|
12
19
|
def urn_number
|
|
13
|
-
return nil unless identifier.
|
|
20
|
+
return nil unless identifier.number
|
|
14
21
|
|
|
15
|
-
identifier.
|
|
22
|
+
identifier.number.render(context: URN_CONTEXT)
|
|
16
23
|
end
|
|
17
24
|
|
|
18
25
|
def urn_no_number
|
|
@@ -4,44 +4,60 @@ require "lutaml/model"
|
|
|
4
4
|
|
|
5
5
|
module Pubid
|
|
6
6
|
module Csa
|
|
7
|
-
# WrapperIdentifier is the base class for all CSA identifiers that wrap
|
|
7
|
+
# WrapperIdentifier is the base class for all CSA identifiers that wrap
|
|
8
|
+
# other identifiers.
|
|
8
9
|
# Examples:
|
|
9
|
-
# -
|
|
10
|
-
# -
|
|
10
|
+
# - CanadianAdopted: CAN/{base}
|
|
11
|
+
# - CsaAdopted: CSA {ISO/IEC/CISPR identifier}
|
|
11
12
|
#
|
|
12
|
-
# The wrapper pattern allows proper MODEL-DRIVEN architecture where
|
|
13
|
-
# are objects that contain other identifier objects, not string
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
#
|
|
17
|
-
|
|
13
|
+
# The wrapper pattern allows proper MODEL-DRIVEN architecture where
|
|
14
|
+
# adoptions are objects that contain other identifier objects, not string
|
|
15
|
+
# prefixes.
|
|
16
|
+
class WrapperIdentifier < Identifier
|
|
17
|
+
# The wrapped identifier (recursively parsed).
|
|
18
|
+
#
|
|
19
|
+
# A real lutaml attribute, not an attr_accessor: the accessor was
|
|
20
|
+
# invisible to `to_hash`, `from_hash` AND `#exclude` (which iterates
|
|
21
|
+
# `self.class.attributes`), so a wrapper serialized to a hash with no
|
|
22
|
+
# identifier in it at all. It is named `base` — the uniform parent
|
|
23
|
+
# accessor every flavor uses — so the inherited `#root` walks it to the
|
|
24
|
+
# origin document and `exclude_from_nested` reaches inside. There is no
|
|
25
|
+
# `wrapped_identifier` alias.
|
|
26
|
+
#
|
|
27
|
+
# Typed as the cross-flavor `::Pubid::Identifier`, not the CSA one:
|
|
28
|
+
# CsaAdopted wraps ISO/IEC/CISPR ids, and lutaml enforces the declared
|
|
29
|
+
# type — `polymorphic: true` widens it only to SUBCLASSES, so a narrower
|
|
30
|
+
# type raises Lutaml::Model::IncorrectModelError on `to_hash`. The
|
|
31
|
+
# Ieee::Identifiers::AdoptedStandard precedent. The nested child carries
|
|
32
|
+
# its own `_type`, so `from_hash` routes it back via TypeResolver.
|
|
33
|
+
attribute :base, ::Pubid::Identifier, polymorphic: true
|
|
18
34
|
|
|
19
35
|
# Reaffirmation year (common across wrappers)
|
|
20
36
|
attribute :reaffirmation, :string
|
|
21
37
|
|
|
38
|
+
# Whether the reaffirmation was printed 4-digit ("(R2004)") rather than
|
|
39
|
+
# 2-digit ("(R04)"). CanadianAdopted#to_s reads it to choose the spacing
|
|
40
|
+
# and to render the year back in its original width.
|
|
41
|
+
attribute :original_reaffirmation_4digit, :boolean, default: -> { false }
|
|
42
|
+
|
|
22
43
|
# Year format tracking (for compatibility)
|
|
23
44
|
attribute :year_format, :string
|
|
24
45
|
|
|
25
46
|
# Subclasses MUST implement to_s
|
|
26
|
-
def to_s
|
|
47
|
+
def to_s(**_opts)
|
|
27
48
|
raise NotImplementedError, "Subclasses must implement to_s method"
|
|
28
49
|
end
|
|
29
50
|
|
|
30
|
-
#
|
|
31
|
-
#
|
|
32
|
-
#
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
def to_slug
|
|
38
|
-
to_mr_string
|
|
51
|
+
# The matching primitives relaton uses to normalise a reference before
|
|
52
|
+
# comparing it. An adoption wrapper peels to the document it adopts;
|
|
53
|
+
# without these the inherited defaults return the WRAPPER, which is a
|
|
54
|
+
# silently wrong answer rather than a loud one.
|
|
55
|
+
def base_document
|
|
56
|
+
base ? base.base_document : self
|
|
39
57
|
end
|
|
40
58
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
def root
|
|
44
|
-
self
|
|
59
|
+
def drop_supplements
|
|
60
|
+
base || self
|
|
45
61
|
end
|
|
46
62
|
end
|
|
47
63
|
end
|
data/lib/pubid/csa.rb
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require "pubid"
|
|
3
4
|
module Pubid
|
|
4
5
|
module Csa
|
|
5
6
|
extend Pubid::PrefixesSupport
|
|
@@ -20,8 +21,13 @@ module Pubid
|
|
|
20
21
|
autoload :Components, "#{__dir__}/csa/components"
|
|
21
22
|
|
|
22
23
|
def self.parse(identifier_string)
|
|
24
|
+
unless identifier_string.is_a?(String)
|
|
25
|
+
raise Pubid::Errors::InvalidInputError,
|
|
26
|
+
Pubid::INPUT_NOT_A_STRING_MESSAGE
|
|
27
|
+
end
|
|
28
|
+
|
|
23
29
|
if identifier_string.length > Pubid::MAX_INPUT_LENGTH
|
|
24
|
-
raise
|
|
30
|
+
raise Pubid::Errors::InvalidInputError, Pubid::INPUT_TOO_LONG_MESSAGE
|
|
25
31
|
end
|
|
26
32
|
|
|
27
33
|
Identifier.parse(identifier_string)
|
data/lib/pubid/doi/identifier.rb
CHANGED
|
@@ -32,14 +32,17 @@ module Pubid
|
|
|
32
32
|
end
|
|
33
33
|
|
|
34
34
|
def self.parse(identifier)
|
|
35
|
+
unless identifier.is_a?(String)
|
|
36
|
+
raise Pubid::Errors::InvalidInputError,
|
|
37
|
+
Pubid::INPUT_NOT_A_STRING_MESSAGE
|
|
38
|
+
end
|
|
39
|
+
|
|
35
40
|
if identifier.length > Pubid::MAX_INPUT_LENGTH
|
|
36
|
-
raise
|
|
41
|
+
raise Pubid::Errors::InvalidInputError, Pubid::INPUT_TOO_LONG_MESSAGE
|
|
37
42
|
end
|
|
38
43
|
|
|
39
44
|
parsed = Parser.parse(identifier)
|
|
40
45
|
Builder.build(parsed)
|
|
41
|
-
rescue Parslet::ParseFailed => e
|
|
42
|
-
raise "Failed to parse DOI '#{identifier}': #{e.message}"
|
|
43
46
|
end
|
|
44
47
|
end
|
|
45
48
|
end
|
data/lib/pubid/doi/parser.rb
CHANGED
|
@@ -13,7 +13,7 @@ module Pubid
|
|
|
13
13
|
# SUFFIX is one-or-more chars from [A-Za-z0-9._\-/()] (printable minus
|
|
14
14
|
# whitespace). The grammar is intentionally permissive on suffix chars
|
|
15
15
|
# because real DOIs cover the full printable range.
|
|
16
|
-
class Parser <
|
|
16
|
+
class Parser < ::Pubid::Parser::Grammar
|
|
17
17
|
rule(:dot) { str(".") }
|
|
18
18
|
rule(:slash) { str("/") }
|
|
19
19
|
|
data/lib/pubid/doi.rb
CHANGED
|
@@ -30,8 +30,6 @@ module Pubid
|
|
|
30
30
|
def self.parse(identifier)
|
|
31
31
|
parsed = Parser.parse(identifier)
|
|
32
32
|
Builder.build(parsed)
|
|
33
|
-
rescue Parslet::ParseFailed => e
|
|
34
|
-
raise "Failed to parse EASC identifier '#{identifier}': #{e.message}"
|
|
35
33
|
end
|
|
36
34
|
|
|
37
35
|
attribute :publisher, :string, default: "EASC"
|
data/lib/pubid/easc/parser.rb
CHANGED
|
@@ -16,7 +16,7 @@ module Pubid
|
|
|
16
16
|
# Also accepts Latin transliterations (PMG, RMG, V) for
|
|
17
17
|
# round-tripping with English-language tooling. The renderer
|
|
18
18
|
# emits Cyrillic as the canonical form.
|
|
19
|
-
class Parser <
|
|
19
|
+
class Parser < ::Pubid::Parser::Grammar
|
|
20
20
|
include ::Pubid::Parser::CommonParseRules
|
|
21
21
|
|
|
22
22
|
root :identifier
|
|
@@ -71,7 +71,15 @@ module Pubid
|
|
|
71
71
|
end
|
|
72
72
|
|
|
73
73
|
def self.parse(string)
|
|
74
|
-
|
|
74
|
+
unless string.is_a?(String)
|
|
75
|
+
raise ::Pubid::Errors::InvalidInputError,
|
|
76
|
+
::Pubid::INPUT_NOT_A_STRING_MESSAGE
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
if string.length > ::Pubid::MAX_INPUT_LENGTH
|
|
80
|
+
raise ::Pubid::Errors::InvalidInputError,
|
|
81
|
+
::Pubid::INPUT_TOO_LONG_MESSAGE
|
|
82
|
+
end
|
|
75
83
|
|
|
76
84
|
new.parse(string.strip)
|
|
77
85
|
end
|