pubid 2.0.0.pre.alpha.8 → 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/data/bipm/update_codes.yaml +9 -0
- data/data/iec/update_codes.yaml +3 -0
- data/data/ieee/update_codes.yaml +107 -1
- data/{archived-gems/pubid-nist → data/nist}/series.yaml +34 -0
- data/data/nist/update_codes.yaml +8 -0
- data/lib/pubid/adobe/builder.rb +52 -0
- data/lib/pubid/adobe/identifier.rb +47 -0
- data/lib/pubid/adobe/identifiers/publication.rb +31 -0
- data/lib/pubid/adobe/identifiers/tech_note.rb +32 -0
- data/lib/pubid/adobe/identifiers.rb +10 -0
- data/lib/pubid/adobe/parser.rb +136 -0
- data/lib/pubid/adobe/renderer.rb +39 -0
- data/lib/pubid/adobe/urn_generator.rb +42 -0
- data/lib/pubid/adobe/urn_parser.rb +69 -0
- data/lib/pubid/adobe.rb +61 -0
- data/lib/pubid/amca/builder.rb +4 -4
- data/lib/pubid/amca/identifier.rb +1 -3
- data/lib/pubid/amca/identifiers/base.rb +50 -33
- data/lib/pubid/amca/identifiers/interpretation.rb +18 -10
- data/lib/pubid/amca/identifiers/publication.rb +14 -10
- data/lib/pubid/amca/identifiers/standard.rb +3 -1
- data/lib/pubid/amca/identifiers.rb +0 -1
- data/lib/pubid/amca/parser.rb +1 -1
- data/lib/pubid/amca/renderer.rb +4 -4
- data/lib/pubid/amca/single_identifier.rb +1 -1
- data/lib/pubid/amca/urn_generator.rb +2 -2
- data/lib/pubid/amca.rb +5 -4
- 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 +53 -32
- data/lib/pubid/ashrae/identifier.rb +3 -4
- data/lib/pubid/ashrae/identifiers/addenda_package.rb +7 -1
- data/lib/pubid/ashrae/identifiers/addendum.rb +9 -1
- data/lib/pubid/ashrae/identifiers/base.rb +94 -12
- data/lib/pubid/ashrae/identifiers/combined_addenda.rb +8 -1
- 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/identifiers.rb +0 -1
- data/lib/pubid/ashrae/parser.rb +37 -17
- data/lib/pubid/ashrae/renderer.rb +20 -20
- data/lib/pubid/ashrae/single_identifier.rb +1 -1
- data/lib/pubid/ashrae/supplement_identifier.rb +21 -6
- data/lib/pubid/ashrae/urn_generator.rb +8 -2
- data/lib/pubid/ashrae.rb +10 -4
- 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 +163 -0
- data/lib/pubid/bipm/identifier.rb +285 -0
- data/lib/pubid/bipm/identifiers/committee_document.rb +36 -0
- data/lib/pubid/bipm/identifiers/guide.rb +35 -0
- data/lib/pubid/bipm/identifiers/meeting.rb +53 -0
- data/lib/pubid/bipm/identifiers/mep.rb +33 -0
- data/lib/pubid/bipm/identifiers/metrologia_article.rb +48 -0
- data/lib/pubid/bipm/identifiers/si_brochure.rb +33 -0
- data/lib/pubid/bipm/identifiers.rb +15 -0
- data/lib/pubid/bipm/parser.rb +237 -0
- data/lib/pubid/bipm/renderer.rb +118 -0
- data/lib/pubid/bipm/urn_generator.rb +58 -0
- data/lib/pubid/bipm/urn_parser.rb +60 -0
- data/lib/pubid/bipm.rb +92 -0
- data/lib/pubid/bsi/builder.rb +62 -52
- data/lib/pubid/bsi/identifier.rb +0 -1
- data/lib/pubid/bsi/identifiers/addendum_document.rb +2 -2
- 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/amendment.rb +4 -4
- 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/consolidated_identifier.rb +6 -0
- data/lib/pubid/bsi/identifiers/corrigendum.rb +4 -4
- data/lib/pubid/bsi/identifiers/expert_commentary.rb +5 -5
- 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/identifiers/supplement_document.rb +2 -2
- data/lib/pubid/bsi/identifiers/value_added_publication.rb +6 -6
- data/lib/pubid/bsi/parser.rb +1 -1
- data/lib/pubid/bsi/renderer.rb +71 -59
- data/lib/pubid/bsi/single_identifier.rb +64 -7
- data/lib/pubid/bsi/urn_generator.rb +11 -2
- data/lib/pubid/bsi.rb +7 -1
- data/lib/pubid/builder/base.rb +23 -11
- data/lib/pubid/bundled_identifier.rb +19 -9
- data/lib/pubid/calconnect/builder.rb +38 -0
- data/lib/pubid/calconnect/identifier.rb +121 -0
- data/lib/pubid/calconnect/identifiers/standard.rb +29 -0
- data/lib/pubid/calconnect/identifiers.rb +9 -0
- data/lib/pubid/calconnect/parser.rb +54 -0
- data/lib/pubid/calconnect/renderer.rb +36 -0
- data/lib/pubid/calconnect/urn_generator.rb +33 -0
- data/lib/pubid/calconnect/urn_parser.rb +34 -0
- data/lib/pubid/calconnect.rb +83 -0
- data/lib/pubid/ccsds/builder.rb +1 -1
- data/lib/pubid/ccsds/identifier.rb +10 -3
- data/lib/pubid/ccsds/identifiers/base.rb +4 -2
- data/lib/pubid/ccsds/identifiers/corrigendum.rb +4 -4
- data/lib/pubid/ccsds/parser.rb +1 -1
- data/lib/pubid/ccsds/single_identifier.rb +2 -2
- data/lib/pubid/ccsds/supplement_identifier.rb +6 -6
- data/lib/pubid/ccsds/urn_generator.rb +3 -3
- data/lib/pubid/ccsds.rb +1 -0
- data/lib/pubid/cen_cenelec/builder.rb +131 -72
- 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 -14
- data/lib/pubid/cen_cenelec/identifiers/corrigendum.rb +47 -8
- data/lib/pubid/cen_cenelec/identifiers/european_norm.rb +60 -3
- 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 +104 -82
- data/lib/pubid/cie/builder.rb +149 -24
- data/lib/pubid/cie/identifier.rb +13 -4
- data/lib/pubid/cie/identifiers/bundle.rb +35 -5
- data/lib/pubid/cie/identifiers/code_attributes.rb +52 -0
- data/lib/pubid/cie/identifiers/conference.rb +11 -6
- data/lib/pubid/cie/identifiers/corrigendum.rb +17 -23
- data/lib/pubid/cie/identifiers/dual_published.rb +6 -6
- data/lib/pubid/cie/identifiers/identical.rb +9 -9
- data/lib/pubid/cie/identifiers/joint_published.rb +10 -10
- data/lib/pubid/cie/identifiers/proceedings.rb +41 -0
- data/lib/pubid/cie/identifiers/standard.rb +43 -8
- data/lib/pubid/cie/identifiers/supplement.rb +27 -25
- data/lib/pubid/cie/identifiers/tutorial_bundle.rb +7 -3
- data/lib/pubid/cie/identifiers.rb +2 -0
- data/lib/pubid/cie/parser.rb +55 -6
- data/lib/pubid/cie/single_identifier.rb +40 -1
- data/lib/pubid/cie/supplement_identifier.rb +29 -16
- data/lib/pubid/cie/urn_generator.rb +11 -8
- data/lib/pubid/cie.rb +7 -2
- data/lib/pubid/components/date.rb +21 -5
- 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 +48 -48
- data/lib/pubid/csa/composite_identifier.rb +18 -7
- data/lib/pubid/csa/identifier.rb +187 -80
- data/lib/pubid/csa/identifiers/bundled.rb +25 -9
- 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 +97 -69
- data/lib/pubid/csa/identifiers/csa_adopted.rb +4 -4
- data/lib/pubid/csa/identifiers/package.rb +4 -4
- data/lib/pubid/csa/parser.rb +12 -8
- 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 +43 -10
- data/lib/pubid/csa.rb +7 -1
- data/lib/pubid/doi/builder.rb +18 -0
- data/lib/pubid/doi/identifier.rb +49 -0
- data/lib/pubid/doi/identifiers/resource.rb +30 -0
- data/lib/pubid/doi/identifiers.rb +9 -0
- data/lib/pubid/doi/parser.rb +52 -0
- data/lib/pubid/doi/renderer.rb +13 -0
- data/lib/pubid/doi.rb +56 -0
- data/lib/pubid/easc/builder.rb +55 -0
- data/lib/pubid/easc/identifier.rb +59 -0
- data/lib/pubid/easc/identifiers/pmg.rb +20 -0
- data/lib/pubid/easc/identifiers/rmg.rb +19 -0
- data/lib/pubid/easc/identifiers.rb +10 -0
- data/lib/pubid/easc/parser.rb +88 -0
- data/lib/pubid/easc/renderer.rb +48 -0
- data/lib/pubid/easc/urn_generator.rb +46 -0
- data/lib/pubid/easc/urn_parser.rb +57 -0
- data/lib/pubid/easc.rb +53 -0
- data/lib/pubid/ecma/builder.rb +45 -0
- data/lib/pubid/ecma/identifier.rb +147 -0
- data/lib/pubid/ecma/identifiers/memento.rb +30 -0
- data/lib/pubid/ecma/identifiers/standard.rb +31 -0
- data/lib/pubid/ecma/identifiers/technical_report.rb +31 -0
- data/lib/pubid/ecma/identifiers.rb +11 -0
- data/lib/pubid/ecma/parser.rb +76 -0
- data/lib/pubid/ecma/renderer.rb +67 -0
- data/lib/pubid/ecma/urn_generator.rb +46 -0
- data/lib/pubid/ecma/urn_parser.rb +51 -0
- data/lib/pubid/ecma.rb +68 -0
- data/lib/pubid/errors.rb +80 -0
- data/lib/pubid/etsi/builder.rb +13 -4
- data/lib/pubid/etsi/identifier.rb +1 -3
- data/lib/pubid/etsi/identifiers/base.rb +43 -11
- data/lib/pubid/etsi/identifiers/etsi_standard.rb +207 -4
- data/lib/pubid/etsi/identifiers/supplement_identifier.rb +45 -3
- data/lib/pubid/etsi/identifiers.rb +0 -1
- data/lib/pubid/etsi/parser.rb +9 -3
- data/lib/pubid/etsi/renderer.rb +8 -2
- data/lib/pubid/etsi.rb +6 -5
- 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/exporter.rb +2 -1
- data/lib/pubid/export/flavor_exporter.rb +18 -3
- data/lib/pubid/export.rb +1 -0
- data/lib/pubid/format_detector.rb +1 -0
- data/lib/pubid/gb/builder.rb +45 -0
- data/lib/pubid/gb/identifier.rb +67 -0
- data/lib/pubid/gb/identifiers/standard.rb +34 -0
- data/lib/pubid/gb/identifiers.rb +9 -0
- data/lib/pubid/gb/parser.rb +63 -0
- data/lib/pubid/gb/renderer.rb +35 -0
- data/lib/pubid/gb.rb +88 -0
- data/lib/pubid/gost/builder.rb +185 -0
- data/lib/pubid/gost/identifier.rb +47 -0
- data/lib/pubid/gost/identifiers/foreign_reference.rb +25 -0
- data/lib/pubid/gost/identifiers/harmonized.rb +39 -0
- data/lib/pubid/gost/identifiers/identical_adoption.rb +39 -0
- data/lib/pubid/gost/identifiers/interstate_standard.rb +20 -0
- data/lib/pubid/gost/identifiers/national_standard.rb +19 -0
- data/lib/pubid/gost/identifiers.rb +13 -0
- data/lib/pubid/gost/parser.rb +105 -0
- data/lib/pubid/gost/renderer.rb +48 -0
- data/lib/pubid/gost/urn_generator.rb +46 -0
- data/lib/pubid/gost/urn_parser.rb +52 -0
- data/lib/pubid/gost.rb +50 -0
- data/lib/pubid/iala/builder.rb +22 -27
- data/lib/pubid/iala/identifier.rb +36 -8
- data/lib/pubid/iala/identifiers/advice.rb +1 -1
- data/lib/pubid/iala/identifiers/annex.rb +10 -10
- data/lib/pubid/iala/identifiers/general_assembly.rb +5 -2
- data/lib/pubid/iala/identifiers/guideline.rb +3 -1
- data/lib/pubid/iala/identifiers/letter.rb +1 -1
- data/lib/pubid/iala/identifiers/manual.rb +3 -1
- data/lib/pubid/iala/identifiers/model_course.rb +3 -1
- data/lib/pubid/iala/identifiers/recommendation.rb +3 -1
- data/lib/pubid/iala/identifiers/report.rb +1 -1
- data/lib/pubid/iala/identifiers/resolution.rb +1 -1
- data/lib/pubid/iala/identifiers/standard.rb +3 -1
- data/lib/pubid/iala/identifiers.rb +0 -1
- data/lib/pubid/iala/parser.rb +10 -2
- data/lib/pubid/iala/renderer.rb +1 -1
- data/lib/pubid/iala/urn_generator.rb +1 -1
- data/lib/pubid/iala/urn_parser.rb +24 -3
- data/lib/pubid/iala.rb +5 -4
- data/lib/pubid/iana/builder.rb +22 -0
- data/lib/pubid/iana/identifier.rb +140 -0
- data/lib/pubid/iana/identifiers/registry.rb +69 -0
- data/lib/pubid/iana/identifiers.rb +9 -0
- data/lib/pubid/iana/parser.rb +38 -0
- data/lib/pubid/iana/renderer.rb +32 -0
- data/lib/pubid/iana/urn_generator.rb +19 -0
- data/lib/pubid/iana/urn_parser.rb +24 -0
- data/lib/pubid/iana.rb +70 -0
- data/lib/pubid/identifier.rb +797 -26
- data/lib/pubid/identifier_metadata.rb +1 -0
- data/lib/pubid/idf/builder.rb +4 -4
- data/lib/pubid/idf/identifier.rb +18 -9
- data/lib/pubid/idf/parser.rb +3 -3
- data/lib/pubid/idf/renderer.rb +5 -5
- data/lib/pubid/idf/supplement_identifier.rb +3 -3
- data/lib/pubid/idf/urn_generator.rb +1 -1
- data/lib/pubid/idf.rb +7 -1
- data/lib/pubid/iec/builder.rb +49 -32
- data/lib/pubid/iec/components.rb +0 -1
- data/lib/pubid/iec/identifier.rb +112 -77
- data/lib/pubid/iec/identifiers/amendment.rb +6 -2
- data/lib/pubid/iec/identifiers/base.rb +2 -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/consolidated_identifier.rb +6 -0
- data/lib/pubid/iec/identifiers/corrigendum.rb +2 -2
- data/lib/pubid/iec/identifiers/fragment_identifier.rb +13 -15
- data/lib/pubid/iec/identifiers/guide.rb +0 -16
- data/lib/pubid/iec/identifiers/international_standard.rb +22 -6
- 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/sheet_identifier.rb +12 -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_group.rb +30 -0
- data/lib/pubid/iec/identifiers/technical_report.rb +1 -18
- data/lib/pubid/iec/identifiers/technical_specification.rb +1 -18
- 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/vap_identifier.rb +12 -12
- data/lib/pubid/iec/identifiers/white_paper.rb +0 -10
- data/lib/pubid/iec/identifiers/working_document.rb +24 -10
- data/lib/pubid/iec/identifiers.rb +1 -0
- data/lib/pubid/iec/parser.rb +53 -28
- data/lib/pubid/iec/renderer.rb +31 -18
- data/lib/pubid/iec/single_identifier.rb +34 -11
- data/lib/pubid/iec/supplement_identifier.rb +32 -19
- data/lib/pubid/iec/urn_generator.rb +227 -61
- data/lib/pubid/iec/urn_parser.rb +42 -4
- data/lib/pubid/iec.rb +2 -6
- data/lib/pubid/ieee/aiee/builder.rb +17 -3
- data/lib/pubid/ieee/aiee/identifier.rb +46 -62
- data/lib/pubid/ieee/aiee/parser.rb +1 -1
- data/lib/pubid/ieee/builder.rb +386 -69
- data/lib/pubid/ieee/compaction.rb +121 -0
- data/lib/pubid/ieee/components/draft.rb +47 -7
- data/lib/pubid/ieee/identifier.rb +1 -3
- data/lib/pubid/ieee/identifiers/adopted_standard.rb +62 -5
- data/lib/pubid/ieee/identifiers/amendment.rb +40 -0
- data/lib/pubid/ieee/identifiers/base.rb +148 -18
- data/lib/pubid/ieee/identifiers/code_number.rb +82 -0
- data/lib/pubid/ieee/identifiers/conformance_identifier.rb +6 -2
- data/lib/pubid/ieee/identifiers/corrigendum.rb +17 -2
- data/lib/pubid/ieee/identifiers/csa_dual_published.rb +24 -3
- data/lib/pubid/ieee/identifiers/dual_identifier.rb +3 -3
- data/lib/pubid/ieee/identifiers/dual_published.rb +58 -3
- data/lib/pubid/ieee/identifiers/iec_ieee_copublished.rb +102 -5
- data/lib/pubid/ieee/identifiers/interpretation_identifier.rb +25 -1
- data/lib/pubid/ieee/identifiers/joint_development.rb +64 -15
- data/lib/pubid/ieee/identifiers/multi_numbered_identifier.rb +58 -6
- data/lib/pubid/ieee/identifiers/nesc/base.rb +90 -19
- data/lib/pubid/ieee/identifiers/nesc/draft.rb +20 -5
- data/lib/pubid/ieee/identifiers/nesc/edition.rb +32 -0
- data/lib/pubid/ieee/identifiers/nesc/handbook.rb +16 -5
- data/lib/pubid/ieee/identifiers/nesc/redline.rb +11 -2
- data/lib/pubid/ieee/identifiers/nesc/standard.rb +18 -3
- data/lib/pubid/ieee/identifiers/nesc.rb +1 -0
- data/lib/pubid/ieee/identifiers/parenthetical_identifier.rb +3 -3
- data/lib/pubid/ieee/identifiers/project_draft_identifier.rb +14 -6
- data/lib/pubid/ieee/identifiers/redlined_standard.rb +4 -4
- data/lib/pubid/ieee/identifiers/si_standard.rb +4 -1
- data/lib/pubid/ieee/identifiers/standard.rb +4 -1
- data/lib/pubid/ieee/identifiers/supplement_identifier.rb +26 -7
- data/lib/pubid/ieee/identifiers.rb +2 -1
- data/lib/pubid/ieee/ire/builder.rb +7 -6
- data/lib/pubid/ieee/ire/identifier.rb +48 -33
- data/lib/pubid/ieee/ire/parser.rb +1 -1
- data/lib/pubid/ieee/nesc/builder.rb +33 -20
- data/lib/pubid/ieee/nesc/parser.rb +16 -15
- data/lib/pubid/ieee/parser.rb +462 -44
- data/lib/pubid/ieee/pre_parser.rb +1 -1
- data/lib/pubid/ieee/renderer.rb +158 -57
- data/lib/pubid/ieee/typed_stages.rb +12 -1
- data/lib/pubid/ieee/urn_generator.rb +35 -8
- data/lib/pubid/ieee.rb +63 -4
- data/lib/pubid/ieee_debug.rb +1 -0
- data/lib/pubid/ietf/builder.rb +78 -0
- data/lib/pubid/ietf/identifier.rb +5 -0
- data/lib/pubid/ietf/identifiers/base.rb +72 -0
- data/lib/pubid/ietf/identifiers/bcp.rb +36 -0
- data/lib/pubid/ietf/identifiers/fyi.rb +36 -0
- data/lib/pubid/ietf/identifiers/internet_draft.rb +45 -0
- data/lib/pubid/ietf/identifiers/rfc.rb +27 -0
- data/lib/pubid/ietf/identifiers/serialization.rb +51 -0
- data/lib/pubid/ietf/identifiers/std.rb +36 -0
- data/lib/pubid/ietf/identifiers.rb +14 -0
- data/lib/pubid/ietf/parser.rb +61 -0
- data/lib/pubid/ietf/renderer.rb +64 -0
- data/lib/pubid/ietf/urn_generator.rb +37 -0
- data/lib/pubid/ietf/urn_parser.rb +43 -0
- data/lib/pubid/ietf.rb +86 -0
- data/lib/pubid/iho/identifier.rb +1 -3
- data/lib/pubid/iho/identifiers/base.rb +11 -10
- data/lib/pubid/iho/identifiers/bibliographic.rb +1 -1
- data/lib/pubid/iho/identifiers/circular_letter.rb +1 -1
- data/lib/pubid/iho/identifiers/miscellaneous.rb +1 -1
- data/lib/pubid/iho/identifiers/publication.rb +1 -1
- data/lib/pubid/iho/identifiers/standard.rb +1 -1
- data/lib/pubid/iho/identifiers.rb +0 -1
- data/lib/pubid/iho/parser.rb +1 -1
- data/lib/pubid/iho.rb +8 -7
- data/lib/pubid/isbn/builder.rb +44 -0
- data/lib/pubid/isbn/check_digit.rb +53 -0
- data/lib/pubid/isbn/identifier.rb +81 -0
- data/lib/pubid/isbn/identifiers/book.rb +30 -0
- data/lib/pubid/isbn/identifiers.rb +9 -0
- data/lib/pubid/isbn/parser.rb +45 -0
- data/lib/pubid/isbn/renderer.rb +16 -0
- data/lib/pubid/isbn.rb +53 -0
- data/lib/pubid/iso/builder.rb +9 -4
- data/lib/pubid/iso/bundled_identifier.rb +5 -3
- data/lib/pubid/iso/combined_identifier.rb +6 -4
- data/lib/pubid/iso/identifier.rb +29 -8
- data/lib/pubid/iso/identifiers/directives_supplement.rb +12 -12
- data/lib/pubid/iso/normalizer.rb +2 -2
- data/lib/pubid/iso/parser.rb +17 -13
- data/lib/pubid/iso/supplement_identifier.rb +19 -6
- data/lib/pubid/iso/urn_generator.rb +4 -1
- data/lib/pubid/iso/urn_parser.rb +1 -1
- data/lib/pubid/iso.rb +7 -1
- data/lib/pubid/itu/builder.rb +230 -29
- data/lib/pubid/itu/components/code.rb +48 -5
- data/lib/pubid/itu/components/designation.rb +35 -0
- data/lib/pubid/itu/components.rb +1 -0
- data/lib/pubid/itu/identifier.rb +1 -3
- data/lib/pubid/itu/identifiers/addendum.rb +15 -0
- data/lib/pubid/itu/identifiers/amendment.rb +7 -29
- data/lib/pubid/itu/identifiers/annex.rb +13 -2
- data/lib/pubid/itu/identifiers/annex_of_recommendation.rb +87 -0
- data/lib/pubid/itu/identifiers/appendix_of_recommendation.rb +92 -0
- data/lib/pubid/itu/identifiers/base.rb +357 -25
- data/lib/pubid/itu/identifiers/combined_identifier.rb +99 -23
- data/lib/pubid/itu/identifiers/corrigendum.rb +16 -23
- data/lib/pubid/itu/identifiers/errata.rb +15 -0
- data/lib/pubid/itu/identifiers/handbook.rb +38 -0
- data/lib/pubid/itu/identifiers/question.rb +63 -0
- data/lib/pubid/itu/identifiers/recommendation.rb +3 -2
- data/lib/pubid/itu/identifiers/report.rb +39 -0
- data/lib/pubid/itu/identifiers/special_publication.rb +3 -1
- data/lib/pubid/itu/identifiers/standard_serialization.rb +58 -0
- data/lib/pubid/itu/identifiers/supplement.rb +119 -14
- data/lib/pubid/itu/identifiers.rb +10 -1
- data/lib/pubid/itu/model.rb +1 -1
- data/lib/pubid/itu/parser.rb +481 -27
- data/lib/pubid/itu/urn_generator.rb +36 -6
- data/lib/pubid/itu/urn_parser.rb +8 -0
- data/lib/pubid/itu.rb +12 -3
- data/lib/pubid/jcgm/builder.rb +24 -14
- data/lib/pubid/jcgm/identifier.rb +10 -0
- data/lib/pubid/jcgm/identifiers/amendment.rb +0 -2
- data/lib/pubid/jcgm/identifiers/corrigendum.rb +34 -0
- data/lib/pubid/jcgm/identifiers/gum_guide.rb +3 -3
- data/lib/pubid/jcgm/identifiers/meeting.rb +47 -0
- data/lib/pubid/jcgm/identifiers.rb +2 -0
- data/lib/pubid/jcgm/parser.rb +74 -7
- data/lib/pubid/jcgm/renderer.rb +33 -12
- data/lib/pubid/jcgm/single_identifier.rb +84 -6
- data/lib/pubid/jcgm/supplement_identifier.rb +39 -4
- data/lib/pubid/jcgm/urn_generator.rb +21 -13
- data/lib/pubid/jcgm/urn_parser.rb +164 -10
- data/lib/pubid/jcgm.rb +10 -0
- data/lib/pubid/jis/identifier.rb +62 -3
- data/lib/pubid/jis/parser.rb +1 -1
- data/lib/pubid/jis.rb +1 -0
- data/lib/pubid/nist/builder.rb +29 -9
- data/lib/pubid/nist/caster.rb +7 -45
- data/lib/pubid/nist/circular_supplement_builder.rb +7 -5
- data/lib/pubid/nist/components/stage.rb +2 -2
- data/lib/pubid/nist/components/supplement.rb +5 -2
- data/lib/pubid/nist/configuration.rb +6 -2
- data/lib/pubid/nist/identifier.rb +1 -3
- data/lib/pubid/nist/identifiers/base.rb +133 -39
- data/lib/pubid/nist/identifiers/circular.rb +10 -3
- data/lib/pubid/nist/identifiers/circular_supplement.rb +14 -5
- data/lib/pubid/nist/identifiers/commercial_standard.rb +1 -1
- data/lib/pubid/nist/identifiers/commercial_standard_emergency.rb +1 -1
- data/lib/pubid/nist/identifiers/commercial_standards_monthly.rb +8 -2
- data/lib/pubid/nist/identifiers/crpl_report.rb +8 -2
- data/lib/pubid/nist/identifiers/dated_document.rb +1 -1
- data/lib/pubid/nist/identifiers/federal_information_processing_standards.rb +1 -1
- data/lib/pubid/nist/identifiers/grant_contractor_report.rb +1 -1
- data/lib/pubid/nist/identifiers/handbook.rb +10 -3
- data/lib/pubid/nist/identifiers/internal_report.rb +13 -6
- data/lib/pubid/nist/identifiers/letter_circular.rb +1 -1
- data/lib/pubid/nist/identifiers/miscellaneous_publication.rb +15 -7
- data/lib/pubid/nist/identifiers/monograph.rb +15 -8
- data/lib/pubid/nist/identifiers/ncstar.rb +2 -2
- data/lib/pubid/nist/identifiers/nsrds.rb +1 -1
- data/lib/pubid/nist/identifiers/owmwp.rb +1 -1
- data/lib/pubid/nist/identifiers/report.rb +15 -7
- data/lib/pubid/nist/identifiers/special_publication.rb +10 -1
- data/lib/pubid/nist/identifiers/technical_note.rb +1 -1
- data/lib/pubid/nist/identifiers.rb +0 -1
- data/lib/pubid/nist/parser.rb +27 -4
- data/lib/pubid/nist/preprocessor.rb +15 -0
- data/lib/pubid/nist/router.rb +2 -2
- data/lib/pubid/nist/series/ir.rb +0 -3
- data/lib/pubid/nist/supplement_identifier.rb +24 -9
- data/lib/pubid/nist.rb +19 -13
- data/lib/pubid/oasis/builder.rb +79 -0
- data/lib/pubid/oasis/identifier.rb +160 -0
- data/lib/pubid/oasis/identifiers/standard.rb +29 -0
- data/lib/pubid/oasis/identifiers.rb +9 -0
- data/lib/pubid/oasis/parser.rb +34 -0
- data/lib/pubid/oasis/renderer.rb +29 -0
- data/lib/pubid/oasis/urn_generator.rb +25 -0
- data/lib/pubid/oasis/urn_parser.rb +22 -0
- data/lib/pubid/oasis.rb +80 -0
- data/lib/pubid/ogc/builder.rb +33 -0
- data/lib/pubid/ogc/identifier.rb +81 -0
- data/lib/pubid/ogc/identifiers/document.rb +26 -0
- data/lib/pubid/ogc/identifiers.rb +10 -0
- data/lib/pubid/ogc/parser.rb +40 -0
- data/lib/pubid/ogc/renderer.rb +33 -0
- data/lib/pubid/ogc/urn_generator.rb +14 -0
- data/lib/pubid/ogc/urn_parser.rb +22 -0
- data/lib/pubid/ogc.rb +72 -0
- data/lib/pubid/oiml/builder.rb +36 -8
- data/lib/pubid/oiml/identifier.rb +9 -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 +12 -13
- data/lib/pubid/oiml/renderer.rb +13 -13
- data/lib/pubid/oiml/single_identifier.rb +41 -37
- data/lib/pubid/oiml/supplement_identifier.rb +36 -9
- data/lib/pubid/oiml/urn_parser.rb +23 -6
- data/lib/pubid/oiml.rb +10 -0
- data/lib/pubid/omg/builder.rb +20 -0
- data/lib/pubid/omg/identifier.rb +61 -0
- data/lib/pubid/omg/identifiers/specification.rb +32 -0
- data/lib/pubid/omg/identifiers.rb +9 -0
- data/lib/pubid/omg/parser.rb +93 -0
- data/lib/pubid/omg/renderer.rb +31 -0
- data/lib/pubid/omg.rb +52 -0
- data/lib/pubid/parser/grammar.rb +74 -0
- data/lib/pubid/parser.rb +2 -0
- data/lib/pubid/parsers/mr_string.rb +120 -7
- data/lib/pubid/plateau/builder.rb +8 -4
- data/lib/pubid/plateau/identifier.rb +1 -3
- data/lib/pubid/plateau/identifiers/base.rb +1 -6
- data/lib/pubid/plateau/identifiers/handbook.rb +1 -1
- data/lib/pubid/plateau/identifiers/technical_report.rb +1 -1
- data/lib/pubid/plateau/identifiers.rb +0 -1
- data/lib/pubid/plateau/parser.rb +16 -6
- data/lib/pubid/plateau/renderer.rb +1 -1
- data/lib/pubid/plateau/supplement_identifier.rb +11 -11
- data/lib/pubid/plateau.rb +14 -4
- 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 +6 -4
- data/lib/pubid/renderers/mr_string.rb +54 -6
- data/lib/pubid/renderers/supplement_renderer.rb +1 -1
- data/lib/pubid/renderers.rb +1 -0
- data/lib/pubid/rendering/numbering.rb +25 -7
- data/lib/pubid/rendering/supplement.rb +4 -4
- data/lib/pubid/rendering.rb +1 -0
- data/lib/pubid/sae/builder.rb +1 -1
- data/lib/pubid/sae/identifier.rb +1 -3
- data/lib/pubid/sae/identifiers/base.rb +19 -9
- data/lib/pubid/sae/identifiers.rb +0 -1
- data/lib/pubid/sae/parser.rb +1 -1
- data/lib/pubid/sae.rb +4 -3
- 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 +41 -0
- data/lib/pubid/tgpp/identifier.rb +107 -0
- data/lib/pubid/tgpp/identifiers/technical_report.rb +32 -0
- data/lib/pubid/tgpp/identifiers/technical_specification.rb +33 -0
- data/lib/pubid/tgpp/identifiers.rb +11 -0
- data/lib/pubid/tgpp/parser.rb +78 -0
- data/lib/pubid/tgpp/renderer.rb +52 -0
- data/lib/pubid/tgpp/urn_generator.rb +39 -0
- data/lib/pubid/tgpp/urn_parser.rb +30 -0
- data/lib/pubid/tgpp.rb +84 -0
- data/lib/pubid/type_resolver.rb +74 -0
- data/lib/pubid/un/builder.rb +42 -0
- data/lib/pubid/un/identifier.rb +40 -0
- data/lib/pubid/un/identifiers/document.rb +24 -0
- data/lib/pubid/un/identifiers.rb +9 -0
- data/lib/pubid/un/parser.rb +25 -0
- data/lib/pubid/un/renderer.rb +11 -0
- data/lib/pubid/un.rb +47 -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 +55 -0
- data/lib/pubid/w3c/identifier.rb +130 -0
- data/lib/pubid/w3c/identifiers/candidate_recommendation.rb +31 -0
- data/lib/pubid/w3c/identifiers/candidate_recommendation_draft.rb +31 -0
- data/lib/pubid/w3c/identifiers/draft_note.rb +31 -0
- data/lib/pubid/w3c/identifiers/note.rb +30 -0
- data/lib/pubid/w3c/identifiers/obsolete_recommendation.rb +31 -0
- data/lib/pubid/w3c/identifiers/proposed_edited_recommendation.rb +31 -0
- data/lib/pubid/w3c/identifiers/proposed_recommendation.rb +31 -0
- data/lib/pubid/w3c/identifiers/recommendation.rb +31 -0
- data/lib/pubid/w3c/identifiers/standard.rb +12 -0
- data/lib/pubid/w3c/identifiers/superseded_recommendation.rb +31 -0
- data/lib/pubid/w3c/identifiers/working_draft.rb +30 -0
- data/lib/pubid/w3c/identifiers.rb +25 -0
- data/lib/pubid/w3c/parser.rb +43 -0
- data/lib/pubid/w3c/renderer.rb +35 -0
- data/lib/pubid/w3c/urn_generator.rb +18 -0
- data/lib/pubid/w3c/urn_parser.rb +36 -0
- data/lib/pubid/w3c.rb +68 -0
- data/lib/pubid/xsf/builder.rb +17 -0
- data/lib/pubid/xsf/identifier.rb +66 -0
- data/lib/pubid/xsf/identifiers/xep.rb +31 -0
- data/lib/pubid/xsf/identifiers.rb +9 -0
- data/lib/pubid/xsf/parser.rb +38 -0
- data/lib/pubid/xsf/renderer.rb +23 -0
- data/lib/pubid/xsf/urn_generator.rb +13 -0
- data/lib/pubid/xsf/urn_parser.rb +18 -0
- data/lib/pubid/xsf.rb +82 -0
- data/lib/pubid.rb +424 -22
- 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 +241 -19
- 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/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/cie/components/code.rb +0 -80
- data/lib/pubid/iala/identifiers/base.rb +0 -14
- data/lib/pubid/iec/components/code.rb +0 -36
- /data/{archived-gems/pubid-nist → data/nist}/stages.yaml +0 -0
|
@@ -24,7 +24,46 @@ module Pubid
|
|
|
24
24
|
attribute :publisher, :string, default: -> { "CIE" }
|
|
25
25
|
|
|
26
26
|
attribute :year, :string
|
|
27
|
-
|
|
27
|
+
# The number<->year separator character, derived from +style+ (the sole
|
|
28
|
+
# separator field; there is no date_separator attribute):
|
|
29
|
+
# current -> ":" legacy -> "-" slash -> "/"
|
|
30
|
+
def date_sep_char
|
|
31
|
+
{ "legacy" => "-", "slash" => "/" }.fetch(style, ":")
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
# Partial-reference matching: CIE keeps the publication year in its own
|
|
35
|
+
# `year` string attribute (the separator lives in `style`), not a `Date`
|
|
36
|
+
# component, so the base's `:year`->`:date` remap would nil the unused
|
|
37
|
+
# inherited `date` and leave `year` intact. Call super (preserving the
|
|
38
|
+
# nested-identifier recursion), then nil `year` directly so a year-less
|
|
39
|
+
# CIE ref is a year wildcard under `matches?(ignore: [:year])`.
|
|
40
|
+
#
|
|
41
|
+
# Known limit: `style` (which also encodes the era: current<->colon,
|
|
42
|
+
# legacy<->dash) is intentionally NOT wildcarded, so bare `CIE 015`
|
|
43
|
+
# (always current) matches a colon-dated full but not a legacy dash-dated
|
|
44
|
+
# (pre-2001) one. Partial-ref scope targets modern colon forms.
|
|
45
|
+
def exclude(*args)
|
|
46
|
+
result = super
|
|
47
|
+
result.year = nil if args.include?(:year) || args.include?(:date)
|
|
48
|
+
result
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
# CIE stores its publication year in its own `year` string attribute
|
|
52
|
+
# (not a Components::Date), and uses a single-Language component with
|
|
53
|
+
# multiple formats. Override the lossless MR template so `CIE S 017/E:2011`
|
|
54
|
+
# round-trips as `CIE.S.017.E.2011` rather than losing the type letter,
|
|
55
|
+
# language, and year (issue #142). Subclasses add the `s_prefix` and
|
|
56
|
+
# `language` attributes that this template reads.
|
|
57
|
+
def mr_year
|
|
58
|
+
year&.to_s
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def mr_languages
|
|
62
|
+
return nil unless respond_to?(:language) && language
|
|
63
|
+
|
|
64
|
+
# Lowercase + filename-safe: drop the leading `/` (path-unsafe).
|
|
65
|
+
language.code.to_s.downcase
|
|
66
|
+
end
|
|
28
67
|
end
|
|
29
68
|
end
|
|
30
69
|
end
|
|
@@ -2,25 +2,38 @@
|
|
|
2
2
|
|
|
3
3
|
module Pubid
|
|
4
4
|
module Cie
|
|
5
|
-
# Base class for CIE supplement identifiers
|
|
6
|
-
# Single Responsibility: Provide common attributes for supplement documents
|
|
5
|
+
# Base class for CIE supplement identifiers (Supplement, Corrigendum).
|
|
7
6
|
#
|
|
8
|
-
#
|
|
9
|
-
#
|
|
10
|
-
#
|
|
7
|
+
# Like ISO/IEC/BSI/JCGM, a CIE supplement wraps its base document as a
|
|
8
|
+
# nested full identifier (+base+, a Pubid::Cie::Identifier),
|
|
9
|
+
# rather than flat base_number/base_year strings. This lets CIE supplements
|
|
10
|
+
# participate in the shared base_document / drop_supplements / matches?
|
|
11
|
+
# vocabulary relaton uses to match a citation to its base standard.
|
|
11
12
|
#
|
|
12
|
-
#
|
|
13
|
-
# - Corrigendum (corrigenda with /CorN notation)
|
|
14
|
-
# - Supplement (supplements with -SPN notation)
|
|
15
|
-
#
|
|
16
|
-
# Architecture Note:
|
|
17
|
-
# CIE uses a different architectural approach than ISO/IEC:
|
|
18
|
-
# - ISO/IEC: Recursive base_identifier objects
|
|
19
|
-
# - CIE: Flat string attributes (base_number, base_year, etc.)
|
|
13
|
+
# Concrete subtypes: Supplement (-SPN), Corrigendum (/CorN).
|
|
20
14
|
class SupplementIdentifier < Identifier
|
|
21
|
-
|
|
22
|
-
#
|
|
23
|
-
|
|
15
|
+
attribute :base, Identifier, polymorphic: true
|
|
16
|
+
# The supplement's/corrigendum's own ordinal ("1" in -SP1 / Cor1).
|
|
17
|
+
# :string overrides the base ::Pubid::Identifier Components::Code type.
|
|
18
|
+
# (Not the index key — relaton keys on #root.number, the base standard's.)
|
|
19
|
+
attribute :number, :string
|
|
20
|
+
|
|
21
|
+
# Uniform, class-agnostic supplement interface (shared by Supplement and
|
|
22
|
+
# Corrigendum) so callers never special-case corrigenda. +supplement_type+
|
|
23
|
+
# and +supplement_year+ are defined per subclass.
|
|
24
|
+
def supplement_number
|
|
25
|
+
number
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
# The underlying standard, with supplement layer(s) peeled recursively.
|
|
29
|
+
def base_document
|
|
30
|
+
base&.base_document || self
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
# Dropping one supplement layer yields the wrapped base identifier.
|
|
34
|
+
def drop_supplements
|
|
35
|
+
base || self
|
|
36
|
+
end
|
|
24
37
|
end
|
|
25
38
|
end
|
|
26
39
|
end
|
|
@@ -15,8 +15,8 @@ module Pubid
|
|
|
15
15
|
|
|
16
16
|
parts << publisher_component
|
|
17
17
|
|
|
18
|
-
if identifier.
|
|
19
|
-
parts << identifier.
|
|
18
|
+
if identifier.respond_to?(:code_string) && identifier.code_string
|
|
19
|
+
parts << identifier.code_string
|
|
20
20
|
end
|
|
21
21
|
|
|
22
22
|
year = extract_year
|
|
@@ -37,8 +37,8 @@ module Pubid
|
|
|
37
37
|
stage = maybe(:stage)
|
|
38
38
|
parts << stage.to_s.downcase if stage
|
|
39
39
|
|
|
40
|
-
|
|
41
|
-
parts << "sep.#{
|
|
40
|
+
# style is the sole separator field; record it for dated identifiers
|
|
41
|
+
parts << "sep.#{maybe(:style)}" if year
|
|
42
42
|
|
|
43
43
|
iec_identifier = maybe(:iec_identifier)
|
|
44
44
|
parts << "iec.#{iec_identifier}" if iec_identifier
|
|
@@ -49,11 +49,14 @@ module Pubid
|
|
|
49
49
|
doc_type = maybe(:doc_type)
|
|
50
50
|
parts << "doctype.#{doc_type}" if doc_type
|
|
51
51
|
|
|
52
|
-
|
|
53
|
-
|
|
52
|
+
if identifier.respond_to?(:ids) && identifier.ids&.any?
|
|
53
|
+
parts << "bundle.#{identifier}"
|
|
54
|
+
end
|
|
54
55
|
|
|
55
|
-
|
|
56
|
-
|
|
56
|
+
if identifier.is_a?(Cie::Identifiers::TutorialBundle) &&
|
|
57
|
+
identifier.number
|
|
58
|
+
parts << "tut-bundle.#{identifier.number}"
|
|
59
|
+
end
|
|
57
60
|
|
|
58
61
|
languages = maybe(:languages)
|
|
59
62
|
if languages&.any?
|
data/lib/pubid/cie.rb
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require "pubid"
|
|
3
4
|
module Pubid
|
|
4
5
|
module Cie
|
|
5
6
|
extend Pubid::PrefixesSupport
|
|
@@ -8,7 +9,6 @@ module Pubid
|
|
|
8
9
|
PREFIXES = ["CIE"].freeze
|
|
9
10
|
|
|
10
11
|
module Components
|
|
11
|
-
autoload :Code, "#{__dir__}/cie/components/code"
|
|
12
12
|
autoload :Language, "#{__dir__}/cie/components/language"
|
|
13
13
|
end
|
|
14
14
|
|
|
@@ -24,8 +24,13 @@ module Pubid
|
|
|
24
24
|
# Main entry point for CIE identifiers
|
|
25
25
|
# Delegates to Identifier.parse
|
|
26
26
|
def self.parse(input)
|
|
27
|
+
unless input.is_a?(String)
|
|
28
|
+
raise Pubid::Errors::InvalidInputError,
|
|
29
|
+
Pubid::INPUT_NOT_A_STRING_MESSAGE
|
|
30
|
+
end
|
|
31
|
+
|
|
27
32
|
if input.length > Pubid::MAX_INPUT_LENGTH
|
|
28
|
-
raise
|
|
33
|
+
raise Pubid::Errors::InvalidInputError, Pubid::INPUT_TOO_LONG_MESSAGE
|
|
29
34
|
end
|
|
30
35
|
|
|
31
36
|
Identifier.parse(input)
|
|
@@ -6,19 +6,33 @@ module Pubid
|
|
|
6
6
|
module Components
|
|
7
7
|
# Publication date component
|
|
8
8
|
#
|
|
9
|
-
# Human render: "YYYY" or "YYYY-MM" or "YYYY-MM-DD"
|
|
10
|
-
#
|
|
9
|
+
# Human render: "YYYY" or "YYYY-MM" or "YYYY-MM-DD"; or "--" when the
|
|
10
|
+
# date slot is present but explicitly undated (ISO/IEC undated-reference
|
|
11
|
+
# convention, e.g. "ISO 16634:--"). URN render: year only (RFC 5141-bis
|
|
12
|
+
# URN spec); flavors that drop the slot when undated gate that decision
|
|
13
|
+
# at the URN-generator level, not here.
|
|
11
14
|
class Date < Lutaml::Model::Serializable
|
|
12
15
|
attribute :year, :string
|
|
13
16
|
attribute :month, :string
|
|
14
17
|
attribute :day, :string
|
|
18
|
+
attribute :undated, :boolean, default: false
|
|
15
19
|
|
|
16
|
-
# True when the year is set to a non-empty value
|
|
20
|
+
# True when the year is set to a non-empty value, OR the date is
|
|
21
|
+
# explicitly marked undated. An undated date is a meaningful
|
|
22
|
+
# publication-date slot (it is what renders as `:--` in ISO/IEC), so
|
|
23
|
+
# callers that gate rendering on "is there a date at all?" should
|
|
24
|
+
# treat undated as present.
|
|
17
25
|
def present?
|
|
26
|
+
return true if undated
|
|
18
27
|
!year.nil? && !year.to_s.empty?
|
|
19
28
|
end
|
|
20
29
|
|
|
30
|
+
def undated?
|
|
31
|
+
!!undated
|
|
32
|
+
end
|
|
33
|
+
|
|
21
34
|
def render(context: nil)
|
|
35
|
+
return "--" if undated? && (year.nil? || year.to_s.empty?)
|
|
22
36
|
return nil unless present?
|
|
23
37
|
return year.to_s if context&.urn?
|
|
24
38
|
return year.to_s unless month
|
|
@@ -29,6 +43,7 @@ module Pubid
|
|
|
29
43
|
end
|
|
30
44
|
|
|
31
45
|
def to_s(_context: nil, _include_month: false)
|
|
46
|
+
return "--" if undated? && (year.nil? || year.to_s.empty?)
|
|
32
47
|
return year.to_s unless month
|
|
33
48
|
|
|
34
49
|
result = "#{year}-#{pad2(month)}"
|
|
@@ -43,13 +58,14 @@ module Pubid
|
|
|
43
58
|
end
|
|
44
59
|
|
|
45
60
|
def hash
|
|
46
|
-
@hash ||= [year, month, day].compact.map(&:hash).hash
|
|
61
|
+
@hash ||= [year, month, day, undated].compact.map(&:hash).hash
|
|
47
62
|
end
|
|
48
63
|
|
|
49
64
|
def eql?(other)
|
|
50
65
|
return false unless other.is_a?(self.class)
|
|
51
66
|
|
|
52
|
-
year == other.year && month == other.month && day == other.day
|
|
67
|
+
year == other.year && month == other.month && day == other.day &&
|
|
68
|
+
undated == other.undated
|
|
53
69
|
end
|
|
54
70
|
end
|
|
55
71
|
end
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Pubid
|
|
4
|
+
module Conformance
|
|
5
|
+
# The single check core shared by the conformance runner and the rspec
|
|
6
|
+
# corpus gate. One corpus case in, its mismatch list out (empty ==
|
|
7
|
+
# passing). The list shape is load-bearing: RSpec's aggregate_failures
|
|
8
|
+
# does not raise on a failed expectation, so exception-based control
|
|
9
|
+
# flow would misread real failures as passes - and the runner needs to
|
|
10
|
+
# accumulate across cases rather than abort.
|
|
11
|
+
module Checks
|
|
12
|
+
class << self
|
|
13
|
+
# @param test_case [Pubid::Conformance::Corpus::Case]
|
|
14
|
+
# @param flavor_module [Module] the flavor owning the case
|
|
15
|
+
# @return [Array<String>] mismatch descriptions, empty when passing
|
|
16
|
+
def check_case(test_case, flavor_module)
|
|
17
|
+
identifier = flavor_module.parse(test_case.representations.human)
|
|
18
|
+
mismatchers(identifier, test_case, flavor_module)
|
|
19
|
+
.flat_map(&:call)
|
|
20
|
+
rescue StandardError => e
|
|
21
|
+
["#{test_case.id} raised #{e.class}"]
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
# Each checker returns the case's mismatch list for its concern.
|
|
25
|
+
def mismatchers(identifier, test_case, flavor_module)
|
|
26
|
+
label = test_case.id.to_s
|
|
27
|
+
[
|
|
28
|
+
-> { canonical_mismatches(identifier, test_case, label) },
|
|
29
|
+
-> { representation_mismatches(identifier, test_case, label) },
|
|
30
|
+
-> { alias_mismatches(test_case, flavor_module, label) },
|
|
31
|
+
-> { deserialize_mismatches(identifier, flavor_module, label) },
|
|
32
|
+
]
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def canonical_mismatches(identifier, test_case, label)
|
|
36
|
+
actual = Conformance.plainify(identifier.to_hash)
|
|
37
|
+
actual == test_case.identifier ? [] : ["#{label} canonical hash"]
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
private
|
|
41
|
+
|
|
42
|
+
def representation_mismatches(identifier, test_case, label)
|
|
43
|
+
mismatches = []
|
|
44
|
+
reps = test_case.representations
|
|
45
|
+
mismatches << "#{label} human" if identifier.to_s != reps.human
|
|
46
|
+
if reps.urn && identifier.to_urn != reps.urn
|
|
47
|
+
mismatches << "#{label} urn"
|
|
48
|
+
end
|
|
49
|
+
mismatches
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def alias_mismatches(test_case, flavor_module, label)
|
|
53
|
+
human = test_case.representations.human
|
|
54
|
+
test_case.non_normalized_aliases.filter_map do |entry|
|
|
55
|
+
aliased = flavor_module.parse(entry.spelling)
|
|
56
|
+
"#{label} alias #{entry.spelling}" if aliased.to_s != human
|
|
57
|
+
rescue StandardError
|
|
58
|
+
"#{label} alias #{entry.spelling} raised"
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def deserialize_mismatches(identifier, flavor_module, label)
|
|
63
|
+
hash = identifier.to_hash
|
|
64
|
+
ok = flavor_module::Identifier.from_hash(hash).to_hash == hash
|
|
65
|
+
ok ? [] : ["#{label} deserialize"]
|
|
66
|
+
rescue StandardError
|
|
67
|
+
["#{label} deserialize raised"]
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
end
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Pubid
|
|
4
|
+
module Conformance
|
|
5
|
+
module Corpus
|
|
6
|
+
# Every proper rendering of the case's identifier.
|
|
7
|
+
class Representations < Lutaml::Model::Serializable
|
|
8
|
+
attribute :human, :string
|
|
9
|
+
attribute :urn, :string
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
# One old spelling that must normalize to the human form.
|
|
13
|
+
class Spelling < Lutaml::Model::Serializable
|
|
14
|
+
attribute :spelling, :string
|
|
15
|
+
attribute :style, :string
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
# Neutral rejection expectation - never an implementation class.
|
|
19
|
+
class Error < Lutaml::Model::Serializable
|
|
20
|
+
attribute :code, :string
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
class Expectation < Lutaml::Model::Serializable
|
|
24
|
+
attribute :error, Error
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
# One corpus case (schema/test.schema.yaml is the wire contract).
|
|
28
|
+
# `identifier` stays an opaque hash on purpose: it is the flavor's
|
|
29
|
+
# own canonical to_hash carried as DATA to compare against, not a
|
|
30
|
+
# structure the reader interprets.
|
|
31
|
+
class Case < Lutaml::Model::Serializable
|
|
32
|
+
attribute :id, :string
|
|
33
|
+
attribute :style, :string
|
|
34
|
+
attribute :identifier, :hash
|
|
35
|
+
attribute :representations, Representations
|
|
36
|
+
attribute :non_normalized_aliases, Spelling, collection: true,
|
|
37
|
+
default: -> { [] }
|
|
38
|
+
attribute :roundtrip, :boolean
|
|
39
|
+
attribute :expect, Expectation
|
|
40
|
+
attribute :input, :string
|
|
41
|
+
attribute :notes, :string
|
|
42
|
+
attribute :review, :string
|
|
43
|
+
|
|
44
|
+
def error_case? = !expect.nil? && !expect.error.nil?
|
|
45
|
+
|
|
46
|
+
# Reference-bug debt: nothing to gate on.
|
|
47
|
+
def quarantined? = identifier.nil? && !error_case?
|
|
48
|
+
|
|
49
|
+
def review? = !review.to_s.empty?
|
|
50
|
+
|
|
51
|
+
def roundtrip_failure_expected? = roundtrip == false
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
end
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Pubid
|
|
4
|
+
module Conformance
|
|
5
|
+
# Typed reading layer for pubid-testsuite payloads. The YAML schema
|
|
6
|
+
# (schema/test.schema.yaml in pubid-testsuite) is the wire contract;
|
|
7
|
+
# these models are the shared typed reader for every implementation -
|
|
8
|
+
# the Ruby gem now, pubid-ts mirroring the same shape later. No
|
|
9
|
+
# consumer pokes payload hashes directly.
|
|
10
|
+
module Corpus
|
|
11
|
+
autoload :Case, "pubid/conformance/corpus/case"
|
|
12
|
+
|
|
13
|
+
class << self
|
|
14
|
+
# Cases from one payload file (underscore payloads excluded).
|
|
15
|
+
def load_file(path)
|
|
16
|
+
Array(YAML.safe_load_file(path)).map { |doc| Case.from_hash(doc) }
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def case_files(flavor, corpus_dir)
|
|
20
|
+
Dir[File.join(corpus_dir, flavor, "*.yaml")]
|
|
21
|
+
.reject { |p| File.basename(p).start_with?("_") }.sort
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def cases(flavor, corpus_dir)
|
|
25
|
+
case_files(flavor, corpus_dir).flat_map { |p| load_file(p) }
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
# The must-fail payload (fail fixtures decoded by the exporter).
|
|
29
|
+
def negative_file(flavor, corpus_dir)
|
|
30
|
+
path = File.join(corpus_dir, flavor, "_negative.yaml")
|
|
31
|
+
File.exist?(path) ? [path] : []
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Pubid
|
|
4
|
+
module Conformance
|
|
5
|
+
# Migrates the ground-truth fixture library (spec/fixtures/{flavor}/
|
|
6
|
+
# identifiers/{pass,fail}/*.txt) into the neutral corpus by running the
|
|
7
|
+
# reference implementation. Fixture lines that normalize to the same
|
|
8
|
+
# identifier collapse into one canonical case carrying the old
|
|
9
|
+
# spellings as non_normalized_aliases (old => normalized, and the
|
|
10
|
+
# normalized form round-trips). Unparseable pass lines are recorded as
|
|
11
|
+
# visible debt; fail lines (stored as "#ID# Error: ..." comments in the
|
|
12
|
+
# fixture files) become negative cases. Nothing is sampled, filtered,
|
|
13
|
+
# or dropped.
|
|
14
|
+
class Generator
|
|
15
|
+
attr_reader :flavor
|
|
16
|
+
|
|
17
|
+
def initialize(flavor)
|
|
18
|
+
require "pubid"
|
|
19
|
+
|
|
20
|
+
@flavor = flavor.to_s
|
|
21
|
+
Pubid.eager_load_flavors!
|
|
22
|
+
@flavor_module = Pubid::Registry.get(@flavor)
|
|
23
|
+
raise ArgumentError, "unknown flavor #{@flavor}" unless @flavor_module
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def generate(output_dir:)
|
|
27
|
+
results = { files: 0, cases: 0, negative: 0, debt: 0, aliases: 0,
|
|
28
|
+
duplicates: 0, reclassify: 0, roundtrip_failures: 0 }
|
|
29
|
+
debt = []
|
|
30
|
+
pass_files.each do |path|
|
|
31
|
+
type = File.basename(path, ".txt")
|
|
32
|
+
cases, type_debt = build_pass_cases(path, type, results)
|
|
33
|
+
debt.concat(type_debt)
|
|
34
|
+
next if cases.empty?
|
|
35
|
+
|
|
36
|
+
write_yaml(File.join(output_dir, "#{type}.yaml"), cases)
|
|
37
|
+
results[:files] += 1
|
|
38
|
+
end
|
|
39
|
+
results[:debt] = debt.size
|
|
40
|
+
write_yaml(File.join(output_dir, "_debt.yaml"), debt) if debt.any?
|
|
41
|
+
negative = build_negative_cases(results)
|
|
42
|
+
if negative.any?
|
|
43
|
+
write_yaml(File.join(output_dir, "_negative.yaml"), negative)
|
|
44
|
+
end
|
|
45
|
+
results
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
private
|
|
49
|
+
|
|
50
|
+
def pass_files
|
|
51
|
+
Dir[File.join(fixtures_dir, "identifiers", "pass", "*.txt")] +
|
|
52
|
+
Dir[File.join(fixtures_dir, "identifiers", "full", "*.txt")]
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def fail_files
|
|
56
|
+
Dir[File.join(fixtures_dir, "identifiers", "fail", "*.txt")]
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def fixtures_dir
|
|
60
|
+
File.join(tests_repo, "reference-docs", @flavor)
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def tests_repo
|
|
64
|
+
@tests_repo ||= ENV.fetch("PUBID_TESTSUITE_PATH",
|
|
65
|
+
File.expand_path("../../../../pubid-testsuite",
|
|
66
|
+
__dir__))
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def fixture_lines(path)
|
|
70
|
+
File.readlines(path).map(&:strip).reject do |line|
|
|
71
|
+
line.empty? || line.start_with?("#")
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
# Fail fixtures store identifiers as comment lines shaped
|
|
76
|
+
# "#IDENTIFIER# Parslet::ParseFailed: ...". Strip the leading # and
|
|
77
|
+
# the trailing historical annotation to recover the input.
|
|
78
|
+
def fail_fixture_lines(path)
|
|
79
|
+
File.readlines(path).filter_map do |raw|
|
|
80
|
+
line = raw.strip
|
|
81
|
+
next if line.empty?
|
|
82
|
+
next line unless line.start_with?("#")
|
|
83
|
+
|
|
84
|
+
input = line.sub(/\A#/, "").split("#", 2).first.to_s.strip
|
|
85
|
+
input unless input.empty?
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
def build_pass_cases(path, type, results)
|
|
90
|
+
groups = {}
|
|
91
|
+
debt = []
|
|
92
|
+
fixture_lines(path).each do |input|
|
|
93
|
+
record = build_record(input)
|
|
94
|
+
if record.key?(:debt)
|
|
95
|
+
debt << record[:debt]
|
|
96
|
+
next
|
|
97
|
+
end
|
|
98
|
+
key = JSON.generate(record[:case]["identifier"]) +
|
|
99
|
+
record[:case]["representations"]["human"]
|
|
100
|
+
(groups[key] ||= { record: record[:case],
|
|
101
|
+
inputs: [] })[:inputs] << input
|
|
102
|
+
end
|
|
103
|
+
cases = assign_ids(groups, type, results)
|
|
104
|
+
[cases, debt]
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
def assign_ids(groups, type, results)
|
|
108
|
+
groups.values.sort_by { |g| canonical_input(g) }.each_with_index
|
|
109
|
+
.map do |group, index|
|
|
110
|
+
record = group[:record]
|
|
111
|
+
record["id"] = format("%s.%s.%04d", @flavor, type, index + 1)
|
|
112
|
+
canonical = canonical_input(group)
|
|
113
|
+
record["style"] = Conformance.style_for(canonical)
|
|
114
|
+
inputs = group[:inputs]
|
|
115
|
+
duplicates = [inputs.count(canonical) - 1, 0].max
|
|
116
|
+
results[:duplicates] += duplicates
|
|
117
|
+
aliases = inputs.reject { |i| i == canonical }.uniq.sort
|
|
118
|
+
results[:aliases] += aliases.size
|
|
119
|
+
unless aliases.empty?
|
|
120
|
+
record["non_normalized_aliases"] = aliases.map do |a|
|
|
121
|
+
{ "input" => a, "style" => Conformance.style_for(a) }
|
|
122
|
+
end
|
|
123
|
+
end
|
|
124
|
+
results[:roundtrip_failures] += 1 if record["roundtrip"] == false
|
|
125
|
+
results[:cases] += 1
|
|
126
|
+
record
|
|
127
|
+
end
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
def canonical_input(group)
|
|
131
|
+
group.dig(:record, "representations", "human")
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
def build_record(input)
|
|
135
|
+
identifier = @flavor_module.parse(input)
|
|
136
|
+
hash = identifier.to_hash
|
|
137
|
+
representations = { "human" => identifier.to_s }
|
|
138
|
+
urn = safe_urn(identifier)
|
|
139
|
+
representations["urn"] = urn if urn
|
|
140
|
+
record = { "id" => nil,
|
|
141
|
+
"identifier" => Conformance.plainify(hash) }
|
|
142
|
+
record["representations"] = representations
|
|
143
|
+
record["roundtrip"] = false unless round_trips?(hash)
|
|
144
|
+
quarantine!(record) if bundled_month_bug?(hash)
|
|
145
|
+
{ case: record }
|
|
146
|
+
rescue StandardError => e
|
|
147
|
+
{ debt: { "id" => "#{@flavor}.debt.#{input.hash.abs}",
|
|
148
|
+
"input" => input,
|
|
149
|
+
"expect" => { "error" =>
|
|
150
|
+
{ "code" => Conformance.error_code_for(e) } },
|
|
151
|
+
"notes" => "unparsed ground-truth fixture: " \
|
|
152
|
+
"#{e.class}: #{e.message.to_s[0, 200]}" } }
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
# Reference implementation parses bundled directive supplements with
|
|
156
|
+
# month-bearing dates nondeterministically across load orders (a
|
|
157
|
+
# spurious day component appears). Quarantine deterministically.
|
|
158
|
+
def bundled_month_bug?(hash)
|
|
159
|
+
hash.to_s.include?("bundled_identifier") && hash.to_s.include?("month")
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
def quarantine!(record)
|
|
163
|
+
record.delete("identifier")
|
|
164
|
+
record.delete("representations")
|
|
165
|
+
record.delete("roundtrip")
|
|
166
|
+
record.delete("non_normalized_aliases")
|
|
167
|
+
record["notes"] = "nondeterministic parse in reference " \
|
|
168
|
+
"implementation (month/day divergence) - " \
|
|
169
|
+
"reference bug, quarantined from gates"
|
|
170
|
+
end
|
|
171
|
+
|
|
172
|
+
def round_trips?(hash)
|
|
173
|
+
@flavor_module::Identifier.from_hash(hash).to_hash == hash
|
|
174
|
+
rescue StandardError
|
|
175
|
+
false
|
|
176
|
+
end
|
|
177
|
+
|
|
178
|
+
def safe_urn(identifier)
|
|
179
|
+
identifier.to_urn
|
|
180
|
+
rescue StandardError
|
|
181
|
+
nil
|
|
182
|
+
end
|
|
183
|
+
|
|
184
|
+
def build_negative_cases(results)
|
|
185
|
+
cases = []
|
|
186
|
+
fail_files.each do |path|
|
|
187
|
+
type = File.basename(path, ".txt")
|
|
188
|
+
fail_fixture_lines(path).each_with_index do |input, index|
|
|
189
|
+
cases << negative_case(format("%s.neg.%s.%04d",
|
|
190
|
+
@flavor, type, index + 1), input)
|
|
191
|
+
results[:negative] += 1
|
|
192
|
+
end
|
|
193
|
+
end
|
|
194
|
+
cases
|
|
195
|
+
end
|
|
196
|
+
|
|
197
|
+
def negative_case(id, input)
|
|
198
|
+
@flavor_module.parse(input)
|
|
199
|
+
{ "id" => id, "input" => input, "style" => Conformance.style_for(input),
|
|
200
|
+
"notes" => "fail fixture unexpectedly parsed - reclassify" }
|
|
201
|
+
rescue StandardError => e
|
|
202
|
+
{ "id" => id, "input" => input,
|
|
203
|
+
"expect" => { "error" =>
|
|
204
|
+
{ "code" => Conformance.error_code_for(e) } } }
|
|
205
|
+
end
|
|
206
|
+
|
|
207
|
+
def write_yaml(path, entries)
|
|
208
|
+
File.write(path, YAML.dump(entries))
|
|
209
|
+
end
|
|
210
|
+
end
|
|
211
|
+
end
|
|
212
|
+
end
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Pubid
|
|
4
|
+
module Conformance
|
|
5
|
+
# Implementation-side PENDING markers: corpus cases this implementation
|
|
6
|
+
# explicitly cannot handle yet. The testsuite owns expectations; this
|
|
7
|
+
# file owns the admission that they are not met - so a pending case is
|
|
8
|
+
# visible debt, never a silent failure and never a hidden pass.
|
|
9
|
+
#
|
|
10
|
+
# Format (conformance/pending.yaml at the implementation repo root):
|
|
11
|
+
# "<case-id glob>":
|
|
12
|
+
# reason: <one line, the root cause>
|
|
13
|
+
# since: <YYYY-MM-DD>
|
|
14
|
+
# ref: <TODO.correct-test-suite PR queue entry or contract id>
|
|
15
|
+
#
|
|
16
|
+
# Rules enforced elsewhere: a pending case that passes raises the
|
|
17
|
+
# "pending satisfied - remove the marker" alarm; entries without a ref
|
|
18
|
+
# are rejected at load.
|
|
19
|
+
class Pending
|
|
20
|
+
PATH = File.expand_path("../../../conformance/pending.yaml", __dir__)
|
|
21
|
+
|
|
22
|
+
class << self
|
|
23
|
+
def for(case_id)
|
|
24
|
+
entry = registry[case_id]
|
|
25
|
+
return entry if entry
|
|
26
|
+
|
|
27
|
+
registry.each do |pattern, meta|
|
|
28
|
+
next if pattern == case_id
|
|
29
|
+
|
|
30
|
+
return meta if File.fnmatch(pattern, case_id)
|
|
31
|
+
end
|
|
32
|
+
nil
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def empty?
|
|
36
|
+
registry.empty?
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
private
|
|
40
|
+
|
|
41
|
+
def registry
|
|
42
|
+
@registry ||= load_registry
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def load_registry
|
|
46
|
+
return {} unless File.exist?(PATH)
|
|
47
|
+
|
|
48
|
+
(YAML.safe_load_file(PATH) || {})
|
|
49
|
+
.to_h { |pattern, meta| [pattern, validated(meta, pattern)] }
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def validated(meta, pattern)
|
|
53
|
+
unless meta.is_a?(Hash) && meta["reason"] && meta["ref"]
|
|
54
|
+
raise ArgumentError,
|
|
55
|
+
"pending entry #{pattern.inspect} needs reason and ref"
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
meta
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
end
|