pubid 1.15.19 → 2.0.0.pre.alpha.2
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/LICENSE.txt +1 -1
- data/README.adoc +2041 -53
- data/archived-gems/pubid-ccsds/update_codes.yaml +1 -0
- data/archived-gems/pubid-iec/stages.yaml +129 -0
- data/archived-gems/pubid-iec/update_codes.yaml +67 -0
- data/archived-gems/pubid-ieee/update_codes.yaml +104 -0
- data/archived-gems/pubid-iso/stages.yaml +106 -0
- data/archived-gems/pubid-iso/update_codes.yaml +4 -0
- data/archived-gems/pubid-itu/i18n.yaml +13 -0
- data/archived-gems/pubid-itu/series.yaml +42 -0
- data/archived-gems/pubid-nist/publishers.yaml +6 -0
- data/archived-gems/pubid-nist/series.yaml +121 -0
- data/archived-gems/pubid-nist/stages.yaml +16 -0
- data/archived-gems/pubid-nist/update_codes.yaml +93 -0
- data/archived-gems/pubid-plateau/update_codes.yaml +6 -0
- data/data/ccsds/update_codes.yaml +1 -0
- data/data/iec/update_codes.yaml +67 -0
- data/data/ieee/update_codes.yaml +104 -0
- data/data/iso/update_codes.yaml +21 -0
- data/data/nist/update_codes.yaml +89 -0
- data/data/plateau/update_codes.yaml +6 -0
- data/lib/pubid/amca/builder.rb +176 -0
- data/lib/pubid/amca/identifier.rb +57 -0
- data/lib/pubid/amca/identifiers/base.rb +64 -0
- data/lib/pubid/amca/identifiers/interpretation.rb +51 -0
- data/lib/pubid/amca/identifiers/publication.rb +47 -0
- data/lib/pubid/amca/identifiers/standard.rb +22 -0
- data/lib/pubid/amca/identifiers.rb +12 -0
- data/lib/pubid/amca/parser.rb +153 -0
- data/lib/pubid/amca/scheme.rb +16 -0
- data/lib/pubid/amca/single_identifier.rb +33 -0
- data/lib/pubid/amca/urn_generator.rb +50 -0
- data/lib/pubid/amca.rb +26 -0
- data/lib/pubid/ansi/builder.rb +52 -0
- data/lib/pubid/ansi/identifier.rb +55 -0
- data/lib/pubid/ansi/identifiers/american_national_standard.rb +12 -0
- data/lib/pubid/ansi/identifiers/standard.rb +16 -0
- data/lib/pubid/ansi/identifiers.rb +11 -0
- data/lib/pubid/ansi/parser.rb +91 -0
- data/lib/pubid/ansi/scheme.rb +15 -0
- data/lib/pubid/ansi/single_identifier.rb +45 -0
- data/lib/pubid/ansi/urn_generator.rb +76 -0
- data/lib/pubid/ansi.rb +27 -0
- data/lib/pubid/api/builder.rb +85 -0
- data/lib/pubid/api/components/code.rb +9 -0
- data/lib/pubid/api/identifier.rb +68 -0
- data/lib/pubid/api/identifiers/base.rb +24 -0
- data/lib/pubid/api/identifiers/bulletin.rb +15 -0
- data/lib/pubid/api/identifiers/continuous_operations_standard.rb +15 -0
- data/lib/pubid/api/identifiers/mpms.rb +44 -0
- data/lib/pubid/api/identifiers/publication.rb +15 -0
- data/lib/pubid/api/identifiers/recommended_practice.rb +15 -0
- data/lib/pubid/api/identifiers/specification.rb +15 -0
- data/lib/pubid/api/identifiers/standard.rb +15 -0
- data/lib/pubid/api/identifiers/technical_report.rb +15 -0
- data/lib/pubid/api/identifiers/typeless_standard.rb +27 -0
- data/lib/pubid/api/parser.rb +140 -0
- data/lib/pubid/api/scheme.rb +66 -0
- data/lib/pubid/api/single_identifier.rb +46 -0
- data/lib/pubid/api/urn_generator.rb +41 -0
- data/lib/pubid/api.rb +17 -0
- data/lib/pubid/ashrae/builder.rb +498 -0
- data/lib/pubid/ashrae/identifier.rb +57 -0
- data/lib/pubid/ashrae/identifiers/addenda_package.rb +46 -0
- data/lib/pubid/ashrae/identifiers/addendum.rb +55 -0
- data/lib/pubid/ashrae/identifiers/base.rb +23 -0
- data/lib/pubid/ashrae/identifiers/combined_addenda.rb +51 -0
- data/lib/pubid/ashrae/identifiers/errata.rb +40 -0
- data/lib/pubid/ashrae/identifiers/guideline.rb +38 -0
- data/lib/pubid/ashrae/identifiers/interpretation.rb +39 -0
- data/lib/pubid/ashrae/identifiers/standard.rb +38 -0
- data/lib/pubid/ashrae/identifiers.rb +16 -0
- data/lib/pubid/ashrae/parser.rb +724 -0
- data/lib/pubid/ashrae/scheme.rb +53 -0
- data/lib/pubid/ashrae/single_identifier.rb +23 -0
- data/lib/pubid/ashrae/supplement_identifier.rb +23 -0
- data/lib/pubid/ashrae/urn_generator.rb +59 -0
- data/lib/pubid/ashrae.rb +21 -0
- data/lib/pubid/asme/builder.rb +153 -0
- data/lib/pubid/asme/components/code.rb +18 -0
- data/lib/pubid/asme/identifier.rb +61 -0
- data/lib/pubid/asme/identifiers/base.rb +70 -0
- data/lib/pubid/asme/identifiers/standard.rb +12 -0
- data/lib/pubid/asme/identifiers.rb +10 -0
- data/lib/pubid/asme/parser.rb +308 -0
- data/lib/pubid/asme/scheme.rb +37 -0
- data/lib/pubid/asme/single_identifier.rb +29 -0
- data/lib/pubid/asme/urn_generator.rb +133 -0
- data/lib/pubid/asme.rb +21 -0
- data/lib/pubid/astm/builder.rb +159 -0
- data/lib/pubid/astm/components/code.rb +33 -0
- data/lib/pubid/astm/identifier.rb +92 -0
- data/lib/pubid/astm/identifiers/adjunct.rb +21 -0
- data/lib/pubid/astm/identifiers/base.rb +13 -0
- data/lib/pubid/astm/identifiers/data_series.rb +25 -0
- data/lib/pubid/astm/identifiers/iso_dual_published.rb +74 -0
- data/lib/pubid/astm/identifiers/manual.rb +40 -0
- data/lib/pubid/astm/identifiers/monograph.rb +25 -0
- data/lib/pubid/astm/identifiers/research_report.rb +18 -0
- data/lib/pubid/astm/identifiers/standard.rb +52 -0
- data/lib/pubid/astm/identifiers/technical_report.rb +23 -0
- data/lib/pubid/astm/identifiers/work_in_progress.rb +21 -0
- data/lib/pubid/astm/parser.rb +244 -0
- data/lib/pubid/astm/scheme.rb +55 -0
- data/lib/pubid/astm/single_identifier.rb +25 -0
- data/lib/pubid/astm/urn_generator.rb +99 -0
- data/lib/pubid/astm.rb +38 -0
- data/lib/pubid/bsi/builder.rb +1483 -0
- data/lib/pubid/bsi/components/code.rb +11 -0
- data/lib/pubid/bsi/components/date.rb +11 -0
- data/lib/pubid/bsi/components/publisher.rb +11 -0
- data/lib/pubid/bsi/components/type.rb +11 -0
- data/lib/pubid/bsi/identifier.rb +87 -0
- data/lib/pubid/bsi/identifiers/addendum_document.rb +64 -0
- data/lib/pubid/bsi/identifiers/adopted_european_norm.rb +95 -0
- data/lib/pubid/bsi/identifiers/adopted_international_standard.rb +82 -0
- data/lib/pubid/bsi/identifiers/aerospace_standard.rb +118 -0
- data/lib/pubid/bsi/identifiers/amendment.rb +40 -0
- data/lib/pubid/bsi/identifiers/base.rb +11 -0
- data/lib/pubid/bsi/identifiers/british_industrial_practice.rb +27 -0
- data/lib/pubid/bsi/identifiers/british_standard.rb +33 -0
- data/lib/pubid/bsi/identifiers/bundled_identifier.rb +114 -0
- data/lib/pubid/bsi/identifiers/committee_document.rb +51 -0
- data/lib/pubid/bsi/identifiers/consolidated_identifier.rb +152 -0
- data/lib/pubid/bsi/identifiers/corrigendum.rb +28 -0
- data/lib/pubid/bsi/identifiers/detailed_specification.rb +69 -0
- data/lib/pubid/bsi/identifiers/disc.rb +56 -0
- data/lib/pubid/bsi/identifiers/draft_document.rb +71 -0
- data/lib/pubid/bsi/identifiers/electronic_book.rb +52 -0
- data/lib/pubid/bsi/identifiers/expert_commentary.rb +47 -0
- data/lib/pubid/bsi/identifiers/explanatory_supplement.rb +82 -0
- data/lib/pubid/bsi/identifiers/flex.rb +61 -0
- data/lib/pubid/bsi/identifiers/handbook.rb +39 -0
- data/lib/pubid/bsi/identifiers/index.rb +62 -0
- data/lib/pubid/bsi/identifiers/method.rb +76 -0
- data/lib/pubid/bsi/identifiers/national_annex.rb +73 -0
- data/lib/pubid/bsi/identifiers/practice_guide.rb +27 -0
- data/lib/pubid/bsi/identifiers/publicly_available_specification.rb +79 -0
- data/lib/pubid/bsi/identifiers/published_document.rb +79 -0
- data/lib/pubid/bsi/identifiers/section.rb +62 -0
- data/lib/pubid/bsi/identifiers/set.rb +46 -0
- data/lib/pubid/bsi/identifiers/standalone_amendment.rb +40 -0
- data/lib/pubid/bsi/identifiers/supplement_document.rb +51 -0
- data/lib/pubid/bsi/identifiers/supplementary_index.rb +81 -0
- data/lib/pubid/bsi/identifiers/technical_specification.rb +79 -0
- data/lib/pubid/bsi/identifiers/test_method.rb +67 -0
- data/lib/pubid/bsi/identifiers/value_added_publication.rb +52 -0
- data/lib/pubid/bsi/identifiers.rb +52 -0
- data/lib/pubid/bsi/model.rb +196 -0
- data/lib/pubid/bsi/parser.rb +659 -0
- data/lib/pubid/bsi/scheme.rb +243 -0
- data/lib/pubid/bsi/single_identifier.rb +129 -0
- data/lib/pubid/bsi/urn_generator.rb +84 -0
- data/lib/pubid/bsi.rb +32 -0
- data/lib/pubid/builder/base.rb +138 -0
- data/lib/pubid/bundled_identifier.rb +126 -0
- data/lib/pubid/ccsds/builder.rb +56 -0
- data/lib/pubid/ccsds/identifier.rb +84 -0
- data/lib/pubid/ccsds/identifiers/base.rb +89 -0
- data/lib/pubid/ccsds/identifiers/base_BASE_88929.rb +70 -0
- data/lib/pubid/ccsds/identifiers/corrigendum.rb +39 -0
- data/lib/pubid/ccsds/identifiers.rb +10 -0
- data/lib/pubid/ccsds/parser.rb +71 -0
- data/lib/pubid/ccsds/scheme.rb +57 -0
- data/lib/pubid/ccsds/single_identifier.rb +77 -0
- data/lib/pubid/ccsds/supplement_identifier.rb +33 -0
- data/lib/pubid/ccsds/urn_generator.rb +115 -0
- data/lib/pubid/ccsds.rb +21 -0
- data/lib/pubid/cen_cenelec/builder.rb +330 -0
- data/lib/pubid/cen_cenelec/identifier.rb +52 -0
- data/lib/pubid/cen_cenelec/identifiers/adopted_european_norm.rb +40 -0
- data/lib/pubid/cen_cenelec/identifiers/amendment.rb +29 -0
- data/lib/pubid/cen_cenelec/identifiers/base.rb +75 -0
- data/lib/pubid/cen_cenelec/identifiers/cen_report.rb +28 -0
- data/lib/pubid/cen_cenelec/identifiers/cen_workshop_agreement.rb +27 -0
- data/lib/pubid/cen_cenelec/identifiers/cenelec_harmonization_document.rb +28 -0
- data/lib/pubid/cen_cenelec/identifiers/consolidated_identifier.rb +61 -0
- data/lib/pubid/cen_cenelec/identifiers/corrigendum.rb +35 -0
- data/lib/pubid/cen_cenelec/identifiers/european_norm.rb +41 -0
- data/lib/pubid/cen_cenelec/identifiers/european_prestandard.rb +37 -0
- data/lib/pubid/cen_cenelec/identifiers/european_specification.rb +28 -0
- data/lib/pubid/cen_cenelec/identifiers/fragment.rb +22 -0
- data/lib/pubid/cen_cenelec/identifiers/guide.rb +27 -0
- data/lib/pubid/cen_cenelec/identifiers/harmonization_document.rb +27 -0
- data/lib/pubid/cen_cenelec/identifiers/technical_report.rb +27 -0
- data/lib/pubid/cen_cenelec/identifiers/technical_specification.rb +35 -0
- data/lib/pubid/cen_cenelec/identifiers.rb +32 -0
- data/lib/pubid/cen_cenelec/parser.rb +144 -0
- data/lib/pubid/cen_cenelec/scheme.rb +164 -0
- data/lib/pubid/cen_cenelec/single_identifier.rb +130 -0
- data/lib/pubid/cen_cenelec/supplement_identifier.rb +48 -0
- data/lib/pubid/cen_cenelec/urn_generator.rb +129 -0
- data/lib/pubid/cen_cenelec.rb +21 -0
- data/lib/pubid/cie/builder.rb +399 -0
- data/lib/pubid/cie/components/code.rb +72 -0
- data/lib/pubid/cie/components/language.rb +58 -0
- data/lib/pubid/cie/identifier.rb +71 -0
- data/lib/pubid/cie/identifiers/bundle.rb +20 -0
- data/lib/pubid/cie/identifiers/conference.rb +32 -0
- data/lib/pubid/cie/identifiers/corrigendum.rb +40 -0
- data/lib/pubid/cie/identifiers/dual_published.rb +41 -0
- data/lib/pubid/cie/identifiers/identical.rb +64 -0
- data/lib/pubid/cie/identifiers/joint_published.rb +52 -0
- data/lib/pubid/cie/identifiers/standard.rb +58 -0
- data/lib/pubid/cie/identifiers/supplement.rb +45 -0
- data/lib/pubid/cie/identifiers/tutorial_bundle.rb +20 -0
- data/lib/pubid/cie/identifiers.rb +17 -0
- data/lib/pubid/cie/parser.rb +347 -0
- data/lib/pubid/cie/scheme.rb +64 -0
- data/lib/pubid/cie/single_identifier.rb +30 -0
- data/lib/pubid/cie/supplement_identifier.rb +26 -0
- data/lib/pubid/cie/urn_generator.rb +123 -0
- data/lib/pubid/cie.rb +28 -0
- data/lib/pubid/components/code.rb +33 -0
- data/lib/pubid/components/date.rb +49 -0
- data/lib/pubid/components/edition.rb +32 -0
- data/lib/pubid/components/factory.rb +50 -0
- data/lib/pubid/components/language.rb +37 -0
- data/lib/pubid/components/locality.rb +10 -0
- data/lib/pubid/components/publisher.rb +36 -0
- data/lib/pubid/components/stage.rb +54 -0
- data/lib/pubid/components/type.rb +58 -0
- data/lib/pubid/components/typed_stage.rb +59 -0
- data/lib/pubid/components.rb +16 -0
- data/lib/pubid/core/pattern_doc_generator.rb +272 -0
- data/lib/pubid/core/update_codes.rb +77 -0
- data/lib/pubid/core.rb +8 -0
- data/lib/pubid/csa/builder.rb +671 -0
- data/lib/pubid/csa/components/code.rb +9 -0
- data/lib/pubid/csa/components.rb +9 -0
- data/lib/pubid/csa/composite_identifier.rb +27 -0
- data/lib/pubid/csa/identifier.rb +513 -0
- data/lib/pubid/csa/identifiers/base.rb +133 -0
- data/lib/pubid/csa/identifiers/bundled.rb +125 -0
- data/lib/pubid/csa/identifiers/canadian_adopted.rb +82 -0
- data/lib/pubid/csa/identifiers/cec.rb +129 -0
- data/lib/pubid/csa/identifiers/combined.rb +130 -0
- data/lib/pubid/csa/identifiers/csa_adopted.rb +78 -0
- data/lib/pubid/csa/identifiers/package.rb +65 -0
- data/lib/pubid/csa/identifiers/series.rb +127 -0
- data/lib/pubid/csa/identifiers/standard.rb +10 -0
- data/lib/pubid/csa/identifiers.rb +17 -0
- data/lib/pubid/csa/parser.rb +445 -0
- data/lib/pubid/csa/scheme.rb +44 -0
- data/lib/pubid/csa/single_identifier.rb +30 -0
- data/lib/pubid/csa/urn_generator.rb +80 -0
- data/lib/pubid/csa/wrapper_identifier.rb +31 -0
- data/lib/pubid/csa.rb +25 -0
- data/lib/pubid/etsi/builder.rb +133 -0
- data/lib/pubid/etsi/components/code.rb +42 -0
- data/lib/pubid/etsi/components/version.rb +37 -0
- data/lib/pubid/etsi/components.rb +10 -0
- data/lib/pubid/etsi/identifier.rb +57 -0
- data/lib/pubid/etsi/identifiers/amendment.rb +15 -0
- data/lib/pubid/etsi/identifiers/base.rb +38 -0
- data/lib/pubid/etsi/identifiers/corrigendum.rb +15 -0
- data/lib/pubid/etsi/identifiers/etsi_standard.rb +19 -0
- data/lib/pubid/etsi/identifiers/supplement_identifier.rb +91 -0
- data/lib/pubid/etsi/identifiers.rb +14 -0
- data/lib/pubid/etsi/parser.rb +133 -0
- data/lib/pubid/etsi/scheme.rb +42 -0
- data/lib/pubid/etsi/urn_generator.rb +76 -0
- data/lib/pubid/etsi.rb +21 -0
- data/lib/pubid/export/auditor.rb +89 -0
- data/lib/pubid/export/data_class_exporter.rb +59 -0
- data/lib/pubid/export/exporter.rb +74 -0
- data/lib/pubid/export/flavor_exporter.rb +402 -0
- data/lib/pubid/export/ieee_exporter.rb +78 -0
- data/lib/pubid/export/itu_exporter.rb +66 -0
- data/lib/pubid/export/nist_exporter.rb +64 -0
- data/lib/pubid/export/registry_exporter.rb +90 -0
- data/lib/pubid/export/result.rb +97 -0
- data/lib/pubid/export/scheme_exporter.rb +70 -0
- data/lib/pubid/export.rb +18 -0
- data/lib/pubid/format_detector.rb +16 -0
- data/lib/pubid/format_registry.rb +42 -0
- data/lib/pubid/identifier.rb +242 -0
- data/lib/pubid/identifier_metadata.rb +148 -0
- data/lib/pubid/identifier_registry.rb +198 -0
- data/lib/pubid/idf/builder.rb +82 -0
- data/lib/pubid/idf/identifier.rb +129 -0
- data/lib/pubid/idf/identifiers/amendment.rb +27 -0
- data/lib/pubid/idf/identifiers/corrigendum.rb +27 -0
- data/lib/pubid/idf/identifiers/international_standard.rb +123 -0
- data/lib/pubid/idf/identifiers/reviewed_method.rb +100 -0
- data/lib/pubid/idf/identifiers.rb +13 -0
- data/lib/pubid/idf/parser.rb +143 -0
- data/lib/pubid/idf/scheme.rb +61 -0
- data/lib/pubid/idf/single_identifier.rb +19 -0
- data/lib/pubid/idf/supplement_identifier.rb +43 -0
- data/lib/pubid/idf/urn_generator.rb +84 -0
- data/lib/pubid/idf.rb +25 -0
- data/lib/pubid/iec/builder.rb +458 -0
- data/lib/pubid/iec/components/code.rb +60 -0
- data/lib/pubid/iec/components/consolidated_amendment.rb +59 -0
- data/lib/pubid/iec/components/publisher.rb +36 -0
- data/lib/pubid/iec/components/sheet.rb +32 -0
- data/lib/pubid/iec/components/trf_info.rb +38 -0
- data/lib/pubid/iec/components/vap_suffix.rb +41 -0
- data/lib/pubid/iec/identifier.rb +256 -0
- data/lib/pubid/iec/identifiers/amendment.rb +94 -0
- data/lib/pubid/iec/identifiers/base.rb +82 -0
- data/lib/pubid/iec/identifiers/component_specification.rb +39 -0
- data/lib/pubid/iec/identifiers/conformity_assessment.rb +39 -0
- data/lib/pubid/iec/identifiers/consolidated_identifier.rb +82 -0
- data/lib/pubid/iec/identifiers/corrigendum.rb +94 -0
- data/lib/pubid/iec/identifiers/fragment_identifier.rb +137 -0
- data/lib/pubid/iec/identifiers/guide.rb +104 -0
- data/lib/pubid/iec/identifiers/international_standard.rb +147 -0
- data/lib/pubid/iec/identifiers/interpretation_sheet.rb +104 -0
- data/lib/pubid/iec/identifiers/operational_document.rb +39 -0
- data/lib/pubid/iec/identifiers/publicly_available_specification.rb +101 -0
- data/lib/pubid/iec/identifiers/sheet_identifier.rb +62 -0
- data/lib/pubid/iec/identifiers/societal_technology_trend_report.rb +40 -0
- data/lib/pubid/iec/identifiers/systems_reference_document.rb +40 -0
- data/lib/pubid/iec/identifiers/technical_report.rb +132 -0
- data/lib/pubid/iec/identifiers/technical_specification.rb +132 -0
- data/lib/pubid/iec/identifiers/technology_report.rb +39 -0
- data/lib/pubid/iec/identifiers/test_report_form.rb +78 -0
- data/lib/pubid/iec/identifiers/vap_identifier.rb +73 -0
- data/lib/pubid/iec/identifiers/white_paper.rb +39 -0
- data/lib/pubid/iec/identifiers/working_document.rb +96 -0
- data/lib/pubid/iec/parser.rb +417 -0
- data/lib/pubid/iec/rendering_style.rb +113 -0
- data/lib/pubid/iec/scheme.rb +71 -0
- data/lib/pubid/iec/single_identifier.rb +80 -0
- data/lib/pubid/iec/supplement_identifier.rb +161 -0
- data/lib/pubid/iec/urn_generator.rb +79 -0
- data/lib/pubid/iec/urn_parser.rb +90 -0
- data/lib/pubid/iec.rb +85 -0
- data/lib/pubid/ieee/aiee/builder.rb +71 -0
- data/lib/pubid/ieee/aiee/identifier.rb +105 -0
- data/lib/pubid/ieee/aiee/parser.rb +130 -0
- data/lib/pubid/ieee/aiee.rb +11 -0
- data/lib/pubid/ieee/builder.rb +1237 -0
- data/lib/pubid/ieee/components/code.rb +102 -0
- data/lib/pubid/ieee/components/draft.rb +93 -0
- data/lib/pubid/ieee/components/relationship.rb +157 -0
- data/lib/pubid/ieee/components/typed_stage.rb +100 -0
- data/lib/pubid/ieee/identifier.rb +54 -0
- data/lib/pubid/ieee/identifiers/adopted_standard.rb +33 -0
- data/lib/pubid/ieee/identifiers/base.rb +591 -0
- data/lib/pubid/ieee/identifiers/conformance_identifier.rb +35 -0
- data/lib/pubid/ieee/identifiers/corrigendum.rb +37 -0
- data/lib/pubid/ieee/identifiers/csa_dual_published.rb +51 -0
- data/lib/pubid/ieee/identifiers/dual_identifier.rb +18 -0
- data/lib/pubid/ieee/identifiers/dual_published.rb +28 -0
- data/lib/pubid/ieee/identifiers/iec_ieee_copublished.rb +27 -0
- data/lib/pubid/ieee/identifiers/interpretation_identifier.rb +34 -0
- data/lib/pubid/ieee/identifiers/joint_development.rb +172 -0
- data/lib/pubid/ieee/identifiers/multi_numbered_identifier.rb +51 -0
- data/lib/pubid/ieee/identifiers/nesc/base.rb +56 -0
- data/lib/pubid/ieee/identifiers/nesc/draft.rb +28 -0
- data/lib/pubid/ieee/identifiers/nesc/handbook.rb +32 -0
- data/lib/pubid/ieee/identifiers/nesc/redline.rb +26 -0
- data/lib/pubid/ieee/identifiers/nesc/standard.rb +26 -0
- data/lib/pubid/ieee/identifiers/nesc.rb +15 -0
- data/lib/pubid/ieee/identifiers/parenthetical_identifier.rb +20 -0
- data/lib/pubid/ieee/identifiers/project_draft_identifier.rb +26 -0
- data/lib/pubid/ieee/identifiers/redlined_standard.rb +33 -0
- data/lib/pubid/ieee/identifiers/si_standard.rb +73 -0
- data/lib/pubid/ieee/identifiers/standard.rb +41 -0
- data/lib/pubid/ieee/identifiers/supplement_identifier.rb +23 -0
- data/lib/pubid/ieee/identifiers.rb +33 -0
- data/lib/pubid/ieee/ire/builder.rb +61 -0
- data/lib/pubid/ieee/ire/identifier.rb +58 -0
- data/lib/pubid/ieee/ire/parser.rb +91 -0
- data/lib/pubid/ieee/ire.rb +11 -0
- data/lib/pubid/ieee/nesc/builder.rb +101 -0
- data/lib/pubid/ieee/nesc/parser.rb +154 -0
- data/lib/pubid/ieee/nesc.rb +10 -0
- data/lib/pubid/ieee/parser.rb +1226 -0
- data/lib/pubid/ieee/scheme.rb +90 -0
- data/lib/pubid/ieee/typed_stages.rb +172 -0
- data/lib/pubid/ieee/urn_generator.rb +188 -0
- data/lib/pubid/ieee.rb +32 -0
- data/lib/pubid/ieee_debug.rb +31 -0
- data/lib/pubid/iho/builder.rb +37 -0
- data/lib/pubid/iho/identifier.rb +61 -0
- data/lib/pubid/iho/identifiers/base.rb +41 -0
- data/lib/pubid/iho/identifiers/bibliographic.rb +16 -0
- data/lib/pubid/iho/identifiers/circular_letter.rb +15 -0
- data/lib/pubid/iho/identifiers/miscellaneous.rb +16 -0
- data/lib/pubid/iho/identifiers/publication.rb +15 -0
- data/lib/pubid/iho/identifiers/standard.rb +15 -0
- data/lib/pubid/iho/identifiers.rb +14 -0
- data/lib/pubid/iho/parser.rb +68 -0
- data/lib/pubid/iho/scheme.rb +29 -0
- data/lib/pubid/iho/urn_generator.rb +29 -0
- data/lib/pubid/iho.rb +21 -0
- data/lib/pubid/iso/builder.rb +309 -0
- data/lib/pubid/iso/bundled_identifier.rb +85 -0
- data/lib/pubid/iso/combined_identifier.rb +22 -0
- data/lib/pubid/iso/components/code.rb +36 -0
- data/lib/pubid/iso/components/publisher.rb +60 -0
- data/lib/pubid/iso/components.rb +12 -0
- data/lib/pubid/iso/format_resolver.rb +45 -0
- data/lib/pubid/iso/identifier.rb +330 -0
- data/lib/pubid/iso/identifiers/addendum.rb +104 -0
- data/lib/pubid/iso/identifiers/amendment.rb +128 -0
- data/lib/pubid/iso/identifiers/base.rb +115 -0
- data/lib/pubid/iso/identifiers/corrigendum.rb +108 -0
- data/lib/pubid/iso/identifiers/data.rb +76 -0
- data/lib/pubid/iso/identifiers/directives.rb +59 -0
- data/lib/pubid/iso/identifiers/directives_supplement.rb +119 -0
- data/lib/pubid/iso/identifiers/extract.rb +30 -0
- data/lib/pubid/iso/identifiers/guide.rb +100 -0
- data/lib/pubid/iso/identifiers/international_standard.rb +168 -0
- data/lib/pubid/iso/identifiers/international_standardized_profile.rb +94 -0
- data/lib/pubid/iso/identifiers/international_workshop_agreement.rb +89 -0
- data/lib/pubid/iso/identifiers/pas.rb +93 -0
- data/lib/pubid/iso/identifiers/recommendation.rb +45 -0
- data/lib/pubid/iso/identifiers/supplement.rb +87 -0
- data/lib/pubid/iso/identifiers/tc_document.rb +108 -0
- data/lib/pubid/iso/identifiers/technical_report.rb +103 -0
- data/lib/pubid/iso/identifiers/technical_specification.rb +102 -0
- data/lib/pubid/iso/identifiers/technology_trends_assessments.rb +95 -0
- data/lib/pubid/iso/identifiers.rb +33 -0
- data/lib/pubid/iso/parser.rb +512 -0
- data/lib/pubid/iso/rendering_style.rb +120 -0
- data/lib/pubid/iso/scheme.rb +193 -0
- data/lib/pubid/iso/single_identifier.rb +64 -0
- data/lib/pubid/iso/supplement_identifier.rb +27 -0
- data/lib/pubid/iso/urn_generator.rb +426 -0
- data/lib/pubid/iso/urn_parser.rb +437 -0
- data/lib/pubid/iso/utilities.rb +86 -0
- data/lib/pubid/iso.rb +50 -0
- data/lib/pubid/itu/builder.rb +171 -0
- data/lib/pubid/itu/components/code.rb +39 -0
- data/lib/pubid/itu/components/sector.rb +35 -0
- data/lib/pubid/itu/components/series.rb +29 -0
- data/lib/pubid/itu/i18n.rb +9 -0
- data/lib/pubid/itu/i18n.yaml +30 -0
- data/lib/pubid/itu/identifier.rb +118 -0
- data/lib/pubid/itu/identifiers/amendment.rb +43 -0
- data/lib/pubid/itu/identifiers/annex.rb +74 -0
- data/lib/pubid/itu/identifiers/base.rb +154 -0
- data/lib/pubid/itu/identifiers/combined_identifier.rb +47 -0
- data/lib/pubid/itu/identifiers/corrigendum.rb +44 -0
- data/lib/pubid/itu/identifiers/recommendation.rb +16 -0
- data/lib/pubid/itu/identifiers/special_publication.rb +31 -0
- data/lib/pubid/itu/identifiers/supplement.rb +46 -0
- data/lib/pubid/itu/identifiers.rb +16 -0
- data/lib/pubid/itu/model.rb +111 -0
- data/lib/pubid/itu/parser.rb +225 -0
- data/lib/pubid/itu/scheme.rb +174 -0
- data/lib/pubid/itu/urn_generator.rb +105 -0
- data/lib/pubid/itu.rb +22 -0
- data/lib/pubid/jcgm/builder.rb +88 -0
- data/lib/pubid/jcgm/components/publisher.rb +20 -0
- data/lib/pubid/jcgm/components.rb +9 -0
- data/lib/pubid/jcgm/identifier.rb +54 -0
- data/lib/pubid/jcgm/identifiers/amendment.rb +35 -0
- data/lib/pubid/jcgm/identifiers/guide.rb +21 -0
- data/lib/pubid/jcgm/identifiers/gum_guide.rb +51 -0
- data/lib/pubid/jcgm/identifiers.rb +11 -0
- data/lib/pubid/jcgm/parser.rb +84 -0
- data/lib/pubid/jcgm/scheme.rb +60 -0
- data/lib/pubid/jcgm/single_identifier.rb +48 -0
- data/lib/pubid/jcgm/supplement_identifier.rb +16 -0
- data/lib/pubid/jcgm/urn_generator.rb +110 -0
- data/lib/pubid/jcgm.rb +31 -0
- data/lib/pubid/jis/builder.rb +124 -0
- data/lib/pubid/jis/components/code.rb +59 -0
- data/lib/pubid/jis/components.rb +9 -0
- data/lib/pubid/jis/identifier.rb +61 -0
- data/lib/pubid/jis/identifiers/amendment.rb +16 -0
- data/lib/pubid/jis/identifiers/base.rb +72 -0
- data/lib/pubid/jis/identifiers/explanation.rb +22 -0
- data/lib/pubid/jis/identifiers/japanese_industrial_standard.rb +16 -0
- data/lib/pubid/jis/identifiers/standard.rb +27 -0
- data/lib/pubid/jis/identifiers/technical_report.rb +31 -0
- data/lib/pubid/jis/identifiers/technical_specification.rb +31 -0
- data/lib/pubid/jis/identifiers.rb +17 -0
- data/lib/pubid/jis/parser.rb +109 -0
- data/lib/pubid/jis/scheme.rb +49 -0
- data/lib/pubid/jis/single_identifier.rb +37 -0
- data/lib/pubid/jis/supplement_identifier.rb +47 -0
- data/lib/pubid/jis/urn_generator.rb +25 -0
- data/lib/pubid/jis.rb +23 -0
- data/lib/pubid/lutaml/no_store_registration.rb +30 -0
- data/lib/pubid/nist/builder.rb +2269 -0
- data/lib/pubid/nist/components/code.rb +38 -0
- data/lib/pubid/nist/components/edition.rb +134 -0
- data/lib/pubid/nist/components/issue_number.rb +28 -0
- data/lib/pubid/nist/components/part.rb +77 -0
- data/lib/pubid/nist/components/publisher.rb +24 -0
- data/lib/pubid/nist/components/stage.rb +53 -0
- data/lib/pubid/nist/components/supplement.rb +188 -0
- data/lib/pubid/nist/components/translation.rb +42 -0
- data/lib/pubid/nist/components/update.rb +103 -0
- data/lib/pubid/nist/components/version.rb +35 -0
- data/lib/pubid/nist/components/volume.rb +32 -0
- data/lib/pubid/nist/components.rb +19 -0
- data/lib/pubid/nist/configuration.rb +77 -0
- data/lib/pubid/nist/identifier.rb +62 -0
- data/lib/pubid/nist/identifiers/base.rb +578 -0
- data/lib/pubid/nist/identifiers/circular.rb +68 -0
- data/lib/pubid/nist/identifiers/circular_supplement.rb +50 -0
- data/lib/pubid/nist/identifiers/commercial_standard.rb +41 -0
- data/lib/pubid/nist/identifiers/commercial_standard_emergency.rb +56 -0
- data/lib/pubid/nist/identifiers/commercial_standards_monthly.rb +56 -0
- data/lib/pubid/nist/identifiers/crpl_report.rb +132 -0
- data/lib/pubid/nist/identifiers/federal_information_processing_standards.rb +104 -0
- data/lib/pubid/nist/identifiers/grant_contractor_report.rb +35 -0
- data/lib/pubid/nist/identifiers/handbook.rb +50 -0
- data/lib/pubid/nist/identifiers/internal_report.rb +56 -0
- data/lib/pubid/nist/identifiers/letter_circular.rb +45 -0
- data/lib/pubid/nist/identifiers/miscellaneous_publication.rb +65 -0
- data/lib/pubid/nist/identifiers/monograph.rb +69 -0
- data/lib/pubid/nist/identifiers/ncstar.rb +41 -0
- data/lib/pubid/nist/identifiers/nsrds.rb +41 -0
- data/lib/pubid/nist/identifiers/owmwp.rb +35 -0
- data/lib/pubid/nist/identifiers/report.rb +67 -0
- data/lib/pubid/nist/identifiers/special_publication.rb +36 -0
- data/lib/pubid/nist/identifiers/technical_note.rb +90 -0
- data/lib/pubid/nist/identifiers.rb +33 -0
- data/lib/pubid/nist/parser.rb +1117 -0
- data/lib/pubid/nist/scheme.rb +199 -0
- data/lib/pubid/nist/supplement_identifier.rb +67 -0
- data/lib/pubid/nist/urn_generator.rb +133 -0
- data/lib/pubid/nist.rb +37 -0
- data/lib/pubid/oiml/builder.rb +189 -0
- data/lib/pubid/oiml/components/code.rb +20 -0
- data/lib/pubid/oiml/components.rb +9 -0
- data/lib/pubid/oiml/identifier.rb +61 -0
- data/lib/pubid/oiml/identifiers/amendment.rb +13 -0
- data/lib/pubid/oiml/identifiers/annex.rb +62 -0
- data/lib/pubid/oiml/identifiers/base.rb +36 -0
- data/lib/pubid/oiml/identifiers/basic_publication.rb +13 -0
- data/lib/pubid/oiml/identifiers/document.rb +13 -0
- data/lib/pubid/oiml/identifiers/expert_report.rb +13 -0
- data/lib/pubid/oiml/identifiers/guide.rb +13 -0
- data/lib/pubid/oiml/identifiers/recommendation.rb +13 -0
- data/lib/pubid/oiml/identifiers/seminar_report.rb +13 -0
- data/lib/pubid/oiml/identifiers/vocabulary.rb +13 -0
- data/lib/pubid/oiml/identifiers.rb +18 -0
- data/lib/pubid/oiml/parser.rb +173 -0
- data/lib/pubid/oiml/scheme.rb +46 -0
- data/lib/pubid/oiml/single_identifier.rb +90 -0
- data/lib/pubid/oiml/supplement_identifier.rb +43 -0
- data/lib/pubid/oiml/urn_generator.rb +64 -0
- data/lib/pubid/oiml.rb +26 -0
- data/lib/pubid/parser/common_parse_methods.rb +13 -0
- data/lib/pubid/parser/common_parse_rules.rb +56 -0
- data/lib/pubid/parser.rb +8 -0
- data/lib/pubid/parsers/base.rb +11 -0
- data/lib/pubid/parsers/mr_string.rb +93 -0
- data/lib/pubid/plateau/builder.rb +50 -0
- data/lib/pubid/plateau/identifier.rb +57 -0
- data/lib/pubid/plateau/identifiers/annex.rb +16 -0
- data/lib/pubid/plateau/identifiers/base.rb +51 -0
- data/lib/pubid/plateau/identifiers/handbook.rb +34 -0
- data/lib/pubid/plateau/identifiers/technical_report.rb +20 -0
- data/lib/pubid/plateau/identifiers.rb +12 -0
- data/lib/pubid/plateau/parser.rb +63 -0
- data/lib/pubid/plateau/scheme.rb +45 -0
- data/lib/pubid/plateau/supplement_identifier.rb +72 -0
- data/lib/pubid/plateau/urn_generator.rb +29 -0
- data/lib/pubid/plateau.rb +26 -0
- data/lib/pubid/renderers/base.rb +53 -0
- data/lib/pubid/renderers/directives_renderer.rb +61 -0
- data/lib/pubid/renderers/guide_renderer.rb +24 -0
- data/lib/pubid/renderers/human_readable.rb +70 -0
- data/lib/pubid/renderers/iwa_renderer.rb +20 -0
- data/lib/pubid/renderers/mr_string.rb +16 -0
- data/lib/pubid/renderers/supplement_renderer.rb +36 -0
- data/lib/pubid/renderers/urn.rb +11 -0
- data/lib/pubid/renderers.rb +14 -0
- data/lib/pubid/rendering/base.rb +73 -0
- data/lib/pubid/rendering/common.rb +211 -0
- data/lib/pubid/rendering/context.rb +159 -0
- data/lib/pubid/rendering/date.rb +27 -0
- data/lib/pubid/rendering/format.rb +25 -0
- data/lib/pubid/rendering/language.rb +21 -0
- data/lib/pubid/rendering/numbering.rb +24 -0
- data/lib/pubid/rendering/publisher.rb +25 -0
- data/lib/pubid/rendering/stage.rb +38 -0
- data/lib/pubid/rendering/supplement.rb +46 -0
- data/lib/pubid/rendering.rb +16 -0
- data/lib/pubid/sae/builder.rb +32 -0
- data/lib/pubid/sae/components/code.rb +9 -0
- data/lib/pubid/sae/components/date.rb +19 -0
- data/lib/pubid/sae/components/type.rb +19 -0
- data/lib/pubid/sae/components.rb +11 -0
- data/lib/pubid/sae/identifier.rb +37 -0
- data/lib/pubid/sae/identifiers/base.rb +42 -0
- data/lib/pubid/sae/identifiers.rb +9 -0
- data/lib/pubid/sae/parser.rb +55 -0
- data/lib/pubid/sae/scheme.rb +47 -0
- data/lib/pubid/sae/urn_generator.rb +38 -0
- data/lib/pubid/sae.rb +19 -0
- data/lib/pubid/scheme.rb +219 -0
- data/lib/pubid/urn_generator/base.rb +110 -0
- data/lib/pubid/utils/string_normalizer.rb +196 -0
- data/lib/pubid/utils.rb +7 -0
- data/lib/pubid/version.rb +3 -1
- data/lib/pubid.rb +137 -13
- data/lib/tasks/docs.rake +37 -0
- data/lib/tasks/export.rake +38 -0
- data/lib/tasks/website-data.json +7488 -0
- metadata +616 -171
- data/lib/pubid/registry.rb +0 -30
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "lutaml/model"
|
|
4
|
+
|
|
5
|
+
module Pubid
|
|
6
|
+
module Csa
|
|
7
|
+
# CompositeIdentifier is the base class for identifiers that contain
|
|
8
|
+
# collections of other identifiers or package materials.
|
|
9
|
+
#
|
|
10
|
+
# Examples:
|
|
11
|
+
# - PackageIdentifier: Base + package materials
|
|
12
|
+
# - Future: BundleIdentifier refactor to use composite
|
|
13
|
+
#
|
|
14
|
+
# This follows the Composite pattern where an identifier can contain
|
|
15
|
+
# other identifiers or additional metadata as a collection.
|
|
16
|
+
class CompositeIdentifier < Lutaml::Model::Serializable
|
|
17
|
+
# The primary/base identifier
|
|
18
|
+
# Use attr_accessor since it can be any identifier object
|
|
19
|
+
attr_accessor :base_identifier
|
|
20
|
+
|
|
21
|
+
# Subclasses MUST implement to_s to define how they render
|
|
22
|
+
def to_s
|
|
23
|
+
raise NotImplementedError, "Subclasses must implement to_s method"
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
@@ -0,0 +1,513 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Pubid
|
|
4
|
+
module Csa
|
|
5
|
+
class Identifier
|
|
6
|
+
# Factory that builds a CSA identifier from a hash of primitives.
|
|
7
|
+
# Default is {Identifiers::Standard}.
|
|
8
|
+
TYPE_KEY_TO_KLASS = {
|
|
9
|
+
standard: "Standard",
|
|
10
|
+
bundled: "Bundled",
|
|
11
|
+
canadian_adopted: "CanadianAdopted",
|
|
12
|
+
cec: "Cec",
|
|
13
|
+
combined: "Combined",
|
|
14
|
+
csa_adopted: "CsaAdopted",
|
|
15
|
+
package: "Package",
|
|
16
|
+
series: "Series",
|
|
17
|
+
}.freeze
|
|
18
|
+
|
|
19
|
+
def self.create(type: nil, **opts)
|
|
20
|
+
klass = resolve_create_class(type)
|
|
21
|
+
klass.new(**coerce_create_attrs(opts, klass: klass))
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def self.resolve_create_class(type)
|
|
25
|
+
return Identifiers::Standard if type.nil?
|
|
26
|
+
|
|
27
|
+
klass_name = TYPE_KEY_TO_KLASS[type.to_sym]
|
|
28
|
+
raise ArgumentError, "Unknown CSA type: #{type.inspect}" unless klass_name
|
|
29
|
+
|
|
30
|
+
Identifiers.const_get(klass_name)
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def self.coerce_create_attrs(opts, klass:)
|
|
34
|
+
attrs = {}
|
|
35
|
+
|
|
36
|
+
if (v = opts[:code] || opts[:number])
|
|
37
|
+
attrs[:code] = Pubid::Components::Code.new(value: v.to_s)
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
if opts[:year]
|
|
41
|
+
year_str = opts[:year].to_s
|
|
42
|
+
attrs[:year] = year_str
|
|
43
|
+
# Preserve 4-digit year rendering (e.g. "B51:2024") rather than
|
|
44
|
+
# collapsing to "B51:24".
|
|
45
|
+
attrs[:original_year_4digit] = year_str.length == 4 unless opts.key?(:original_year_4digit)
|
|
46
|
+
end
|
|
47
|
+
attrs[:original_year_4digit] = opts[:original_year_4digit] if opts.key?(:original_year_4digit)
|
|
48
|
+
attrs[:year_format] = opts[:year_format].to_s if opts[:year_format]
|
|
49
|
+
attrs[:year_prefix] = opts[:year_prefix].to_s if opts[:year_prefix]
|
|
50
|
+
attrs[:reaffirmation] = opts[:reaffirmation].to_s if opts[:reaffirmation]
|
|
51
|
+
attrs[:french] = opts[:french] if opts.key?(:french)
|
|
52
|
+
attrs[:has_publisher] = opts.fetch(:has_publisher, true)
|
|
53
|
+
attrs[:publisher_prefix] = opts[:publisher_prefix].to_s if opts[:publisher_prefix]
|
|
54
|
+
attrs[:series_prefix] = opts[:series_prefix].to_s if opts[:series_prefix]
|
|
55
|
+
attrs[:series] = opts[:series] if opts.key?(:series) && [true, false].include?(opts[:series])
|
|
56
|
+
attrs[:package] = opts[:package].to_s if opts[:package]
|
|
57
|
+
attrs[:no_number] = opts[:no_number].to_s if opts[:no_number]
|
|
58
|
+
attrs
|
|
59
|
+
end
|
|
60
|
+
private_class_method :resolve_create_class, :coerce_create_attrs
|
|
61
|
+
|
|
62
|
+
def self.parse(input)
|
|
63
|
+
# Filter out comments
|
|
64
|
+
return nil if input.start_with?("#")
|
|
65
|
+
|
|
66
|
+
# Filter out non-standards
|
|
67
|
+
return nil if input.match?(/^CSA (Communities|Group|Learning|OnDemand|Update)/)
|
|
68
|
+
|
|
69
|
+
# Preprocessing: normalize CEI to IEC (French name)
|
|
70
|
+
input = input.gsub("CEI/IEC", "IEC").gsub(/\bCEI\b/, "IEC")
|
|
71
|
+
|
|
72
|
+
# Detect CAN/ wrapper (Canadian adoption)
|
|
73
|
+
if input.start_with?("CAN/")
|
|
74
|
+
# Check if this is actually a bundled/combined identifier with + or /
|
|
75
|
+
# that should NOT be wrapped in CanadianAdopted
|
|
76
|
+
wrapped_input = input.sub(/^CAN\//, "")
|
|
77
|
+
|
|
78
|
+
# Check for bundled (+) or combined (/ or ,) patterns that should remain as-is
|
|
79
|
+
# These should be parsed normally, with publisher prefix applied to each part
|
|
80
|
+
# Patterns to detect:
|
|
81
|
+
# 1. Bundled: + separator (e.g., "CSA B127.1:99 + B127.2:99")
|
|
82
|
+
# 2. Combined with space: / separator with space before CSA- (e.g., "CSA A23.1:24/CSA A23.2:24")
|
|
83
|
+
# 3. Combined with CAN/CSA-: / separator with CSA- appearing multiple times (e.g., "CSA-B138.1-17/CSA-B138.2-17")
|
|
84
|
+
if wrapped_input.include?("+") ||
|
|
85
|
+
(wrapped_input.include?("/") && wrapped_input.match?(/\s+CSA-/)) ||
|
|
86
|
+
(wrapped_input.include?("/") && wrapped_input.scan("CSA-").length > 1)
|
|
87
|
+
# This is a bundled or combined identifier - parse normally and add prefix
|
|
88
|
+
# Normalize CSA- to CSA (with space) for parsing
|
|
89
|
+
normalized = wrapped_input.sub(/^CSA-/, "CSA ")
|
|
90
|
+
normalized = normalized.gsub("CAN/CSA-", "CSA ").gsub("CAN3-",
|
|
91
|
+
"CSA ")
|
|
92
|
+
normalized = normalized.gsub(/\s+/, " ").strip
|
|
93
|
+
|
|
94
|
+
# Parse normally (will create Bundled or Combined identifier)
|
|
95
|
+
tree = Parser.new.parse(normalized)
|
|
96
|
+
result = Builder.new.build(tree)
|
|
97
|
+
|
|
98
|
+
# Apply CAN/CSA- prefix to the appropriate parts
|
|
99
|
+
if result
|
|
100
|
+
set_publisher_prefix(result, "CAN/CSA-")
|
|
101
|
+
|
|
102
|
+
# Handle reaffirmation if present
|
|
103
|
+
if (wrapped_input =~ /\(R(\d{4})\)/) && result.class.attributes.key?(:reaffirmation)
|
|
104
|
+
result.reaffirmation = $1
|
|
105
|
+
end
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
return result
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
# This is a standard single identifier wrapped in CanadianAdopted
|
|
112
|
+
# Remove CAN/ prefix (already done above)
|
|
113
|
+
|
|
114
|
+
# Extract reaffirmation FIRST (before any other processing)
|
|
115
|
+
reaffirm_year = nil
|
|
116
|
+
reaffirmation_was_4digit = false # Track original format
|
|
117
|
+
if wrapped_input =~ /\(R(\d{2,4})\)/
|
|
118
|
+
reaffirm_year = $1
|
|
119
|
+
reaffirmation_was_4digit = ($1.length == 4) # Track if original was 4-digit
|
|
120
|
+
# Convert 2-digit year to 4-digit if needed
|
|
121
|
+
if reaffirm_year.length == 2
|
|
122
|
+
year_int = reaffirm_year.to_i
|
|
123
|
+
reaffirm_year = year_int < 50 ? "20#{reaffirm_year}" : "19#{reaffirm_year}"
|
|
124
|
+
end
|
|
125
|
+
wrapped_input = wrapped_input.sub(/\s*\(R\d{2,4}\)/, "")
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
# Detect and preserve original format (CSA- vs CSA)
|
|
129
|
+
# Also track that this is a CAN/CSA- identifier (not just CSA-)
|
|
130
|
+
original_prefix = if wrapped_input.start_with?("CSA-")
|
|
131
|
+
"CSA-"
|
|
132
|
+
elsif wrapped_input.start_with?("CSA ")
|
|
133
|
+
"CSA"
|
|
134
|
+
end
|
|
135
|
+
is_can_csa = true # Track that this has the CAN/ wrapper
|
|
136
|
+
|
|
137
|
+
# Normalize CSA- to CSA (with space) for parsing
|
|
138
|
+
wrapped_input = wrapped_input.sub(/^CSA-/, "CSA ")
|
|
139
|
+
|
|
140
|
+
# Parse the wrapped identifier recursively
|
|
141
|
+
wrapped_identifier = parse(wrapped_input)
|
|
142
|
+
return nil unless wrapped_identifier
|
|
143
|
+
|
|
144
|
+
# NOTE: Series identifiers should be wrapped in CanadianAdopted when
|
|
145
|
+
# they have CAN/CSA- prefix. The Series will handle rendering correctly.
|
|
146
|
+
# Do NOT return Series directly - always wrap in CanadianAdopted.
|
|
147
|
+
|
|
148
|
+
# Set publisher prefix on wrapped identifier
|
|
149
|
+
# For Series identifiers with CAN/ wrapper, use full "CAN/CSA-" prefix
|
|
150
|
+
# For other identifiers, use the detected original_prefix ("CSA-" or "CSA")
|
|
151
|
+
if wrapped_identifier.class.attributes.key?(:publisher_prefix)
|
|
152
|
+
if is_can_csa && wrapped_identifier.is_a?(Identifiers::Series)
|
|
153
|
+
# Series gets full "CAN/CSA-" prefix for proper rendering
|
|
154
|
+
wrapped_identifier.publisher_prefix = "CAN/CSA-"
|
|
155
|
+
elsif original_prefix
|
|
156
|
+
# For Combined identifiers, set on first identifier
|
|
157
|
+
if wrapped_identifier.is_a?(Identifiers::Combined) && wrapped_identifier.first
|
|
158
|
+
wrapped_identifier.first.publisher_prefix = original_prefix if wrapped_identifier.first.class.attributes.key?(:publisher_prefix)
|
|
159
|
+
else
|
|
160
|
+
# For non-Combined identifiers, set directly
|
|
161
|
+
wrapped_identifier.publisher_prefix = original_prefix
|
|
162
|
+
end
|
|
163
|
+
end
|
|
164
|
+
end
|
|
165
|
+
|
|
166
|
+
# Set reaffirmation on wrapped_identifier if it has the attribute
|
|
167
|
+
if wrapped_identifier.class.attributes.key?(:reaffirmation) && reaffirm_year
|
|
168
|
+
wrapped_identifier.reaffirmation = reaffirm_year
|
|
169
|
+
if wrapped_identifier.class.attributes.key?(:original_reaffirmation_4digit)
|
|
170
|
+
wrapped_identifier.original_reaffirmation_4digit = reaffirmation_was_4digit
|
|
171
|
+
end
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
# Create CanadianAdoptedIdentifier wrapper
|
|
175
|
+
result = Identifiers::CanadianAdopted.new
|
|
176
|
+
result.wrapped_identifier = wrapped_identifier
|
|
177
|
+
result.reaffirmation = reaffirm_year if reaffirm_year
|
|
178
|
+
|
|
179
|
+
return result
|
|
180
|
+
end
|
|
181
|
+
|
|
182
|
+
# Detect CAN3- wrapper (historical Canadian adoption)
|
|
183
|
+
if input.start_with?("CAN3-")
|
|
184
|
+
# This is a historical Canadian adoption - parse as wrapper
|
|
185
|
+
# Remove CAN3- prefix
|
|
186
|
+
wrapped_input = input.sub(/^CAN3-/, "CSA ")
|
|
187
|
+
|
|
188
|
+
# Detect year format before normalization (CAN3- standards use dash format)
|
|
189
|
+
# Format: CAN3-Z299.0-86 (uses dash, not colon)
|
|
190
|
+
has_dash_year = wrapped_input.match?(/-\d{2}\b/) # Match -86, -05, etc. (2-digit years)
|
|
191
|
+
|
|
192
|
+
# Extract reaffirmation FIRST (before any other processing)
|
|
193
|
+
reaffirm_year = nil
|
|
194
|
+
reaffirmation_was_4digit = false # Track original format
|
|
195
|
+
if wrapped_input =~ /\(R(\d{2,4})\)/
|
|
196
|
+
reaffirm_year = $1
|
|
197
|
+
reaffirmation_was_4digit = ($1.length == 4) # Track if original was 4-digit
|
|
198
|
+
# Convert 2-digit year to 4-digit if needed
|
|
199
|
+
if reaffirm_year.length == 2
|
|
200
|
+
year_int = reaffirm_year.to_i
|
|
201
|
+
reaffirm_year = year_int < 50 ? "20#{reaffirm_year}" : "19#{reaffirm_year}"
|
|
202
|
+
end
|
|
203
|
+
wrapped_input = wrapped_input.sub(/\s*\(R\d{2,4}\)/, "")
|
|
204
|
+
end
|
|
205
|
+
|
|
206
|
+
# Parse the wrapped identifier recursively
|
|
207
|
+
wrapped_identifier = parse(wrapped_input)
|
|
208
|
+
return nil unless wrapped_identifier
|
|
209
|
+
|
|
210
|
+
# Set year_format for dash format identifiers (preserve original 2-digit year)
|
|
211
|
+
if has_dash_year && wrapped_identifier.class.attributes.key?(:year_format)
|
|
212
|
+
wrapped_identifier.year_format = "dash"
|
|
213
|
+
# Mark original year as 2-digit so renderer converts back (1986 → 86)
|
|
214
|
+
if wrapped_identifier.class.attributes.key?(:original_year_4digit)
|
|
215
|
+
wrapped_identifier.original_year_4digit = false
|
|
216
|
+
end
|
|
217
|
+
end
|
|
218
|
+
|
|
219
|
+
# Check if this is a Series identifier - return it directly with CAN3- prefix
|
|
220
|
+
# Series identifiers are complete identifier types and handle the prefix themselves
|
|
221
|
+
# They don't need to be wrapped in CanadianAdopted
|
|
222
|
+
if wrapped_identifier.is_a?(Identifiers::Series)
|
|
223
|
+
wrapped_identifier.publisher_prefix = "CAN3-"
|
|
224
|
+
wrapped_identifier.reaffirmation = reaffirm_year if reaffirm_year
|
|
225
|
+
wrapped_identifier.original_reaffirmation_4digit = reaffirmation_was_4digit
|
|
226
|
+
return wrapped_identifier
|
|
227
|
+
end
|
|
228
|
+
|
|
229
|
+
# Set CAN3- as publisher prefix on wrapped identifier
|
|
230
|
+
if wrapped_identifier.class.attributes.key?(:publisher_prefix)
|
|
231
|
+
wrapped_identifier.publisher_prefix = "CAN3-"
|
|
232
|
+
end
|
|
233
|
+
|
|
234
|
+
# Set reaffirmation on wrapped_identifier if it has the attribute
|
|
235
|
+
if wrapped_identifier.class.attributes.key?(:reaffirmation) && reaffirm_year
|
|
236
|
+
wrapped_identifier.reaffirmation = reaffirm_year
|
|
237
|
+
if wrapped_identifier.class.attributes.key?(:original_reaffirmation_4digit)
|
|
238
|
+
wrapped_identifier.original_reaffirmation_4digit = reaffirmation_was_4digit
|
|
239
|
+
end
|
|
240
|
+
end
|
|
241
|
+
|
|
242
|
+
# Create CanadianAdoptedIdentifier wrapper
|
|
243
|
+
result = Identifiers::CanadianAdopted.new
|
|
244
|
+
result.wrapped_identifier = wrapped_identifier
|
|
245
|
+
result.reaffirmation = reaffirm_year if reaffirm_year
|
|
246
|
+
|
|
247
|
+
return result
|
|
248
|
+
end
|
|
249
|
+
|
|
250
|
+
# Detect CSA adoption of international standards
|
|
251
|
+
# Examples: CSA ISO/IEC TR 12785-3:15, CSA CISPR 16-1-1:18, CSA IEC 60601-1:08
|
|
252
|
+
# CSA CEI/IEC 61000-4-28-01 (bilingual)
|
|
253
|
+
if input.match?(/^CSA (ISO\/IEC|CEI\/IEC|CISPR|IEC|CEI|ISO)\s/)
|
|
254
|
+
# This is CSA adoption of international standard
|
|
255
|
+
# Extract the wrapped standard portion
|
|
256
|
+
wrapped_input = input.sub(/^CSA\s+/, "")
|
|
257
|
+
|
|
258
|
+
# Extract reaffirmation FIRST (before parsing)
|
|
259
|
+
reaffirm_year = nil
|
|
260
|
+
if wrapped_input =~ /\(R(\d{2,4})\)/
|
|
261
|
+
reaffirm_year = $1
|
|
262
|
+
# Convert 2-digit year to 4-digit if needed
|
|
263
|
+
if reaffirm_year.length == 2
|
|
264
|
+
year_int = reaffirm_year.to_i
|
|
265
|
+
reaffirm_year = year_int < 50 ? "20#{reaffirm_year}" : "19#{reaffirm_year}"
|
|
266
|
+
end
|
|
267
|
+
wrapped_input = wrapped_input.sub(/\s*\(R\d{2,4}\)/, "")
|
|
268
|
+
end
|
|
269
|
+
|
|
270
|
+
# Convert 2-digit years to 4-digit for external parser
|
|
271
|
+
# :15 → :2015, :04 → :2004
|
|
272
|
+
if wrapped_input =~ /:(\d{2})\b/
|
|
273
|
+
short_year_str = $1 # Keep as string "04", "15", etc.
|
|
274
|
+
short_year_int = short_year_str.to_i
|
|
275
|
+
# Determine century: 00-49 → 2000s, 50-99 → 1900s
|
|
276
|
+
full_year = short_year_int < 50 ? "20#{short_year_str}" : "19#{short_year_str}"
|
|
277
|
+
wrapped_input = wrapped_input.sub(/:#{short_year_str}\b/,
|
|
278
|
+
":#{full_year}")
|
|
279
|
+
end
|
|
280
|
+
|
|
281
|
+
# Convert CSA amendment format to ISO/IEC format
|
|
282
|
+
# /A1:22 → /Amd 1:2022, /A1-22 → /Amd 1-2022
|
|
283
|
+
# Also handle 2-digit and 4-digit amendment years (convert to 4-digit)
|
|
284
|
+
# Note: In gsub blocks with string regex, we must use $1, $2, $3
|
|
285
|
+
# because the block receives a String, not MatchData
|
|
286
|
+
wrapped_input = wrapped_input.gsub(%r{/A(\d+)([:/-])(\d{2,4})\b}) do
|
|
287
|
+
amendment_num = $1
|
|
288
|
+
separator = $2
|
|
289
|
+
amend_year_str = $3
|
|
290
|
+
amend_year_int = amend_year_str.to_i
|
|
291
|
+
# Convert 2-digit year to 4-digit if needed
|
|
292
|
+
if amend_year_str.length == 2
|
|
293
|
+
amend_full_year = amend_year_int < 50 ? "20#{amend_year_str}" : "19#{amend_year_str}"
|
|
294
|
+
else
|
|
295
|
+
amend_full_year = amend_year_str
|
|
296
|
+
end
|
|
297
|
+
"/Amd #{amendment_num}#{separator}#{amend_full_year}"
|
|
298
|
+
end
|
|
299
|
+
|
|
300
|
+
# Parse with appropriate flavor parser
|
|
301
|
+
wrapped_identifier = parse_external_standard(wrapped_input)
|
|
302
|
+
return nil unless wrapped_identifier
|
|
303
|
+
|
|
304
|
+
# Create CsaAdoptedIdentifier wrapper
|
|
305
|
+
result = Identifiers::CsaAdopted.new
|
|
306
|
+
result.wrapped_identifier = wrapped_identifier
|
|
307
|
+
result.reaffirmation = reaffirm_year if reaffirm_year
|
|
308
|
+
|
|
309
|
+
return result
|
|
310
|
+
end
|
|
311
|
+
|
|
312
|
+
# Detect package identifiers
|
|
313
|
+
# Examples: CSA Z662:23 PACKAGE INCLUDES: +1 (PDF & ESA)
|
|
314
|
+
# CSA B149.1:25 Code, Handbook & Training Package (materials BEFORE keyword)
|
|
315
|
+
# CSA B149.1:20 PACKAGE (PDF + PRINT) (no materials)
|
|
316
|
+
# CSA B108:23 PACKAGE (no trailing space)
|
|
317
|
+
if input.match?(/\sPACKAGE\b/i)
|
|
318
|
+
# Handle two formats:
|
|
319
|
+
# 1. {base} PACKAGE {materials} - materials after keyword
|
|
320
|
+
# 2. {base} {materials} PACKAGE - materials before keyword
|
|
321
|
+
|
|
322
|
+
# Check if materials come after PACKAGE keyword
|
|
323
|
+
# Match: "CSA Z662:23 PACKAGE INCLUDES: +1" or "CSA B149.1:20 PACKAGE (PDF + PRINT)"
|
|
324
|
+
case input
|
|
325
|
+
when /\sPACKAGE\s+[A-Z]/i
|
|
326
|
+
# Format: {base} PACKAGE {materials}
|
|
327
|
+
# Extract materials after PACKAGE keyword
|
|
328
|
+
base_input, package_materials = input.split(/\s+PACKAGE\s+/i, 2)
|
|
329
|
+
base_input = base_input.strip
|
|
330
|
+
package_materials = package_materials ? package_materials.strip : ""
|
|
331
|
+
materials_after = true
|
|
332
|
+
when /:(\d{2,4})(\s+[^P]+)\s+PACKAGE/i
|
|
333
|
+
# Format: {base} PACKAGE or {base} {materials} PACKAGE
|
|
334
|
+
# Examples: "C22.1-15 PACKAGE" (no materials), "CSA B149.1:25 Code, Handbook & Training Package"
|
|
335
|
+
|
|
336
|
+
# Check if there's a year followed by materials before PACKAGE
|
|
337
|
+
# Must check this BEFORE the generic "{base} PACKAGE" pattern
|
|
338
|
+
$1
|
|
339
|
+
$2
|
|
340
|
+
|
|
341
|
+
# Check if this is a combined identifier (has comma with CSA after it)
|
|
342
|
+
# Pattern: ", CSA" or ", CAN" which indicates combined identifier
|
|
343
|
+
if input.match?(/,\s+CSA/)
|
|
344
|
+
# For combined identifiers, we need to extract everything before "& Training Package"
|
|
345
|
+
# The base is the combined identifier, materials is just "& Training Package"
|
|
346
|
+
combined_match = input.match(/^(.+?)(\s+&[^P]+)\s+PACKAGE$/i)
|
|
347
|
+
if combined_match
|
|
348
|
+
base_input = combined_match[1].strip
|
|
349
|
+
package_materials = "#{combined_match[2].strip} Package" # Keep "& Training Package"
|
|
350
|
+
else
|
|
351
|
+
# Fallback to year-based extraction
|
|
352
|
+
year_match = input.match(/:\d{2,4}/)
|
|
353
|
+
if year_match
|
|
354
|
+
base_input = input[0..(year_match.end(0) - 1)]
|
|
355
|
+
materials_input = input[year_match.end(0)..].strip
|
|
356
|
+
package_materials = materials_input
|
|
357
|
+
end
|
|
358
|
+
end
|
|
359
|
+
else
|
|
360
|
+
# Standard single identifier with materials before PACKAGE
|
|
361
|
+
year_match = input.match(/:\d{2,4}/)
|
|
362
|
+
if year_match
|
|
363
|
+
base_input = input[0..(year_match.end(0) - 1)]
|
|
364
|
+
# Materials is everything between base and PACKAGE - keep the "Package" suffix for correct capitalization
|
|
365
|
+
materials_input = input[year_match.end(0)..].strip
|
|
366
|
+
package_materials = materials_input # Keep full materials including "Package" suffix
|
|
367
|
+
base_input = base_input.strip
|
|
368
|
+
end
|
|
369
|
+
end
|
|
370
|
+
materials_after = false
|
|
371
|
+
# Format: {base} {materials} PACKAGE - "CSA B149.1:25 Code, Handbook & Training Package"
|
|
372
|
+
# OR: Combined identifier with package: "CSA B149.1:25, CSA B149.2:25 & Training Package"
|
|
373
|
+
when /^(.+?)\s+PACKAGE\s*$/i
|
|
374
|
+
# Format: {base} PACKAGE (no materials) - "C22.1-15 PACKAGE"
|
|
375
|
+
# Treat PACKAGE as the package description
|
|
376
|
+
base_input = input.sub(/\s+PACKAGE\s*$/i, "").strip
|
|
377
|
+
package_materials = "" # No additional materials
|
|
378
|
+
materials_after = true
|
|
379
|
+
else
|
|
380
|
+
# Fallback: try parsing incrementally
|
|
381
|
+
tokens = input.split(/\s+/)
|
|
382
|
+
base_input = ""
|
|
383
|
+
tokens.each do |token|
|
|
384
|
+
break if token.match?(/^PACKAGE$/i)
|
|
385
|
+
|
|
386
|
+
test_input = base_input.empty? ? token : "#{base_input} #{token}"
|
|
387
|
+
parsed = parse(test_input)
|
|
388
|
+
if parsed
|
|
389
|
+
base_input = test_input
|
|
390
|
+
else
|
|
391
|
+
break
|
|
392
|
+
end
|
|
393
|
+
end
|
|
394
|
+
|
|
395
|
+
# Extract materials as everything between base and PACKAGE
|
|
396
|
+
if base_input && base_input.length < input.length
|
|
397
|
+
materials_input = input[base_input.length..].strip
|
|
398
|
+
package_materials = materials_input.sub(/\s+PACKAGE\s*$/i,
|
|
399
|
+
"").strip
|
|
400
|
+
materials_after = !package_materials.empty?
|
|
401
|
+
end
|
|
402
|
+
end
|
|
403
|
+
|
|
404
|
+
# Parse base identifier recursively
|
|
405
|
+
base_identifier = base_input ? parse(base_input) : nil
|
|
406
|
+
return nil unless base_identifier
|
|
407
|
+
|
|
408
|
+
# Create PackageIdentifier
|
|
409
|
+
result = Identifiers::Package.new
|
|
410
|
+
result.base_identifier = base_identifier
|
|
411
|
+
# Set materials if present
|
|
412
|
+
if package_materials && !package_materials.empty?
|
|
413
|
+
result.package_materials = package_materials
|
|
414
|
+
end
|
|
415
|
+
result.package_keyword = "PACKAGE"
|
|
416
|
+
# Set materials_after_keyword flag based on which format we detected
|
|
417
|
+
result.materials_after_keyword = materials_after
|
|
418
|
+
|
|
419
|
+
return result
|
|
420
|
+
end
|
|
421
|
+
|
|
422
|
+
# Legacy handling for CAN/CSA- and CAN3- (will be migrated to proper classes later)
|
|
423
|
+
# Detect original publisher prefix before normalization
|
|
424
|
+
publisher_prefix = if input.start_with?("CAN/CSA-")
|
|
425
|
+
"CAN/CSA-"
|
|
426
|
+
elsif input.start_with?("CAN3-")
|
|
427
|
+
"CAN3-"
|
|
428
|
+
elsif input.start_with?("CSA ")
|
|
429
|
+
"CSA"
|
|
430
|
+
end
|
|
431
|
+
|
|
432
|
+
# Detect year format before normalization
|
|
433
|
+
# CAN/CSA- standards use dash format: CAN/CSA-C22.2-05
|
|
434
|
+
# Modern CSA standards use colon format: CSA B149:20
|
|
435
|
+
has_dash_year = input.match?(/-\d{2}\b/)
|
|
436
|
+
|
|
437
|
+
# Normalize CAN/CSA- and CAN3- to CSA (global replacement for combined identifiers)
|
|
438
|
+
normalized = input.gsub("CAN/CSA-", "CSA ")
|
|
439
|
+
# Normalize CAN3- to CSA (historical prefix)
|
|
440
|
+
normalized = normalized.gsub("CAN3-", "CSA ")
|
|
441
|
+
|
|
442
|
+
tree = Parser.new.parse(normalized)
|
|
443
|
+
result = Builder.new.build(tree)
|
|
444
|
+
|
|
445
|
+
# Set publisher prefix if detected
|
|
446
|
+
if result && publisher_prefix
|
|
447
|
+
set_publisher_prefix(result, publisher_prefix)
|
|
448
|
+
end
|
|
449
|
+
|
|
450
|
+
# Set year format if detected as dash and not already set
|
|
451
|
+
if result && has_dash_year && result.year_format.nil?
|
|
452
|
+
result.year_format = "dash"
|
|
453
|
+
end
|
|
454
|
+
|
|
455
|
+
result
|
|
456
|
+
rescue Parslet::ParseFailed => e
|
|
457
|
+
raise e
|
|
458
|
+
end
|
|
459
|
+
|
|
460
|
+
def self.set_publisher_prefix(obj, prefix)
|
|
461
|
+
# Set on main object if it has the attribute
|
|
462
|
+
if obj.class.attributes.key?(:publisher_prefix)
|
|
463
|
+
obj.publisher_prefix = prefix
|
|
464
|
+
end
|
|
465
|
+
|
|
466
|
+
# Set on combined identifier parts
|
|
467
|
+
if obj.is_a?(Identifiers::Combined)
|
|
468
|
+
if obj.first&.class&.attributes&.key?(:publisher_prefix)
|
|
469
|
+
obj.first.publisher_prefix = prefix
|
|
470
|
+
end
|
|
471
|
+
if obj.second && obj.second.class.attributes.key?(:has_publisher) && obj.second.has_publisher && obj.second.class.attributes.key?(:publisher_prefix)
|
|
472
|
+
obj.second.publisher_prefix = prefix
|
|
473
|
+
end
|
|
474
|
+
if obj.third && obj.third.class.attributes.key?(:has_publisher) && obj.third.has_publisher && obj.third.class.attributes.key?(:publisher_prefix)
|
|
475
|
+
obj.third.publisher_prefix = prefix
|
|
476
|
+
end
|
|
477
|
+
end
|
|
478
|
+
|
|
479
|
+
# Set on bundled identifier base
|
|
480
|
+
if obj.is_a?(Identifiers::Bundled) && obj.base
|
|
481
|
+
set_publisher_prefix(obj.base, prefix)
|
|
482
|
+
end
|
|
483
|
+
end
|
|
484
|
+
|
|
485
|
+
def self.parse_external_standard(input)
|
|
486
|
+
# Ensure full Pubid is loaded (handles Scheme and all flavors)
|
|
487
|
+
require_relative "../../pubid" unless defined?(Pubid::Iso) && defined?(Pubid::Iec)
|
|
488
|
+
|
|
489
|
+
# Try ISO/IEC first (most common)
|
|
490
|
+
if input.match?(/^(ISO\/IEC|ISO|IEC|CEI|CEI\/IEC)\s/)
|
|
491
|
+
begin
|
|
492
|
+
# Normalize CEI/IEC to IEC for parsing (CEI is French for IEC)
|
|
493
|
+
normalized_input = input.sub(/^CEI\/IEC/, "IEC")
|
|
494
|
+
return Pubid::Iso.parse(normalized_input)
|
|
495
|
+
rescue StandardError
|
|
496
|
+
return nil
|
|
497
|
+
end
|
|
498
|
+
end
|
|
499
|
+
|
|
500
|
+
# Try CISPR (uses IEC parser)
|
|
501
|
+
if input.match?(/^CISPR\s/)
|
|
502
|
+
begin
|
|
503
|
+
return Pubid::Iec.parse(input)
|
|
504
|
+
rescue StandardError
|
|
505
|
+
return nil
|
|
506
|
+
end
|
|
507
|
+
end
|
|
508
|
+
|
|
509
|
+
nil
|
|
510
|
+
end
|
|
511
|
+
end
|
|
512
|
+
end
|
|
513
|
+
end
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Pubid
|
|
4
|
+
module Csa
|
|
5
|
+
module Identifiers
|
|
6
|
+
class Base < SingleIdentifier
|
|
7
|
+
def to_s
|
|
8
|
+
prefix = publisher_prefix || "CSA"
|
|
9
|
+
|
|
10
|
+
# Handle code_only identifiers (empty string means no prefix)
|
|
11
|
+
if prefix == ""
|
|
12
|
+
# No prefix for code_only identifiers
|
|
13
|
+
parts = []
|
|
14
|
+
else
|
|
15
|
+
# Determine if we need space after prefix
|
|
16
|
+
# CAN/CSA- and CAN3- end with dash, so no space needed
|
|
17
|
+
needs_space = !prefix.end_with?("-")
|
|
18
|
+
|
|
19
|
+
parts = []
|
|
20
|
+
parts << prefix
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
# Code and year together
|
|
24
|
+
code_part = code.to_s if code
|
|
25
|
+
|
|
26
|
+
# NO. keyword
|
|
27
|
+
if no_number
|
|
28
|
+
code_part += " NO. #{no_number}"
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
# Series prefix and keyword (before year)
|
|
32
|
+
if series_prefix
|
|
33
|
+
code_part += " #{series_prefix} SERIES"
|
|
34
|
+
elsif series
|
|
35
|
+
# SERIES without prefix
|
|
36
|
+
code_part += " SERIES"
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
parts << code_part if code_part
|
|
40
|
+
|
|
41
|
+
# Year with proper format (colon or dash)
|
|
42
|
+
if year
|
|
43
|
+
# Use dash if year_format is dash, otherwise colon
|
|
44
|
+
separator = year_format == "dash" ? "-" : ":"
|
|
45
|
+
year_part = separator
|
|
46
|
+
year_part += year_prefix if year_prefix # Add M or F prefix
|
|
47
|
+
year_part += "F" if french && year_format != "dash" && !year_prefix # Only add F if no prefix
|
|
48
|
+
# Convert 4-digit year back to 2-digit for M/F prefix preservation
|
|
49
|
+
# M1983 → M83, F1983 → F83, 1983 → 83, 20xx → xx
|
|
50
|
+
# However, preserve original 4-digit format if the input was 4-digit (original_year_4digit)
|
|
51
|
+
year_str = year.to_s
|
|
52
|
+
year_part += if original_year_4digit
|
|
53
|
+
# Preserve 4-digit format (e.g., "M1981" stays "M1981")
|
|
54
|
+
year_str
|
|
55
|
+
elsif year_prefix&.match?(/^[MF]$/) && year_str.length == 4 && year_str.start_with?("19")
|
|
56
|
+
# M/F + 4-digit year (1900s) → convert to 2-digit with prefix
|
|
57
|
+
year_str[2..3]
|
|
58
|
+
elsif year_str.length == 4 && year_str.start_with?("20")
|
|
59
|
+
# 2000s → just last 2 digits
|
|
60
|
+
year_str[2..3]
|
|
61
|
+
elsif year_str.length == 4 && year_str.start_with?("19") && !original_year_4digit
|
|
62
|
+
# 1900s with no M/F prefix, but original was 2-digit (e.g., CAN3-Z299.0-86)
|
|
63
|
+
# Convert back to 2-digit
|
|
64
|
+
year_str[2..3]
|
|
65
|
+
else
|
|
66
|
+
# Other formats - keep as-is
|
|
67
|
+
year_str
|
|
68
|
+
end
|
|
69
|
+
parts[-1] += year_part
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
result = if prefix == ""
|
|
73
|
+
# No prefix, just join parts
|
|
74
|
+
parts.join(" ")
|
|
75
|
+
elsif needs_space
|
|
76
|
+
parts.join(" ")
|
|
77
|
+
elsif parts.length == 2
|
|
78
|
+
# No space after dash-ending prefix - join first two parts directly
|
|
79
|
+
# If there are more parts after code, they should still have spaces
|
|
80
|
+
parts.join
|
|
81
|
+
else
|
|
82
|
+
# More than 2 parts shouldn't happen in current design
|
|
83
|
+
parts.join
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
# Reaffirmation - preserve original format and determine spacing
|
|
87
|
+
if reaffirmation
|
|
88
|
+
# Check if year was originally 2-digit (original_year_4digit flag)
|
|
89
|
+
year_was_2digit = !original_year_4digit
|
|
90
|
+
|
|
91
|
+
# Check if reaffirmation was originally 4-digit (original_reaffirmation_4digit flag)
|
|
92
|
+
reaffirmation_was_4digit = original_reaffirmation_4digit
|
|
93
|
+
|
|
94
|
+
# Preserve original reaffirmation format
|
|
95
|
+
# If original was 4-digit, keep as 4-digit
|
|
96
|
+
# If original was 2-digit, convert from 4-digit storage back to 2-digit
|
|
97
|
+
reaffirmation_str = if reaffirmation_was_4digit
|
|
98
|
+
# Original was 4-digit, keep as-is
|
|
99
|
+
reaffirmation.to_s
|
|
100
|
+
elsif reaffirmation.to_s.length == 4 && reaffirmation.to_s.start_with?(
|
|
101
|
+
"19", "20"
|
|
102
|
+
)
|
|
103
|
+
# Original was 2-digit, convert 4-digit storage back to 2-digit
|
|
104
|
+
# (R2004) → (R04), (R1994) → (R94)
|
|
105
|
+
reaffirmation.to_s[2..3]
|
|
106
|
+
else
|
|
107
|
+
# Already 2-digit or other format
|
|
108
|
+
reaffirmation.to_s
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
# Determine spacing based on original formats
|
|
112
|
+
# Space needed if year is 2-digit and reaffirmation is 4-digit (original format)
|
|
113
|
+
# No space if both year and reaffirmation are 2-digit, or both are 4-digit
|
|
114
|
+
if year_was_2digit && reaffirmation_was_4digit
|
|
115
|
+
# Year was 2-digit, reaffirmation was 4-digit → add space
|
|
116
|
+
result += " (R#{reaffirmation_str})"
|
|
117
|
+
else
|
|
118
|
+
# Both 2-digit, both 4-digit, or other cases → no space
|
|
119
|
+
result += "(R#{reaffirmation_str})"
|
|
120
|
+
end
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
# Package (already has leading space from parser)
|
|
124
|
+
if package
|
|
125
|
+
result += package
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
result
|
|
129
|
+
end
|
|
130
|
+
end
|
|
131
|
+
end
|
|
132
|
+
end
|
|
133
|
+
end
|