metanorma-iso 2.0.2 → 2.0.5

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.
Files changed (53) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +1 -1
  3. data/lib/isodoc/iso/html/html_iso_titlepage.html +1 -1
  4. data/lib/isodoc/iso/html/isodoc.css +1 -2
  5. data/lib/isodoc/iso/html/isodoc.scss +0 -1
  6. data/lib/isodoc/iso/html/word_iso_titlepage.html +1 -1
  7. data/lib/isodoc/iso/html/wordstyle.css +20 -0
  8. data/lib/isodoc/iso/html/wordstyle.scss +20 -0
  9. data/lib/isodoc/iso/i18n-en.yaml +29 -2
  10. data/lib/isodoc/iso/i18n-fr.yaml +27 -3
  11. data/lib/isodoc/iso/i18n-ru.yaml +45 -0
  12. data/lib/isodoc/iso/i18n-zh-Hans.yaml +27 -3
  13. data/lib/isodoc/iso/i18n.rb +1 -0
  14. data/lib/isodoc/iso/init.rb +1 -2
  15. data/lib/isodoc/iso/iso.amendment.xsl +1752 -807
  16. data/lib/isodoc/iso/iso.international-standard.xsl +1752 -807
  17. data/lib/isodoc/iso/metadata.rb +12 -2
  18. data/lib/isodoc/iso/presentation_xml_convert.rb +58 -21
  19. data/lib/metanorma/iso/basicdoc.rng +5 -3
  20. data/lib/metanorma/iso/biblio.rng +5 -3
  21. data/lib/metanorma/iso/boilerplate-fr.xml +3 -3
  22. data/lib/metanorma/iso/boilerplate-ru.xml +39 -0
  23. data/lib/metanorma/iso/boilerplate.xml +3 -3
  24. data/lib/metanorma/iso/cleanup.rb +42 -11
  25. data/lib/metanorma/iso/front.rb +1 -1
  26. data/lib/metanorma/iso/front_id.rb +1 -0
  27. data/lib/metanorma/iso/isodoc.rng +73 -3
  28. data/lib/metanorma/iso/processor.rb +14 -7
  29. data/lib/metanorma/iso/validate.rb +30 -2
  30. data/lib/metanorma/iso/validate_image.rb +3 -3
  31. data/lib/metanorma/iso/validate_list.rb +107 -0
  32. data/lib/metanorma/iso/validate_section.rb +42 -34
  33. data/lib/metanorma/iso/validate_style.rb +32 -2
  34. data/lib/metanorma/iso/validate_title.rb +13 -1
  35. data/lib/metanorma/iso/version.rb +1 -1
  36. data/spec/isodoc/amd_spec.rb +10 -5
  37. data/spec/isodoc/i18n_spec.rb +350 -9
  38. data/spec/isodoc/inline_spec.rb +127 -10
  39. data/spec/isodoc/metadata_spec.rb +153 -3
  40. data/spec/isodoc/postproc_spec.rb +3 -4
  41. data/spec/isodoc/section_spec.rb +1 -0
  42. data/spec/isodoc/terms_spec.rb +4 -4
  43. data/spec/isodoc/xref_spec.rb +18 -18
  44. data/spec/metanorma/base_spec.rb +434 -375
  45. data/spec/metanorma/cleanup_spec.rb +11 -11
  46. data/spec/metanorma/refs_spec.rb +333 -65
  47. data/spec/metanorma/section_spec.rb +15 -20
  48. data/spec/metanorma/validate_spec.rb +449 -14
  49. data/spec/spec_helper.rb +6 -4
  50. data/spec/vcr_cassettes/docrels.yml +211 -16
  51. data/spec/vcr_cassettes/withdrawn_iso.yml +301 -0
  52. metadata +6 -3
  53. data/spec/vcr_cassettes/sortrefs.yml +0 -599
@@ -5,7 +5,13 @@ RSpec.describe IsoDoc do
5
5
  input = <<~INPUT
6
6
  <iso-standard xmlns="http://riboseinc.com/isoxml">
7
7
  <bibdata>
8
+ <status>
9
+ <stage abbreviation='IS' language=''>60</stage>
10
+ </status>
8
11
  <language>en</language>
12
+ <ext>
13
+ <doctype language=''>international-standard</doctype>
14
+ </ext>
9
15
  </bibdata>
10
16
  <preface>
11
17
  <foreword obligation="informative">
@@ -85,8 +91,16 @@ RSpec.describe IsoDoc do
85
91
  presxml = <<~OUTPUT
86
92
  <iso-standard type="presentation" xmlns="http://riboseinc.com/isoxml">
87
93
  <bibdata>
88
- <language current="true">en</language>
89
- </bibdata>
94
+ <status>
95
+ <stage abbreviation='IS' language=''>60</stage>
96
+ <stage abbreviation='IS' language='en'>International standard</stage>
97
+ </status>
98
+ <language current='true'>en</language>
99
+ <ext>
100
+ <doctype language=''>international-standard</doctype>
101
+ <doctype language='en'>International Standard</doctype>
102
+ </ext>
103
+ </bibdata>
90
104
  <preface>
91
105
  <foreword obligation="informative" displayorder='1'>
92
106
  <title>Foreword</title>
@@ -263,7 +277,13 @@ RSpec.describe IsoDoc do
263
277
  .convert("test", <<~"INPUT", true)
264
278
  <iso-standard xmlns="http://riboseinc.com/isoxml">
265
279
  <bibdata>
280
+ <status>
281
+ <stage abbreviation='IS' language=''>60</stage>
282
+ </status>
266
283
  <language>tlh</language>
284
+ <ext>
285
+ <doctype language=''>international-standard</doctype>
286
+ </ext>
267
287
  </bibdata>
268
288
  <preface>
269
289
  <foreword obligation="informative">
@@ -344,8 +364,16 @@ RSpec.describe IsoDoc do
344
364
  .to be_equivalent_to xmlpp(<<~"OUTPUT")
345
365
  <iso-standard type="presentation" xmlns="http://riboseinc.com/isoxml">
346
366
  <bibdata>
347
- <language current="true">tlh</language>
348
- </bibdata>
367
+ <status>
368
+ <stage abbreviation='IS' language=''>60</stage>
369
+ <stage abbreviation='IS' language='tlh'>International standard</stage>
370
+ </status>
371
+ <language current='true'>tlh</language>
372
+ <ext>
373
+ <doctype language=''>international-standard</doctype>
374
+ <doctype language='tlh'>International Standard</doctype>
375
+ </ext>
376
+ </bibdata>
349
377
  <preface>
350
378
  <foreword obligation="informative" displayorder='1'>
351
379
  <title>Foreword</title>
@@ -438,7 +466,13 @@ RSpec.describe IsoDoc do
438
466
  input = <<~INPUT
439
467
  <iso-standard xmlns="http://riboseinc.com/isoxml">
440
468
  <bibdata>
469
+ <status>
470
+ <stage abbreviation='IS' language=''>60</stage>
471
+ </status>
441
472
  <language>fr</language>
473
+ <ext>
474
+ <doctype language=''>international-standard</doctype>
475
+ </ext>
442
476
  </bibdata>
443
477
  <preface>
444
478
  <foreword obligation="informative">
@@ -518,8 +552,16 @@ RSpec.describe IsoDoc do
518
552
  presxml = <<~OUTPUT
519
553
  <iso-standard type="presentation" xmlns="http://riboseinc.com/isoxml">
520
554
  <bibdata>
521
- <language current="true">fr</language>
522
- </bibdata>
555
+ <status>
556
+ <stage abbreviation='IS' language=''>60</stage>
557
+ <stage abbreviation='IS' language='fr'>Norme internationale</stage>
558
+ </status>
559
+ <language current='true'>fr</language>
560
+ <ext>
561
+ <doctype language=''>international-standard</doctype>
562
+ <doctype language='fr'>Norme internationale</doctype>
563
+ </ext>
564
+ </bibdata>
523
565
  <preface>
524
566
  <foreword obligation="informative" displayorder='1'>
525
567
  <title>Foreword</title>
@@ -701,12 +743,303 @@ RSpec.describe IsoDoc do
701
743
  .to be_equivalent_to xmlpp(html)
702
744
  end
703
745
 
746
+ it "processes Russian" do
747
+ input = <<~INPUT
748
+ <iso-standard xmlns="http://riboseinc.com/isoxml">
749
+ <bibdata>
750
+ <status>
751
+ <stage abbreviation='IS' language=''>60</stage>
752
+ </status>
753
+ <language>ru</language>
754
+ <ext>
755
+ <doctype language=''>international-standard</doctype>
756
+ </ext>
757
+ </bibdata>
758
+ <preface>
759
+ <foreword obligation="informative">
760
+ <title>Foreword</title>
761
+ <p id="A">This is a preamble</p>
762
+ </foreword>
763
+ <introduction id="B" obligation="informative">
764
+ <title>Introduction</title>
765
+ <clause id="C" inline-header="false" obligation="informative">
766
+ <title>Introduction Subsection</title>
767
+ </clause>
768
+ <p>This is patent boilerplate</p>
769
+ </introduction>
770
+ </preface>
771
+ <sections>
772
+ <clause id="D" obligation="normative" type="scope">
773
+ <title>Scope</title>
774
+ <p id="E">Text</p>
775
+ </clause>
776
+ <clause id="H" obligation="normative">
777
+ <title>Terms, definitions, symbols and abbreviated terms</title>
778
+ <terms id="I" obligation="normative">
779
+ <title>Normal Terms</title>
780
+ <term id="J">
781
+ <preferred><expression><name>Term2</name></expression></preferred>
782
+ </term>
783
+ </terms>
784
+ <definitions id="K">
785
+ <dl>
786
+ <dt>Symbol</dt>
787
+ <dd>Definition</dd>
788
+ </dl>
789
+ </definitions>
790
+ </clause>
791
+ <definitions id="L">
792
+ <dl>
793
+ <dt>Symbol</dt>
794
+ <dd>Definition</dd>
795
+ </dl>
796
+ </definitions>
797
+ <clause id="M" inline-header="false" obligation="normative">
798
+ <title>Clause 4</title>
799
+ <clause id="N" inline-header="false" obligation="normative">
800
+ <title>Introduction</title>
801
+ </clause>
802
+ <clause id="O" inline-header="false" obligation="normative">
803
+ <title>Clause 4.2</title>
804
+ </clause>
805
+ </clause>
806
+ </sections>
807
+ <annex id="P" inline-header="false" obligation="normative">
808
+ <title>Annex</title>
809
+ <clause id="Q" inline-header="false" obligation="normative">
810
+ <title>Annex A.1</title>
811
+ <clause id="Q1" inline-header="false" obligation="normative">
812
+ <title>Annex A.1a</title>
813
+ </clause>
814
+ </clause>
815
+ <appendix id="Q2" inline-header="false" obligation="normative">
816
+ <title>An Appendix</title>
817
+ </appendix>
818
+ </annex>
819
+ <bibliography>
820
+ <references id="R" normative="true" obligation="informative">
821
+ <title>Normative References</title>
822
+ </references>
823
+ <clause id="S" obligation="informative">
824
+ <title>Bibliography</title>
825
+ <references id="T" normative="false" obligation="informative">
826
+ <title>Bibliography Subsection</title>
827
+ </references>
828
+ </clause>
829
+ </bibliography>
830
+ </iso-standard>
831
+ INPUT
832
+
833
+ presxml = <<~OUTPUT
834
+ <iso-standard type="presentation" xmlns="http://riboseinc.com/isoxml">
835
+ <bibdata>
836
+ <status>
837
+ <stage abbreviation='IS' language=''>60</stage>
838
+ <stage abbreviation='IS' language='ru'>
839
+ &#x41C;&#x435;&#x436;&#x434;&#x443;&#x43D;&#x430;&#x440;&#x43E;&#x434;&#x43D;&#x44B;&#x439; &#x441;&#x442;&#x430;&#x43D;&#x434;&#x430;&#x440;&#x442;
840
+ </stage>
841
+ </status>
842
+ <language current='true'>ru</language>
843
+ <ext>
844
+ <doctype language=''>international-standard</doctype>
845
+ <doctype language='ru'>
846
+ &#x41C;&#x435;&#x436;&#x434;&#x443;&#x43D;&#x430;&#x440;&#x43E;&#x434;&#x43D;&#x44B;&#x439; &#x421;&#x442;&#x430;&#x43D;&#x434;&#x430;&#x440;&#x442;
847
+ </doctype>
848
+ </ext>
849
+ </bibdata>
850
+ <preface>
851
+ <foreword obligation="informative" displayorder='1'>
852
+ <title>Foreword</title>
853
+ <p id="A">This is a preamble</p>
854
+ </foreword>
855
+ <introduction id="B" obligation="informative" displayorder='2'>
856
+ <title depth="1">0<tab/>Introduction</title>
857
+ <clause id="C" inline-header="false" obligation="informative">
858
+ <title depth="2">0.1<tab/>Introduction Subsection</title>
859
+ </clause>
860
+ <p>This is patent boilerplate</p>
861
+ </introduction>
862
+ </preface>
863
+ <sections>
864
+ <clause id="D" obligation="normative" type="scope" displayorder='3'>
865
+ <title depth="1">1<tab/>Scope</title>
866
+ <p id="E">Text</p>
867
+ </clause>
868
+ <clause id="H" obligation="normative" displayorder='5'>
869
+ <title depth="1">3<tab/>Terms, definitions, symbols and abbreviated terms</title>
870
+ <terms id="I" obligation="normative">
871
+ <title depth="2">3.1<tab/>Normal Terms</title>
872
+ <term id="J">
873
+ <name>3.1.1</name>
874
+ <preferred><strong>Term2</strong></preferred>
875
+ </term>
876
+ </terms>
877
+ <definitions id="K" inline-header="true">
878
+ <title>3.2</title>
879
+ <dl>
880
+ <dt>Symbol</dt>
881
+ <dd>Definition</dd>
882
+ </dl>
883
+ </definitions>
884
+ </clause>
885
+ <definitions id="L" displayorder='6'>
886
+ <title>4</title>
887
+ <dl>
888
+ <dt>Symbol</dt>
889
+ <dd>Definition</dd>
890
+ </dl>
891
+ </definitions>
892
+ <clause id="M" inline-header="false" obligation="normative" displayorder='7'>
893
+ <title depth="1">5<tab/>Clause 4</title>
894
+ <clause id="N" inline-header="false" obligation="normative">
895
+ <title depth="2">5.1<tab/>Introduction</title>
896
+ </clause>
897
+ <clause id="O" inline-header="false" obligation="normative">
898
+ <title depth="2">5.2<tab/>Clause 4.2</title>
899
+ </clause>
900
+ </clause>
901
+ </sections>
902
+ <annex id="P" inline-header="false" obligation="normative" displayorder='8'>
903
+ <title>
904
+ <strong>&#x414;&#x43E;&#x43F;&#x43E;&#x43B;&#x43D;&#x435;&#x43D;&#x438;&#x435; A</strong>
905
+ <br/>(&#x43D;&#x43E;&#x440;&#x43C;&#x430;&#x442;&#x438;&#x432;&#x43D;&#x43E;&#x435;)
906
+ <br/>
907
+ <br/>
908
+ <strong>Annex</strong></title>
909
+ <clause id="Q" inline-header="false" obligation="normative">
910
+ <title depth="2">A.1<tab/>Annex A.1</title>
911
+ <clause id="Q1" inline-header="false" obligation="normative">
912
+ <title depth="3">A.1.1<tab/>Annex A.1a</title>
913
+ </clause>
914
+ </clause>
915
+ <appendix id="Q2" inline-header="false" obligation="normative">
916
+ <title depth="2"> &#x41F;&#x440;&#x438;&#x43B;&#x43E;&#x436;&#x435;&#x43D;&#x438;&#x435; 1<tab/>An Appendix</title>
917
+ </appendix>
918
+ </annex>
919
+ <bibliography>
920
+ <references id="R" normative="true" obligation="informative" displayorder='4'>
921
+ <title depth="1">2<tab/>Normative References</title>
922
+ </references>
923
+ <clause id="S" obligation="informative" displayorder='9'>
924
+ <title depth="1">Bibliography</title>
925
+ <references id="T" normative="false" obligation="informative">
926
+ <title depth="2">Bibliography Subsection</title>
927
+ </references>
928
+ </clause>
929
+ </bibliography>
930
+ </iso-standard>
931
+ OUTPUT
932
+
933
+ html = <<~OUTPUT
934
+ #{HTML_HDR.gsub(/"en"/, '"ru"')}
935
+ <br/>
936
+ <div>
937
+ <h1 class="ForewordTitle">Foreword</h1>
938
+ <p id="A">This is a preamble</p>
939
+ </div>
940
+ <br/>
941
+ <div class="Section3" id="B">
942
+ <h1 class="IntroTitle">0&#160; Introduction</h1>
943
+ <div id="C">
944
+ <h2>0.1&#160; Introduction Subsection</h2>
945
+ </div>
946
+ <p>This is patent boilerplate</p>
947
+ </div>
948
+ <p class="zzSTDTitle1"/>
949
+ <div id="D">
950
+ <h1>1&#160; Scope</h1>
951
+ <p id="E">Text</p>
952
+ </div>
953
+ <div>
954
+ <h1>2&#160; Normative References</h1>
955
+ </div>
956
+ <div id="H">
957
+ <h1>3&#160; Terms, definitions, symbols and abbreviated terms</h1>
958
+ <div id="I">
959
+ <h2>3.1&#160; Normal Terms</h2>
960
+ <p class="TermNum" id="J">3.1.1</p>
961
+ <p class="Terms" style="text-align:left;"><b>Term2</b></p>
962
+ </div>
963
+ <div id="K">
964
+ <span class="zzMoveToFollowing">
965
+ <b>3.2&#160; </b>
966
+ </span>
967
+ <dl>
968
+ <dt>
969
+ <p>Symbol</p>
970
+ </dt>
971
+ <dd>Definition</dd>
972
+ </dl>
973
+ </div>
974
+ </div>
975
+ <div class="Symbols" id="L">
976
+ <h1>4</h1>
977
+ <dl>
978
+ <dt>
979
+ <p>Symbol</p>
980
+ </dt>
981
+ <dd>Definition</dd>
982
+ </dl>
983
+ </div>
984
+ <div id="M">
985
+ <h1>5&#160; Clause 4</h1>
986
+ <div id="N">
987
+ <h2>5.1&#160; Introduction</h2>
988
+ </div>
989
+ <div id="O">
990
+ <h2>5.2&#160; Clause 4.2</h2>
991
+ </div>
992
+ </div>
993
+ <br/>
994
+ <div class="Section3" id="P">
995
+ <h1 class="Annex">
996
+ <b>&#1044;&#1086;&#1087;&#1086;&#1083;&#1085;&#1077;&#1085;&#1080;&#1077; A</b>
997
+ <br/>(&#1085;&#1086;&#1088;&#1084;&#1072;&#1090;&#1080;&#1074;&#1085;&#1086;&#1077;)
998
+ <br/>
999
+ <br/>
1000
+ <b>Annex</b></h1>
1001
+ <div id="Q">
1002
+ <h2>A.1&#160; Annex A.1</h2>
1003
+ <div id="Q1">
1004
+ <h3>A.1.1&#160; Annex A.1a</h3>
1005
+ </div>
1006
+ </div>
1007
+ <div id="Q2">
1008
+ <h2>&#1055;&#1088;&#1080;&#1083;&#1086;&#1078;&#1077;&#1085;&#1080;&#1077; 1&#160; An Appendix</h2>
1009
+ </div>
1010
+ </div>
1011
+ <br/>
1012
+ <div>
1013
+ <h1 class="Section3">Bibliography</h1>
1014
+ <div>
1015
+ <h2 class="Section3">Bibliography Subsection</h2>
1016
+ </div>
1017
+ </div>
1018
+ </div>
1019
+ </body>
1020
+ </html>
1021
+ OUTPUT
1022
+ expect(xmlpp(IsoDoc::Iso::PresentationXMLConvert.new({})
1023
+ .convert("test", input, true))
1024
+ .sub(%r{<localized-strings>.*</localized-strings>}m, ""))
1025
+ .to be_equivalent_to xmlpp(presxml)
1026
+ expect(xmlpp(IsoDoc::Iso::HtmlConvert.new({})
1027
+ .convert("test", presxml, true)))
1028
+ .to be_equivalent_to xmlpp(html)
1029
+ end
1030
+
704
1031
  it "processes Simplified Chinese" do
705
1032
  input = <<~INPUT
706
1033
  <iso-standard xmlns="http://riboseinc.com/isoxml">
707
1034
  <bibdata>
1035
+ <status>
1036
+ <stage abbreviation='IS' language=''>60</stage>
1037
+ </status>
708
1038
  <language>zh</language>
709
1039
  <script>Hans</script>
1040
+ <ext>
1041
+ <doctype language=''>international-standard</doctype>
1042
+ </ext>
710
1043
  </bibdata>
711
1044
  <preface>
712
1045
  <foreword obligation="informative">
@@ -802,9 +1135,17 @@ RSpec.describe IsoDoc do
802
1135
  presxml = <<~OUTPUT
803
1136
  <iso-standard type="presentation" xmlns="http://riboseinc.com/isoxml">
804
1137
  <bibdata>
805
- <language current="true">zh</language>
806
- <script current="true">Hans</script>
807
- </bibdata>
1138
+ <status>
1139
+ <stage abbreviation='IS' language=''>60</stage>
1140
+ <stage abbreviation='IS' language='zh'>&#x56FD;&#x9645;&#x6807;&#x51C6;</stage>
1141
+ </status>
1142
+ <language current='true'>zh</language>
1143
+ <script current='true'>Hans</script>
1144
+ <ext>
1145
+ <doctype language=''>international-standard</doctype>
1146
+ <doctype language='zh'>&#x56FD;&#x9645;&#x6807;&#x51C6;</doctype>
1147
+ </ext>
1148
+ </bibdata>
808
1149
  <preface>
809
1150
  <foreword obligation="informative" displayorder='1'>
810
1151
  <title>Foreword</title>
@@ -437,12 +437,12 @@ RSpec.describe IsoDoc do
437
437
  <li><concept><refterm>term6</refterm>
438
438
  <renderterm>word</renderterm>
439
439
  <eref bibitemid="ISO712" type="inline" citeas="ISO 712">
440
- <localityStack>
440
+ <localityStack connective="and">
441
441
  <locality type='clause'>
442
442
  <referenceFrom>3.1</referenceFrom>
443
443
  </locality>
444
444
  </localityStack>
445
- <localityStack>
445
+ <localityStack connective="and">
446
446
  <locality type='figure'>
447
447
  <referenceFrom>b</referenceFrom>
448
448
  </locality>
@@ -452,12 +452,12 @@ RSpec.describe IsoDoc do
452
452
  <li><concept><refterm>term7</refterm>
453
453
  <renderterm>word</renderterm>
454
454
  <eref bibitemid="ISO712" type="inline" citeas="ISO 712">
455
- <localityStack>
455
+ <localityStack connective="and">
456
456
  <locality type='clause'>
457
457
  <referenceFrom>3.1</referenceFrom>
458
458
  </locality>
459
459
  </localityStack>
460
- <localityStack>
460
+ <localityStack connective="and">
461
461
  <locality type='figure'>
462
462
  <referenceFrom>b</referenceFrom>
463
463
  </locality>
@@ -537,25 +537,25 @@ RSpec.describe IsoDoc do
537
537
  </li>
538
538
  <li>
539
539
  <em>word</em>
540
- (<eref bibitemid="ISO712" type="inline" citeas="ISO 712"><localityStack>
540
+ (<eref bibitemid="ISO712" type="inline" citeas="ISO 712"><localityStack connective="and">
541
541
  <locality type="clause">
542
542
  <referenceFrom>3.1</referenceFrom>
543
543
  </locality>
544
- </localityStack><localityStack>
544
+ </localityStack><localityStack connective="and">
545
545
  <locality type="figure">
546
546
  <referenceFrom>b</referenceFrom>
547
547
  </locality>
548
- </localityStack>ISO 712, 3.1; Figure b</eref>)
548
+ </localityStack>ISO 712, 3.1 and Figure b</eref>)
549
549
  </li>
550
550
  <li>
551
551
  <em>word</em>
552
552
  (<eref bibitemid="ISO712" type="inline" citeas="ISO 712">
553
- <localityStack>
553
+ <localityStack connective="and">
554
554
  <locality type="clause">
555
555
  <referenceFrom>3.1</referenceFrom>
556
556
  </locality>
557
557
  </localityStack>
558
- <localityStack>
558
+ <localityStack connective="and">
559
559
  <locality type="figure">
560
560
  <referenceFrom>b</referenceFrom>
561
561
  </locality>
@@ -658,7 +658,7 @@ RSpec.describe IsoDoc do
658
658
  <li>
659
659
  <i>word</i>
660
660
  (
661
- <a href='#ISO712'>ISO 712, 3.1; Figure b</a>
661
+ <a href='#ISO712'>ISO 712, 3.1 and Figure b</a>
662
662
  )
663
663
  </li>
664
664
  <li>
@@ -947,4 +947,121 @@ RSpec.describe IsoDoc do
947
947
  expect(xmlpp(IsoDoc::Iso::HtmlConvert.new({})
948
948
  .convert("test", presxml, true))).to be_equivalent_to xmlpp(output)
949
949
  end
950
+
951
+ it "combines locality stacks with connectives, omitting subclauses" do
952
+ input = <<~INPUT
953
+ <itu-standard xmlns="https://www.calconnect.org/standards/itu">
954
+ <p id='_'>
955
+ <eref type='inline' bibitemid='ref1' citeas='XYZ'>
956
+ <localityStack connective='from'>
957
+ <locality type='clause'>
958
+ <referenceFrom>3</referenceFrom>
959
+ </locality>
960
+ </localityStack>
961
+ <localityStack connective='to'>
962
+ <locality type='clause'>
963
+ <referenceFrom>5</referenceFrom>
964
+ </locality>
965
+ </localityStack>
966
+ </eref>
967
+ <eref type='inline' bibitemid='ref1' citeas='XYZ'>
968
+ <localityStack connective='from'>
969
+ <locality type='clause'>
970
+ <referenceFrom>3.1</referenceFrom>
971
+ </locality>
972
+ </localityStack>
973
+ <localityStack connective='to'>
974
+ <locality type='clause'>
975
+ <referenceFrom>5.1</referenceFrom>
976
+ </locality>
977
+ </localityStack>
978
+ </eref>
979
+ <eref type='inline' bibitemid='ref1' citeas='XYZ'>
980
+ <localityStack connective='from'>
981
+ <locality type='clause'>
982
+ <referenceFrom>3.1</referenceFrom>
983
+ </locality>
984
+ </localityStack>
985
+ <localityStack connective='to'>
986
+ <locality type='clause'>
987
+ <referenceFrom>5</referenceFrom>
988
+ </locality>
989
+ </localityStack>
990
+ </eref>
991
+ <eref type='inline' bibitemid='ref1' citeas='XYZ'>
992
+ <localityStack connective='from'>
993
+ <locality type='clause'>
994
+ <referenceFrom>3.1</referenceFrom>
995
+ </locality>
996
+ </localityStack>
997
+ <localityStack connective='to'>
998
+ <locality type='table'>
999
+ <referenceFrom>5</referenceFrom>
1000
+ </locality>
1001
+ </localityStack>
1002
+ </eref>
1003
+ </p>
1004
+ </itu-standard>
1005
+ INPUT
1006
+ output = <<~OUTPUT
1007
+ <itu-standard xmlns='https://www.calconnect.org/standards/itu' type='presentation'>
1008
+ <p id='_'>
1009
+ <eref type='inline' bibitemid='ref1' citeas='XYZ' droploc=''>
1010
+ <localityStack connective='from'>
1011
+ <locality type='clause'>
1012
+ <referenceFrom>3</referenceFrom>
1013
+ </locality>
1014
+ </localityStack>
1015
+ <localityStack connective='to'>
1016
+ <locality type='clause'>
1017
+ <referenceFrom>5</referenceFrom>
1018
+ </locality>
1019
+ </localityStack>
1020
+ XYZ, Clause 3 to 5
1021
+ </eref>
1022
+ <eref type='inline' bibitemid='ref1' citeas='XYZ' droploc=''>
1023
+ <localityStack connective='from'>
1024
+ <locality type='clause'>
1025
+ <referenceFrom>3.1</referenceFrom>
1026
+ </locality>
1027
+ </localityStack>
1028
+ <localityStack connective='to'>
1029
+ <locality type='clause'>
1030
+ <referenceFrom>5.1</referenceFrom>
1031
+ </locality>
1032
+ </localityStack>
1033
+ XYZ, 3.1 to 5.1
1034
+ </eref>
1035
+ <eref type='inline' bibitemid='ref1' citeas='XYZ'>
1036
+ <localityStack connective='from'>
1037
+ <locality type='clause'>
1038
+ <referenceFrom>3.1</referenceFrom>
1039
+ </locality>
1040
+ </localityStack>
1041
+ <localityStack connective='to'>
1042
+ <locality type='clause'>
1043
+ <referenceFrom>5</referenceFrom>
1044
+ </locality>
1045
+ </localityStack>
1046
+ XYZ, 3.1 to Clause 5
1047
+ </eref>
1048
+ <eref type='inline' bibitemid='ref1' citeas='XYZ'>
1049
+ <localityStack connective='from'>
1050
+ <locality type='clause'>
1051
+ <referenceFrom>3.1</referenceFrom>
1052
+ </locality>
1053
+ </localityStack>
1054
+ <localityStack connective='to'>
1055
+ <locality type='table'>
1056
+ <referenceFrom>5</referenceFrom>
1057
+ </locality>
1058
+ </localityStack>
1059
+ XYZ, 3.1 to Table 5
1060
+ </eref>
1061
+ </p>
1062
+ </itu-standard>
1063
+ OUTPUT
1064
+ expect(xmlpp(IsoDoc::Iso::PresentationXMLConvert.new({})
1065
+ .convert("test", input, true))).to be_equivalent_to xmlpp(output)
1066
+ end
950
1067
  end