@json-to-office/core-docx 4.5.0 → 5.3.0

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.
package/dist/index.js CHANGED
@@ -456,17 +456,38 @@ var init_devportal_docx_theme = __esm({
456
456
  accent5: "#8A9299",
457
457
  accent6: "#E8A18D"
458
458
  },
459
+ palette: {
460
+ rule: "#D8D5D1",
461
+ textMuted: "#737373",
462
+ onPrimary: "#FFFFFF",
463
+ surfaceInverse: "#12191F",
464
+ positive: "#2E7D4F",
465
+ negative: "#B42318",
466
+ chart: ["accent", "primary", "accent4", "accent5", "accent6", "rule"]
467
+ },
459
468
  fonts: {
460
- heading: { family: "Helvetica", size: 23 },
461
- body: { family: "Helvetica", size: 9.5 },
462
- mono: { family: "Courier New", size: 10 },
463
- light: { family: "Helvetica", size: 23 }
469
+ heading: {
470
+ family: "Helvetica",
471
+ size: 23
472
+ },
473
+ body: {
474
+ family: "Helvetica",
475
+ size: 9.5
476
+ },
477
+ mono: {
478
+ family: "Courier New",
479
+ size: 10
480
+ },
481
+ light: {
482
+ family: "Helvetica",
483
+ size: 23
484
+ }
464
485
  },
465
486
  page: {
466
487
  size: "A4",
467
488
  margins: {
468
- top: 1440,
469
- bottom: 1440,
489
+ top: 1080,
490
+ bottom: 1080,
470
491
  left: 1080,
471
492
  right: 1080,
472
493
  header: 720,
@@ -474,13 +495,183 @@ var init_devportal_docx_theme = __esm({
474
495
  gutter: 0
475
496
  }
476
497
  },
498
+ typography: {
499
+ roles: {
500
+ eyebrow: {
501
+ face: "heading",
502
+ size: 8,
503
+ weight: 700,
504
+ case: "upper",
505
+ tracking: 10,
506
+ color: "accent",
507
+ spaceAfter: 4
508
+ },
509
+ display: {
510
+ face: "heading",
511
+ weight: 700,
512
+ color: "primary",
513
+ lineHeight: 1.05,
514
+ spaceAfter: 8,
515
+ tracking: -2
516
+ },
517
+ stat: {
518
+ face: "heading",
519
+ weight: 700,
520
+ color: "accent",
521
+ lineHeight: 1
522
+ },
523
+ quote: {
524
+ face: "body",
525
+ color: "textSecondary",
526
+ lineHeight: 1.3
527
+ },
528
+ label: {
529
+ face: "body",
530
+ size: 9,
531
+ weight: 700,
532
+ color: "textSecondary",
533
+ case: "upper",
534
+ tracking: 6
535
+ },
536
+ footer: {
537
+ face: "body",
538
+ size: 8,
539
+ color: "textMuted"
540
+ },
541
+ tableHeader: {
542
+ face: "body",
543
+ size: 9,
544
+ weight: 700,
545
+ color: "secondary"
546
+ },
547
+ tableCell: {
548
+ face: "body",
549
+ size: 9.5,
550
+ color: "textPrimary"
551
+ },
552
+ chartLabel: {
553
+ face: "body",
554
+ size: 9,
555
+ weight: 400,
556
+ color: "textSecondary"
557
+ },
558
+ tracker: {
559
+ face: "body",
560
+ size: 8,
561
+ case: "upper",
562
+ tracking: 6,
563
+ color: "textMuted"
564
+ },
565
+ source: {
566
+ face: "body",
567
+ size: 8,
568
+ color: "textMuted"
569
+ }
570
+ },
571
+ scale: {
572
+ a4: {
573
+ base: 9.5,
574
+ ratio: 1.2,
575
+ baselinePt: 2
576
+ },
577
+ letter: {
578
+ base: 9.5,
579
+ ratio: 1.2,
580
+ baselinePt: 2
581
+ }
582
+ }
583
+ },
584
+ spacing: {
585
+ basePt: 7,
586
+ blockGap: {
587
+ tight: 3,
588
+ normal: 7,
589
+ loose: 14
590
+ },
591
+ canvas: {
592
+ a4: {
593
+ safeAreaIn: 0.75,
594
+ gutterIn: 0,
595
+ columns: 12
596
+ },
597
+ letter: {
598
+ safeAreaIn: 0.75,
599
+ gutterIn: 0,
600
+ columns: 12
601
+ }
602
+ }
603
+ },
604
+ chrome: {
605
+ runningHead: {
606
+ type: "tracker",
607
+ color: "textMuted",
608
+ rule: {
609
+ weightPt: 0.5,
610
+ color: "rule"
611
+ },
612
+ alignment: "right"
613
+ },
614
+ tracker: {
615
+ type: "tracker",
616
+ color: "textMuted",
617
+ alignment: "right"
618
+ },
619
+ actionTitle: {
620
+ type: "display",
621
+ color: "primary"
622
+ },
623
+ keyTakeaways: {
624
+ type: "label",
625
+ color: "primary",
626
+ rule: {
627
+ weightPt: 1,
628
+ color: "accent"
629
+ },
630
+ padPt: 8
631
+ },
632
+ sourceLine: {
633
+ type: "source",
634
+ color: "textMuted"
635
+ },
636
+ confidentialFooter: {
637
+ type: "footer",
638
+ color: "textMuted",
639
+ rule: {
640
+ weightPt: 0.5,
641
+ color: "rule"
642
+ },
643
+ alignment: "left"
644
+ },
645
+ logoSlot: {
646
+ alignment: "right"
647
+ },
648
+ cover: {
649
+ type: "display",
650
+ color: "primary",
651
+ rule: {
652
+ weightPt: 3,
653
+ color: "accent"
654
+ }
655
+ }
656
+ },
657
+ motif: {
658
+ kind: "rule",
659
+ color: "accent",
660
+ weightPt: 2,
661
+ placement: "top"
662
+ },
477
663
  styles: {
478
664
  normal: {
479
665
  font: "body",
480
666
  color: "textPrimary",
481
- lineSpacing: { type: "multiple", value: 1.3 },
667
+ lineSpacing: {
668
+ type: "multiple",
669
+ value: 1.3
670
+ },
482
671
  alignment: "left",
483
- spacing: { after: 7 }
672
+ spacing: {
673
+ after: 7
674
+ }
484
675
  },
485
676
  title: {
486
677
  font: "heading",
@@ -488,9 +679,18 @@ var init_devportal_docx_theme = __esm({
488
679
  bold: true,
489
680
  color: "primary",
490
681
  alignment: "left",
491
- lineSpacing: { type: "multiple", value: 1.02 },
492
- characterSpacing: { type: "condensed", value: 8 },
493
- spacing: { before: 0, after: 10 }
682
+ lineSpacing: {
683
+ type: "multiple",
684
+ value: 1.02
685
+ },
686
+ characterSpacing: {
687
+ type: "condensed",
688
+ value: 8
689
+ },
690
+ spacing: {
691
+ before: 0,
692
+ after: 10
693
+ }
494
694
  },
495
695
  subtitle: {
496
696
  font: "body",
@@ -498,16 +698,28 @@ var init_devportal_docx_theme = __esm({
498
698
  italic: false,
499
699
  color: "textSecondary",
500
700
  alignment: "left",
501
- lineSpacing: { type: "multiple", value: 1.25 },
502
- spacing: { before: 0, after: 12 }
701
+ lineSpacing: {
702
+ type: "multiple",
703
+ value: 1.25
704
+ },
705
+ spacing: {
706
+ before: 0,
707
+ after: 12
708
+ }
503
709
  },
504
710
  heading1: {
505
711
  font: "heading",
506
712
  size: 21,
507
713
  bold: true,
508
714
  color: "primary",
509
- lineSpacing: { type: "multiple", value: 1.15 },
510
- spacing: { before: 26, after: 12 },
715
+ lineSpacing: {
716
+ type: "multiple",
717
+ value: 1.15
718
+ },
719
+ spacing: {
720
+ before: 26,
721
+ after: 12
722
+ },
511
723
  keepNext: true,
512
724
  alignment: "left",
513
725
  borders: {
@@ -524,8 +736,14 @@ var init_devportal_docx_theme = __esm({
524
736
  size: 15.5,
525
737
  bold: true,
526
738
  color: "secondary",
527
- lineSpacing: { type: "multiple", value: 1.15 },
528
- spacing: { before: 20, after: 8 },
739
+ lineSpacing: {
740
+ type: "multiple",
741
+ value: 1.15
742
+ },
743
+ spacing: {
744
+ before: 20,
745
+ after: 8
746
+ },
529
747
  keepNext: true,
530
748
  alignment: "left"
531
749
  },
@@ -534,7 +752,10 @@ var init_devportal_docx_theme = __esm({
534
752
  size: 12.5,
535
753
  bold: true,
536
754
  color: "secondary",
537
- spacing: { before: 14, after: 6 },
755
+ spacing: {
756
+ before: 14,
757
+ after: 6
758
+ },
538
759
  keepNext: true,
539
760
  alignment: "left"
540
761
  },
@@ -543,7 +764,10 @@ var init_devportal_docx_theme = __esm({
543
764
  size: 11.5,
544
765
  bold: true,
545
766
  color: "textPrimary",
546
- spacing: { before: 12, after: 4 },
767
+ spacing: {
768
+ before: 12,
769
+ after: 4
770
+ },
547
771
  keepNext: true,
548
772
  alignment: "left"
549
773
  },
@@ -552,7 +776,10 @@ var init_devportal_docx_theme = __esm({
552
776
  size: 10.5,
553
777
  bold: true,
554
778
  color: "secondary",
555
- spacing: { before: 10, after: 4 },
779
+ spacing: {
780
+ before: 10,
781
+ after: 4
782
+ },
556
783
  keepNext: true,
557
784
  alignment: "left"
558
785
  },
@@ -561,8 +788,14 @@ var init_devportal_docx_theme = __esm({
561
788
  size: 10.5,
562
789
  bold: false,
563
790
  color: "textSecondary",
564
- characterSpacing: { type: "expanded", value: 20 },
565
- spacing: { before: 10, after: 4 },
791
+ characterSpacing: {
792
+ type: "expanded",
793
+ value: 20
794
+ },
795
+ spacing: {
796
+ before: 10,
797
+ after: 4
798
+ },
566
799
  keepNext: true,
567
800
  alignment: "left"
568
801
  },
@@ -571,24 +804,53 @@ var init_devportal_docx_theme = __esm({
571
804
  size: 11,
572
805
  bold: true,
573
806
  color: "primary",
574
- spacing: { before: 5, after: 3 },
575
- tabStops: [{ type: "right", position: 9746, leader: "dot" }]
807
+ spacing: {
808
+ before: 5,
809
+ after: 3
810
+ },
811
+ tabStops: [
812
+ {
813
+ type: "right",
814
+ position: 9746,
815
+ leader: "dot"
816
+ }
817
+ ]
576
818
  },
577
819
  TOC2: {
578
820
  font: "body",
579
821
  size: 10.5,
580
822
  color: "textPrimary",
581
- indent: { left: 240 },
582
- spacing: { after: 2 },
583
- tabStops: [{ type: "right", position: 9746, leader: "dot" }]
823
+ indent: {
824
+ left: 240
825
+ },
826
+ spacing: {
827
+ after: 2
828
+ },
829
+ tabStops: [
830
+ {
831
+ type: "right",
832
+ position: 9746,
833
+ leader: "dot"
834
+ }
835
+ ]
584
836
  },
585
837
  TOC3: {
586
838
  font: "body",
587
839
  size: 10,
588
840
  color: "textSecondary",
589
- indent: { left: 480 },
590
- spacing: { after: 2 },
591
- tabStops: [{ type: "right", position: 9746, leader: "dot" }]
841
+ indent: {
842
+ left: 480
843
+ },
844
+ spacing: {
845
+ after: 2
846
+ },
847
+ tabStops: [
848
+ {
849
+ type: "right",
850
+ position: 9746,
851
+ leader: "dot"
852
+ }
853
+ ]
592
854
  }
593
855
  },
594
856
  componentDefaults: {
@@ -596,22 +858,37 @@ var init_devportal_docx_theme = __esm({
596
858
  width: 100,
597
859
  borderColor: "#E2E0DD",
598
860
  borderSize: 0.5,
599
- hideBorders: { left: true, right: true, insideVertical: true },
861
+ hideBorders: {
862
+ left: true,
863
+ right: true,
864
+ insideVertical: true
865
+ },
600
866
  cellDefaults: {
601
- padding: { top: 3, bottom: 3 }
867
+ padding: {
868
+ top: 3,
869
+ bottom: 3
870
+ }
602
871
  },
603
872
  headerCellDefaults: {
604
- font: { bold: true },
873
+ font: {
874
+ bold: true
875
+ },
605
876
  color: "#172028",
606
877
  backgroundColor: "#F7ECE7",
607
- borderColor: { bottom: "#D8D5D1" },
608
- borderSize: { bottom: 1 }
878
+ borderColor: {
879
+ bottom: "#D8D5D1"
880
+ },
881
+ borderSize: {
882
+ bottom: 1
883
+ }
609
884
  }
610
885
  },
611
886
  list: {
612
887
  format: "bullet",
613
888
  bullet: "\u2014",
614
- spacing: { item: 2 }
889
+ spacing: {
890
+ item: 2
891
+ }
615
892
  },
616
893
  image: {
617
894
  alignment: "center"
@@ -650,7 +927,19 @@ var init_vermilion_docx_theme = __esm({
650
927
  borderPrimary: "#C7C8CA",
651
928
  borderSecondary: "#EFEAE4",
652
929
  backgroundPrimary: "#FFFFFF",
653
- backgroundSecondary: "#FAF7F5"
930
+ backgroundSecondary: "#FAF7F5",
931
+ accent4: "#F4857A",
932
+ accent5: "#F9C4BE",
933
+ accent6: "#939598"
934
+ },
935
+ palette: {
936
+ rule: "#C7C8CA",
937
+ textMuted: "#939598",
938
+ onPrimary: "#FFFFFF",
939
+ surfaceInverse: "#282829",
940
+ positive: "#2E7D4F",
941
+ negative: "#B42318",
942
+ chart: ["accent", "primary", "textMuted", "accent4", "rule", "accent5"]
654
943
  },
655
944
  fonts: {
656
945
  heading: {
@@ -673,28 +962,190 @@ var init_vermilion_docx_theme = __esm({
673
962
  page: {
674
963
  size: "A4",
675
964
  margins: {
676
- top: 1360,
677
- bottom: 1360,
678
- left: 1180,
679
- right: 1180,
965
+ top: 1152,
966
+ bottom: 1152,
967
+ left: 1152,
968
+ right: 1152,
680
969
  header: 620,
681
970
  footer: 620,
682
971
  gutter: 0
683
972
  }
684
973
  },
685
- styles: {
686
- normal: {
687
- font: "body",
688
- color: "textPrimary",
689
- lineSpacing: {
690
- type: "multiple",
691
- value: 1.3
974
+ typography: {
975
+ roles: {
976
+ eyebrow: {
977
+ face: "heading",
978
+ size: 8,
979
+ weight: 700,
980
+ case: "upper",
981
+ tracking: 8,
982
+ color: "accent",
983
+ spaceAfter: 4
692
984
  },
693
- alignment: "left",
694
- spacing: {
695
- after: 8
696
- }
697
- },
985
+ display: {
986
+ face: "heading",
987
+ weight: 700,
988
+ color: "accent",
989
+ lineHeight: 1.05,
990
+ spaceAfter: 8
991
+ },
992
+ stat: {
993
+ face: "heading",
994
+ weight: 700,
995
+ color: "accent",
996
+ lineHeight: 1
997
+ },
998
+ quote: {
999
+ face: "body",
1000
+ color: "textSecondary",
1001
+ lineHeight: 1.3
1002
+ },
1003
+ label: {
1004
+ face: "body",
1005
+ size: 9,
1006
+ weight: 700,
1007
+ color: "textSecondary"
1008
+ },
1009
+ footer: {
1010
+ face: "body",
1011
+ size: 8,
1012
+ color: "textMuted"
1013
+ },
1014
+ tableHeader: {
1015
+ face: "body",
1016
+ size: 9.5,
1017
+ weight: 700,
1018
+ color: "accent"
1019
+ },
1020
+ tableCell: {
1021
+ face: "body",
1022
+ size: 9.5,
1023
+ color: "textPrimary"
1024
+ },
1025
+ chartLabel: {
1026
+ face: "body",
1027
+ size: 9,
1028
+ weight: 400,
1029
+ color: "textSecondary"
1030
+ },
1031
+ tracker: {
1032
+ face: "body",
1033
+ size: 8,
1034
+ case: "upper",
1035
+ tracking: 6,
1036
+ color: "textMuted"
1037
+ },
1038
+ source: {
1039
+ face: "body",
1040
+ size: 8,
1041
+ color: "textMuted"
1042
+ }
1043
+ },
1044
+ scale: {
1045
+ a4: {
1046
+ base: 10.5,
1047
+ ratio: 1.25,
1048
+ baselinePt: 2
1049
+ },
1050
+ letter: {
1051
+ base: 10.5,
1052
+ ratio: 1.25,
1053
+ baselinePt: 2
1054
+ }
1055
+ }
1056
+ },
1057
+ spacing: {
1058
+ basePt: 8,
1059
+ blockGap: {
1060
+ tight: 4,
1061
+ normal: 8,
1062
+ loose: 16
1063
+ },
1064
+ canvas: {
1065
+ a4: {
1066
+ safeAreaIn: 0.8,
1067
+ gutterIn: 0,
1068
+ columns: 12
1069
+ },
1070
+ letter: {
1071
+ safeAreaIn: 0.8,
1072
+ gutterIn: 0,
1073
+ columns: 12
1074
+ }
1075
+ }
1076
+ },
1077
+ chrome: {
1078
+ runningHead: {
1079
+ type: "tracker",
1080
+ color: "textMuted",
1081
+ rule: {
1082
+ weightPt: 0.5,
1083
+ color: "rule"
1084
+ },
1085
+ alignment: "right"
1086
+ },
1087
+ tracker: {
1088
+ type: "tracker",
1089
+ color: "textMuted",
1090
+ alignment: "right"
1091
+ },
1092
+ actionTitle: {
1093
+ type: "display",
1094
+ color: "primary"
1095
+ },
1096
+ keyTakeaways: {
1097
+ type: "label",
1098
+ color: "primary",
1099
+ rule: {
1100
+ weightPt: 1.5,
1101
+ color: "accent"
1102
+ },
1103
+ padPt: 8
1104
+ },
1105
+ sourceLine: {
1106
+ type: "source",
1107
+ color: "textMuted"
1108
+ },
1109
+ confidentialFooter: {
1110
+ type: "footer",
1111
+ color: "textMuted",
1112
+ rule: {
1113
+ weightPt: 0.5,
1114
+ color: "rule"
1115
+ },
1116
+ alignment: "left"
1117
+ },
1118
+ logoSlot: {
1119
+ alignment: "right"
1120
+ },
1121
+ cover: {
1122
+ type: "display",
1123
+ color: "primary",
1124
+ rule: {
1125
+ weightPt: 4,
1126
+ color: "accent"
1127
+ }
1128
+ }
1129
+ },
1130
+ motif: {
1131
+ kind: "rule",
1132
+ color: "accent",
1133
+ weightPt: 4,
1134
+ placement: "top"
1135
+ },
1136
+ styles: {
1137
+ normal: {
1138
+ font: "body",
1139
+ color: "textPrimary",
1140
+ lineSpacing: {
1141
+ type: "multiple",
1142
+ value: 1.3
1143
+ },
1144
+ alignment: "left",
1145
+ spacing: {
1146
+ after: 8
1147
+ }
1148
+ },
698
1149
  heading1: {
699
1150
  font: "heading",
700
1151
  size: 25,
@@ -814,23 +1265,40 @@ var init_vermilion_docx_theme = __esm({
814
1265
  insideVertical: true
815
1266
  },
816
1267
  cellDefaults: {
817
- font: { size: 9.5 },
818
- padding: { top: 7, bottom: 7 },
1268
+ font: {
1269
+ size: 9.5
1270
+ },
1271
+ padding: {
1272
+ top: 7,
1273
+ bottom: 7
1274
+ },
819
1275
  verticalAlignment: "middle"
820
1276
  },
821
1277
  headerCellDefaults: {
822
1278
  color: "#EF4130",
823
- font: { size: 9.5, bold: true },
824
- padding: { top: 0, bottom: 8 },
1279
+ font: {
1280
+ size: 9.5,
1281
+ bold: true
1282
+ },
1283
+ padding: {
1284
+ top: 0,
1285
+ bottom: 8
1286
+ },
825
1287
  verticalAlignment: "bottom",
826
- borderColor: { bottom: "#EF4130" },
827
- borderSize: { bottom: 0.5 }
1288
+ borderColor: {
1289
+ bottom: "#EF4130"
1290
+ },
1291
+ borderSize: {
1292
+ bottom: 0.5
1293
+ }
828
1294
  }
829
1295
  },
830
1296
  list: {
831
1297
  format: "bullet",
832
1298
  bullet: "\u2014",
833
- spacing: { item: 2 }
1299
+ spacing: {
1300
+ item: 2
1301
+ }
834
1302
  },
835
1303
  image: {
836
1304
  alignment: "center"
@@ -14930,7 +15398,34 @@ var DOCX_QUALITY_PROFILES = {
14930
15398
  "technical-report": {
14931
15399
  id: "technical-report",
14932
15400
  formats: ["docx"],
14933
- description: "Portable professional report defaults."
15401
+ description: "Technical report or memo: numbered sections under a running head with page numbers on every section after the cover, a source wherever a block declares one, no heading skipped, every size on the theme scale with at most nine in play, no page rendered empty or left half blank, and at least one chart or table.",
15402
+ rules: {
15403
+ // A figure or table in a technical report cites where its numbers come
15404
+ // from; the takeaway is the client report's ask, the caption is the
15405
+ // block's own.
15406
+ "docx/required-chrome": { parameters: { required: ["source"] } },
15407
+ "docx/running-head": {
15408
+ parameters: {
15409
+ required: ["header", "footer", "pageNumber"],
15410
+ fromSection: 1
15411
+ }
15412
+ },
15413
+ "docx/heading-hierarchy": { severity: "warning" },
15414
+ "docx/type-scale": { enabled: true },
15415
+ // One more than the client report: the contents list paints TOC2 and
15416
+ // the sub-headings paint heading 2.
15417
+ "docx/size-count": { enabled: true, parameters: { maximumSizes: 9 } },
15418
+ "docx/role-drift": { enabled: true },
15419
+ "rendered/empty-page": { severity: "warning" },
15420
+ "rendered/page-underfilled": { severity: "warning" },
15421
+ // A technical report argues from measurements: a runs table, a chart.
15422
+ "docx/exhibit-required": { enabled: true }
15423
+ }
15424
+ },
15425
+ general: {
15426
+ id: "general",
15427
+ formats: ["docx"],
15428
+ description: "Any document that names no archetype: integrity and information-design rules at their defaults, nothing required by structure."
14934
15429
  },
14935
15430
  "legal-appendix": {
14936
15431
  id: "legal-appendix",
@@ -14938,7 +15433,7 @@ var DOCX_QUALITY_PROFILES = {
14938
15433
  description: "Dense appendix: preserve integrity without editorial taste."
14939
15434
  }
14940
15435
  };
14941
- var DOCX_DEFAULT_QUALITY_PROFILE = DOCX_QUALITY_PROFILES["technical-report"];
15436
+ var DOCX_DEFAULT_QUALITY_PROFILE = DOCX_QUALITY_PROFILES["general"];
14942
15437
  var DOCX_PROFILES_BY_ID = DOCX_QUALITY_PROFILES;
14943
15438
  function declaredDocxQualityProfile(document) {
14944
15439
  const props = document?.props;
@@ -15105,8 +15600,9 @@ init_styles();
15105
15600
 
15106
15601
  // src/blueprints/index.ts
15107
15602
  import {
15108
- blockDependencies,
15109
- validateBlueprint
15603
+ instantiateBlueprint,
15604
+ registerBlueprints,
15605
+ valueAt
15110
15606
  } from "@json-to-office/shared";
15111
15607
  import { collectPlaceholders as collectPlaceholders2 } from "@json-to-office/quality";
15112
15608
  import { existsSync, readdirSync, readFileSync as readFileSync2 } from "fs";
@@ -15220,7 +15716,789 @@ var client_report_docx_blueprint_default = {
15220
15716
  {
15221
15717
  name: "paragraph",
15222
15718
  props: {
15223
- text: "{{Body: two or three short paragraphs of evidence for the section title, each opening with its claim}}"
15719
+ text: "{{Body: two or three short paragraphs of evidence for the section title, each opening with its claim}}"
15720
+ }
15721
+ }
15722
+ ]
15723
+ },
15724
+ {
15725
+ name: "section",
15726
+ children: [
15727
+ {
15728
+ name: "block",
15729
+ props: {
15730
+ ref: "section-opener",
15731
+ slots: {
15732
+ number: "02",
15733
+ title: "{{Section title: the finding, as a statement}}"
15734
+ }
15735
+ }
15736
+ },
15737
+ {
15738
+ name: "paragraph",
15739
+ props: {
15740
+ text: "{{Body: two or three short paragraphs of evidence for the section title, each opening with its claim}}"
15741
+ }
15742
+ },
15743
+ {
15744
+ name: "block",
15745
+ props: {
15746
+ ref: "chart-figure",
15747
+ slots: {
15748
+ chart: {
15749
+ name: "highcharts",
15750
+ props: {
15751
+ width: "100%",
15752
+ options: {
15753
+ chart: {
15754
+ type: "column",
15755
+ width: 900,
15756
+ height: 460
15757
+ },
15758
+ title: {
15759
+ text: null
15760
+ },
15761
+ xAxis: {
15762
+ categories: [
15763
+ "{{Period 1}}",
15764
+ "{{Period 2}}",
15765
+ "{{Period 3}}"
15766
+ ]
15767
+ },
15768
+ yAxis: {
15769
+ title: {
15770
+ text: "{{Measure (unit)}}"
15771
+ }
15772
+ },
15773
+ series: [
15774
+ {
15775
+ name: "{{Series name}}",
15776
+ data: [0, 0, 0]
15777
+ }
15778
+ ]
15779
+ }
15780
+ }
15781
+ },
15782
+ caption: "{{Caption: what the chart shows, as a statement}}",
15783
+ takeaway: "{{Takeaway: the one sentence the reader should keep}}",
15784
+ source: "{{Source: system or document, date}}"
15785
+ }
15786
+ }
15787
+ },
15788
+ {
15789
+ name: "paragraph",
15790
+ props: {
15791
+ text: "{{Body: two or three short paragraphs of evidence for the section title, each opening with its claim}}"
15792
+ }
15793
+ }
15794
+ ]
15795
+ },
15796
+ {
15797
+ name: "section",
15798
+ children: [
15799
+ {
15800
+ name: "block",
15801
+ props: {
15802
+ ref: "section-opener",
15803
+ slots: {
15804
+ number: "03",
15805
+ title: "{{Section title: the finding, as a statement}}"
15806
+ }
15807
+ }
15808
+ },
15809
+ {
15810
+ name: "paragraph",
15811
+ props: {
15812
+ text: "{{Body: two or three short paragraphs of evidence for the section title, each opening with its claim}}"
15813
+ }
15814
+ },
15815
+ {
15816
+ name: "block",
15817
+ props: {
15818
+ ref: "data-table",
15819
+ slots: {
15820
+ title: "{{Table title: what it compares, and the period}}",
15821
+ labelHeader: "{{Row label}}",
15822
+ labels: ["{{Row 1}}", "{{Row 2}}", "{{Row 3}}"],
15823
+ columns: [
15824
+ {
15825
+ header: "{{Measure (unit)}}",
15826
+ cells: ["{{0.0}}", "{{0.0}}", "{{0.0}}"]
15827
+ },
15828
+ {
15829
+ header: "{{Change}}",
15830
+ cells: ["{{0.0}}", "{{0.0}}", "{{0.0}}"]
15831
+ }
15832
+ ],
15833
+ source: "{{Source: system or document, date}}"
15834
+ }
15835
+ }
15836
+ },
15837
+ {
15838
+ name: "block",
15839
+ props: {
15840
+ ref: "callout",
15841
+ slots: {
15842
+ label: "{{Note label}}",
15843
+ text: "{{Note: a caveat about the numbers, a definition or the method}}"
15844
+ }
15845
+ }
15846
+ }
15847
+ ]
15848
+ },
15849
+ {
15850
+ name: "section",
15851
+ children: [
15852
+ {
15853
+ name: "block",
15854
+ props: {
15855
+ ref: "section-opener",
15856
+ slots: {
15857
+ number: "04",
15858
+ title: "{{Section title: the finding, as a statement}}"
15859
+ }
15860
+ }
15861
+ },
15862
+ {
15863
+ name: "paragraph",
15864
+ props: {
15865
+ text: "{{Body: two or three short paragraphs of evidence for the section title, each opening with its claim}}"
15866
+ }
15867
+ },
15868
+ {
15869
+ name: "block",
15870
+ props: {
15871
+ ref: "footnotes"
15872
+ }
15873
+ }
15874
+ ]
15875
+ }
15876
+ ]
15877
+ },
15878
+ narrative: {
15879
+ description: "Argument-led: takeaways, then three sections of prose with one KPI row and one note as evidence, next steps last; one data table in the analysis section carries the numbers the argument leans on.",
15880
+ whenToUse: "The brief is a position, an assessment or a recommendation with few numbers; the reader follows an argument.",
15881
+ pages: {
15882
+ min: 3,
15883
+ max: 6
15884
+ },
15885
+ metadata: {
15886
+ title: "{{Title: as on the cover}}",
15887
+ author: "{{Author or team}}",
15888
+ company: "{{Client name}}",
15889
+ date: "{{Month YYYY}}"
15890
+ },
15891
+ children: [
15892
+ {
15893
+ name: "section",
15894
+ children: [
15895
+ {
15896
+ name: "block",
15897
+ props: {
15898
+ ref: "cover",
15899
+ slots: {
15900
+ title: "{{Title: the report's conclusion in one sentence}}",
15901
+ subtitle: "{{Subtitle: what the report answers, for whom}}",
15902
+ client: "{{Client name}}",
15903
+ date: "{{Month YYYY}}",
15904
+ confidentiality: "{{Confidentiality: Confidential, or For internal use}}"
15905
+ }
15906
+ }
15907
+ }
15908
+ ]
15909
+ },
15910
+ {
15911
+ name: "section",
15912
+ children: [
15913
+ {
15914
+ name: "block",
15915
+ props: {
15916
+ ref: "running-head",
15917
+ slots: {
15918
+ confidentiality: "{{Confidentiality: as on the cover}}",
15919
+ date: "{{Month YYYY}}"
15920
+ }
15921
+ }
15922
+ },
15923
+ {
15924
+ name: "block",
15925
+ props: {
15926
+ ref: "section-opener",
15927
+ slots: {
15928
+ number: "01",
15929
+ title: "{{Section title: the finding, as a statement}}"
15930
+ }
15931
+ }
15932
+ },
15933
+ {
15934
+ name: "block",
15935
+ props: {
15936
+ ref: "key-takeaways",
15937
+ slots: {
15938
+ items: [
15939
+ "{{Takeaway 1: one claim, one sentence, with its number}}",
15940
+ "{{Takeaway 2: one claim, one sentence, with its number}}",
15941
+ "{{Takeaway 3: the recommendation that follows}}"
15942
+ ]
15943
+ }
15944
+ }
15945
+ },
15946
+ {
15947
+ name: "paragraph",
15948
+ props: {
15949
+ text: "{{Body: two or three short paragraphs of evidence for the section title, each opening with its claim}}"
15950
+ }
15951
+ },
15952
+ {
15953
+ name: "paragraph",
15954
+ props: {
15955
+ text: "{{Body: two or three short paragraphs of evidence for the section title, each opening with its claim}}"
15956
+ }
15957
+ }
15958
+ ]
15959
+ },
15960
+ {
15961
+ name: "section",
15962
+ children: [
15963
+ {
15964
+ name: "block",
15965
+ props: {
15966
+ ref: "section-opener",
15967
+ slots: {
15968
+ number: "02",
15969
+ title: "{{Section title: the finding, as a statement}}"
15970
+ }
15971
+ }
15972
+ },
15973
+ {
15974
+ name: "paragraph",
15975
+ props: {
15976
+ text: "{{Body: two or three short paragraphs of evidence for the section title, each opening with its claim}}"
15977
+ }
15978
+ },
15979
+ {
15980
+ name: "block",
15981
+ props: {
15982
+ ref: "callout",
15983
+ slots: {
15984
+ label: "{{Note label}}",
15985
+ text: "{{Note: a caveat about the numbers, a definition or the method}}"
15986
+ }
15987
+ }
15988
+ },
15989
+ {
15990
+ name: "paragraph",
15991
+ props: {
15992
+ text: "{{Body: two or three short paragraphs of evidence for the section title, each opening with its claim}}"
15993
+ }
15994
+ }
15995
+ ]
15996
+ },
15997
+ {
15998
+ name: "section",
15999
+ children: [
16000
+ {
16001
+ name: "block",
16002
+ props: {
16003
+ ref: "section-opener",
16004
+ slots: {
16005
+ number: "03",
16006
+ title: "{{Section title: the finding, as a statement}}"
16007
+ }
16008
+ }
16009
+ },
16010
+ {
16011
+ name: "paragraph",
16012
+ props: {
16013
+ text: "{{Body: two or three short paragraphs of evidence for the section title, each opening with its claim}}"
16014
+ }
16015
+ },
16016
+ {
16017
+ name: "block",
16018
+ props: {
16019
+ ref: "data-table",
16020
+ slots: {
16021
+ title: "{{Table title: what it compares, and the period}}",
16022
+ labelHeader: "{{Row label}}",
16023
+ labels: ["{{Row 1}}", "{{Row 2}}", "{{Row 3}}"],
16024
+ columns: [
16025
+ {
16026
+ header: "{{Measure (unit)}}",
16027
+ cells: ["{{0.0}}", "{{0.0}}", "{{0.0}}"]
16028
+ },
16029
+ {
16030
+ header: "{{Change}}",
16031
+ cells: ["{{0.0}}", "{{0.0}}", "{{0.0}}"]
16032
+ }
16033
+ ],
16034
+ source: "{{Source: system or document, date}}"
16035
+ }
16036
+ }
16037
+ },
16038
+ {
16039
+ name: "block",
16040
+ props: {
16041
+ ref: "kpi-row",
16042
+ slots: {
16043
+ items: [
16044
+ {
16045
+ value: "{{0.0}}",
16046
+ label: "{{What it measures}}"
16047
+ },
16048
+ {
16049
+ value: "{{0.0}}",
16050
+ label: "{{What it measures}}"
16051
+ },
16052
+ {
16053
+ value: "{{0.0}}",
16054
+ label: "{{What it measures}}"
16055
+ }
16056
+ ],
16057
+ source: "{{Source: system or document, date}}"
16058
+ }
16059
+ }
16060
+ },
16061
+ {
16062
+ name: "paragraph",
16063
+ props: {
16064
+ text: "{{Body: two or three short paragraphs of evidence for the section title, each opening with its claim}}"
16065
+ }
16066
+ }
16067
+ ]
16068
+ },
16069
+ {
16070
+ name: "section",
16071
+ children: [
16072
+ {
16073
+ name: "block",
16074
+ props: {
16075
+ ref: "section-opener",
16076
+ slots: {
16077
+ number: "04",
16078
+ title: "{{Section title: the finding, as a statement}}"
16079
+ }
16080
+ }
16081
+ },
16082
+ {
16083
+ name: "paragraph",
16084
+ props: {
16085
+ text: "{{Body: two or three short paragraphs of evidence for the section title, each opening with its claim}}"
16086
+ }
16087
+ },
16088
+ {
16089
+ name: "block",
16090
+ props: {
16091
+ ref: "footnotes"
16092
+ }
16093
+ }
16094
+ ]
16095
+ }
16096
+ ]
16097
+ }
16098
+ }
16099
+ };
16100
+
16101
+ // src/templates/blueprints/technical-report.docx.blueprint.json
16102
+ var technical_report_docx_blueprint_default = {
16103
+ id: "technical-report",
16104
+ format: "docx",
16105
+ title: "Technical report",
16106
+ description: "A technical report or memo for engineers and their managers: numbered sections under a running head that numbers the pages, a contents list, a summary first, method and results with a chart and a runs table, recommendations, a readiness or decision statement, references last; or a memo that opens with To, From, Date and Subject and argues one recommendation in two pages.",
16107
+ whenToUse: "A load-test or audit report, a migration or capacity plan, a post-incident report, a standard, a security review, or a short memo recommending one option. Not for a client's periodic report, which reads for the conclusion first and rarely cites a method.",
16108
+ theme: "consulting",
16109
+ profile: "technical-report",
16110
+ definitions: "technical-report-blocks.docx.json",
16111
+ numbering: "sections",
16112
+ toc: true,
16113
+ variants: {
16114
+ "data-heavy": {
16115
+ description: "Evidence-led: summary, scope and method with its assumptions, results with a chart and two sub-headed findings and a runs table, recommendations with a risk note, a readiness statement, references.",
16116
+ whenToUse: "The brief comes with measurements: runs, findings, incidents, timings, anything the reader will check against a figure.",
16117
+ pages: {
16118
+ min: 4,
16119
+ max: 10
16120
+ },
16121
+ metadata: {
16122
+ title: "{{Title: as on the cover}}",
16123
+ author: "{{Author or team}}",
16124
+ company: "{{Team or client name}}",
16125
+ date: "{{Month YYYY}}"
16126
+ },
16127
+ children: [
16128
+ {
16129
+ name: "section",
16130
+ children: [
16131
+ {
16132
+ name: "block",
16133
+ props: {
16134
+ ref: "cover",
16135
+ slots: {
16136
+ title: "{{Title: the report's conclusion in one sentence}}",
16137
+ subtitle: "{{Subtitle: what was examined, for whom}}",
16138
+ client: "{{Team or client name}}",
16139
+ date: "{{Month YYYY}}",
16140
+ confidentiality: "{{Confidentiality: Internal, or Confidential}}"
16141
+ }
16142
+ }
16143
+ }
16144
+ ]
16145
+ },
16146
+ {
16147
+ name: "section",
16148
+ children: [
16149
+ {
16150
+ name: "block",
16151
+ props: {
16152
+ ref: "running-head",
16153
+ slots: {
16154
+ confidentiality: "{{Confidentiality: as on the cover}}",
16155
+ date: "{{Month YYYY}}"
16156
+ }
16157
+ }
16158
+ },
16159
+ {
16160
+ name: "toc",
16161
+ props: {
16162
+ scope: "document",
16163
+ title: "Contents",
16164
+ depth: {
16165
+ from: 1,
16166
+ to: 2
16167
+ }
16168
+ }
16169
+ },
16170
+ {
16171
+ name: "block",
16172
+ props: {
16173
+ ref: "section-opener",
16174
+ slots: {
16175
+ number: "1",
16176
+ title: "{{Section title: the conclusion, as a statement}}"
16177
+ }
16178
+ }
16179
+ },
16180
+ {
16181
+ name: "block",
16182
+ props: {
16183
+ ref: "key-takeaways",
16184
+ slots: {
16185
+ label: "Summary",
16186
+ items: [
16187
+ "{{Finding 1: one claim, one sentence, with its number}}",
16188
+ "{{Finding 2: one claim, one sentence, with its number}}",
16189
+ "{{Finding 3: the recommendation that follows}}"
16190
+ ]
16191
+ }
16192
+ }
16193
+ },
16194
+ {
16195
+ name: "paragraph",
16196
+ props: {
16197
+ text: "{{Body: what was examined, what was found and what is recommended, in one paragraph}}"
16198
+ }
16199
+ }
16200
+ ]
16201
+ },
16202
+ {
16203
+ name: "section",
16204
+ children: [
16205
+ {
16206
+ name: "block",
16207
+ props: {
16208
+ ref: "section-opener",
16209
+ slots: {
16210
+ number: "2",
16211
+ title: "{{Section title: scope and method}}"
16212
+ }
16213
+ }
16214
+ },
16215
+ {
16216
+ name: "paragraph",
16217
+ props: {
16218
+ text: "{{Body: what was measured, under which conditions, with which instruments, and what was left out}}"
16219
+ }
16220
+ },
16221
+ {
16222
+ name: "block",
16223
+ props: {
16224
+ ref: "callout",
16225
+ slots: {
16226
+ label: "{{Note label: Assumptions, or Limitations}}",
16227
+ text: "{{Note: the assumption or limit the results rest on}}"
16228
+ }
16229
+ }
16230
+ }
16231
+ ]
16232
+ },
16233
+ {
16234
+ name: "section",
16235
+ children: [
16236
+ {
16237
+ name: "block",
16238
+ props: {
16239
+ ref: "section-opener",
16240
+ slots: {
16241
+ number: "3",
16242
+ title: "{{Section title: results, as the headline finding}}"
16243
+ }
16244
+ }
16245
+ },
16246
+ {
16247
+ name: "paragraph",
16248
+ props: {
16249
+ text: "{{Body: what the figure shows and the number that matters}}"
16250
+ }
16251
+ },
16252
+ {
16253
+ name: "block",
16254
+ props: {
16255
+ ref: "chart-figure",
16256
+ slots: {
16257
+ chart: {
16258
+ name: "highcharts",
16259
+ props: {
16260
+ width: "100%",
16261
+ options: {
16262
+ chart: {
16263
+ type: "column",
16264
+ width: 900,
16265
+ height: 460
16266
+ },
16267
+ title: {
16268
+ text: null
16269
+ },
16270
+ xAxis: {
16271
+ categories: [
16272
+ "{{Condition 1}}",
16273
+ "{{Condition 2}}",
16274
+ "{{Condition 3}}"
16275
+ ],
16276
+ title: {
16277
+ text: "{{Independent variable (unit)}}"
16278
+ }
16279
+ },
16280
+ yAxis: {
16281
+ min: 0,
16282
+ title: {
16283
+ text: "{{Measure (unit)}}"
16284
+ }
16285
+ },
16286
+ series: [
16287
+ {
16288
+ name: "{{Series name}}",
16289
+ data: [0, 0, 0]
16290
+ }
16291
+ ],
16292
+ credits: {
16293
+ enabled: false
16294
+ }
16295
+ }
16296
+ }
16297
+ },
16298
+ caption: "{{Caption: what the chart shows, as a statement}}",
16299
+ takeaway: "{{Takeaway: the one sentence the reader should keep}}",
16300
+ source: "{{Source: system, run or document, date}}"
16301
+ }
16302
+ }
16303
+ },
16304
+ {
16305
+ name: "heading",
16306
+ props: {
16307
+ level: 2,
16308
+ text: "{{Sub-heading 3.1: the first result, as a statement}}"
16309
+ }
16310
+ },
16311
+ {
16312
+ name: "paragraph",
16313
+ props: {
16314
+ text: "{{Body: the evidence for the sub-heading, with its numbers}}"
16315
+ }
16316
+ },
16317
+ {
16318
+ name: "heading",
16319
+ props: {
16320
+ level: 2,
16321
+ text: "{{Sub-heading 3.2: the second result, as a statement}}"
16322
+ }
16323
+ },
16324
+ {
16325
+ name: "paragraph",
16326
+ props: {
16327
+ text: "{{Body: the evidence for the sub-heading, with its numbers}}"
16328
+ }
16329
+ },
16330
+ {
16331
+ name: "block",
16332
+ props: {
16333
+ ref: "data-table",
16334
+ slots: {
16335
+ title: "{{Table title: the runs or cases, and their conditions}}",
16336
+ labelHeader: "{{Run or case}}",
16337
+ labels: ["{{Row 1}}", "{{Row 2}}", "{{Row 3}}"],
16338
+ columns: [
16339
+ {
16340
+ header: "{{Measure (unit)}}",
16341
+ cells: ["{{0.0}}", "{{0.0}}", "{{0.0}}"]
16342
+ },
16343
+ {
16344
+ header: "{{Measure (unit)}}",
16345
+ cells: ["{{0.0}}", "{{0.0}}", "{{0.0}}"]
16346
+ }
16347
+ ],
16348
+ notes: "{{Notes: definitions, conditions, exclusions the reader needs to read the figures}}",
16349
+ source: "{{Source: system, run or document, date}}"
16350
+ }
16351
+ }
16352
+ }
16353
+ ]
16354
+ },
16355
+ {
16356
+ name: "section",
16357
+ children: [
16358
+ {
16359
+ name: "block",
16360
+ props: {
16361
+ ref: "section-opener",
16362
+ slots: {
16363
+ number: "4",
16364
+ title: "{{Section title: recommendations, as what to do}}"
16365
+ }
16366
+ }
16367
+ },
16368
+ {
16369
+ name: "paragraph",
16370
+ props: {
16371
+ text: "{{Body: each recommendation with its expected effect, cost and owner}}"
16372
+ }
16373
+ },
16374
+ {
16375
+ name: "block",
16376
+ props: {
16377
+ ref: "callout",
16378
+ slots: {
16379
+ label: "{{Note label: Risk, or Open question}}",
16380
+ text: "{{Note: what could invalidate the recommendation and how it will be checked}}"
16381
+ }
16382
+ }
16383
+ }
16384
+ ]
16385
+ },
16386
+ {
16387
+ name: "section",
16388
+ children: [
16389
+ {
16390
+ name: "block",
16391
+ props: {
16392
+ ref: "section-opener",
16393
+ slots: {
16394
+ number: "5",
16395
+ title: "{{Section title: the readiness or decision statement}}"
16396
+ }
16397
+ }
16398
+ },
16399
+ {
16400
+ name: "paragraph",
16401
+ props: {
16402
+ text: "{{Body: the answer to the brief's question, with its condition}}"
16403
+ }
16404
+ },
16405
+ {
16406
+ name: "block",
16407
+ props: {
16408
+ ref: "footnotes",
16409
+ slots: {
16410
+ title: "References"
16411
+ }
16412
+ }
16413
+ }
16414
+ ]
16415
+ }
16416
+ ]
16417
+ },
16418
+ narrative: {
16419
+ description: "Argument-led: summary, context and constraints, an analysis section built on one comparison table, options and risks, a recommendation with next steps, references.",
16420
+ whenToUse: "The brief is a plan, a policy, a standard or an assessment with few numbers; the reader follows an argument to a decision.",
16421
+ pages: {
16422
+ min: 3,
16423
+ max: 8
16424
+ },
16425
+ metadata: {
16426
+ title: "{{Title: as on the cover}}",
16427
+ author: "{{Author or team}}",
16428
+ company: "{{Team or client name}}",
16429
+ date: "{{Month YYYY}}"
16430
+ },
16431
+ children: [
16432
+ {
16433
+ name: "section",
16434
+ children: [
16435
+ {
16436
+ name: "block",
16437
+ props: {
16438
+ ref: "cover",
16439
+ slots: {
16440
+ title: "{{Title: the report's conclusion in one sentence}}",
16441
+ subtitle: "{{Subtitle: what was examined, for whom}}",
16442
+ client: "{{Team or client name}}",
16443
+ date: "{{Month YYYY}}",
16444
+ confidentiality: "{{Confidentiality: Internal, or Confidential}}"
16445
+ }
16446
+ }
16447
+ }
16448
+ ]
16449
+ },
16450
+ {
16451
+ name: "section",
16452
+ children: [
16453
+ {
16454
+ name: "block",
16455
+ props: {
16456
+ ref: "running-head",
16457
+ slots: {
16458
+ confidentiality: "{{Confidentiality: as on the cover}}",
16459
+ date: "{{Month YYYY}}"
16460
+ }
16461
+ }
16462
+ },
16463
+ {
16464
+ name: "toc",
16465
+ props: {
16466
+ scope: "document",
16467
+ title: "Contents",
16468
+ depth: {
16469
+ from: 1,
16470
+ to: 2
16471
+ }
16472
+ }
16473
+ },
16474
+ {
16475
+ name: "block",
16476
+ props: {
16477
+ ref: "section-opener",
16478
+ slots: {
16479
+ number: "1",
16480
+ title: "{{Section title: the conclusion, as a statement}}"
16481
+ }
16482
+ }
16483
+ },
16484
+ {
16485
+ name: "block",
16486
+ props: {
16487
+ ref: "key-takeaways",
16488
+ slots: {
16489
+ label: "Summary",
16490
+ items: [
16491
+ "{{Finding 1: one claim, one sentence, with its number}}",
16492
+ "{{Finding 2: one claim, one sentence, with its number}}",
16493
+ "{{Finding 3: the recommendation that follows}}"
16494
+ ]
16495
+ }
16496
+ }
16497
+ },
16498
+ {
16499
+ name: "paragraph",
16500
+ props: {
16501
+ text: "{{Body: what was examined, what was found and what is recommended, in one paragraph}}"
15224
16502
  }
15225
16503
  }
15226
16504
  ]
@@ -15233,66 +16511,21 @@ var client_report_docx_blueprint_default = {
15233
16511
  props: {
15234
16512
  ref: "section-opener",
15235
16513
  slots: {
15236
- number: "02",
15237
- title: "{{Section title: the finding, as a statement}}"
16514
+ number: "2",
16515
+ title: "{{Section title: context and constraints}}"
15238
16516
  }
15239
16517
  }
15240
16518
  },
15241
16519
  {
15242
16520
  name: "paragraph",
15243
16521
  props: {
15244
- text: "{{Body: two or three short paragraphs of evidence for the section title, each opening with its claim}}"
15245
- }
15246
- },
15247
- {
15248
- name: "block",
15249
- props: {
15250
- ref: "chart-figure",
15251
- slots: {
15252
- chart: {
15253
- name: "highcharts",
15254
- props: {
15255
- width: "100%",
15256
- options: {
15257
- chart: {
15258
- type: "column",
15259
- width: 900,
15260
- height: 460
15261
- },
15262
- title: {
15263
- text: null
15264
- },
15265
- xAxis: {
15266
- categories: [
15267
- "{{Period 1}}",
15268
- "{{Period 2}}",
15269
- "{{Period 3}}"
15270
- ]
15271
- },
15272
- yAxis: {
15273
- title: {
15274
- text: "{{Measure (unit)}}"
15275
- }
15276
- },
15277
- series: [
15278
- {
15279
- name: "{{Series name}}",
15280
- data: [0, 0, 0]
15281
- }
15282
- ]
15283
- }
15284
- }
15285
- },
15286
- caption: "{{Caption: what the chart shows, as a statement}}",
15287
- takeaway: "{{Takeaway: the one sentence the reader should keep}}",
15288
- source: "{{Source: system or document, date}}"
15289
- }
16522
+ text: "{{Body: the system or situation as it is, with the numbers that bound it}}"
15290
16523
  }
15291
16524
  },
15292
16525
  {
15293
16526
  name: "paragraph",
15294
16527
  props: {
15295
- text: "{{Body: two or three short paragraphs of evidence for the section title, each opening with its claim}}"
16528
+ text: "{{Body: the requirement or question this report answers}}"
15296
16529
  }
15297
16530
  }
15298
16531
  ]
@@ -15305,15 +16538,15 @@ var client_report_docx_blueprint_default = {
15305
16538
  props: {
15306
16539
  ref: "section-opener",
15307
16540
  slots: {
15308
- number: "03",
15309
- title: "{{Section title: the finding, as a statement}}"
16541
+ number: "3",
16542
+ title: "{{Section title: analysis, as the headline finding}}"
15310
16543
  }
15311
16544
  }
15312
16545
  },
15313
16546
  {
15314
16547
  name: "paragraph",
15315
16548
  props: {
15316
- text: "{{Body: two or three short paragraphs of evidence for the section title, each opening with its claim}}"
16549
+ text: "{{Body: the argument, opening with its claim}}"
15317
16550
  }
15318
16551
  },
15319
16552
  {
@@ -15321,8 +16554,8 @@ var client_report_docx_blueprint_default = {
15321
16554
  props: {
15322
16555
  ref: "data-table",
15323
16556
  slots: {
15324
- title: "{{Table title: what it compares, and the period}}",
15325
- labelHeader: "{{Row label}}",
16557
+ title: "{{Table title: what it compares, and the conditions}}",
16558
+ labelHeader: "{{Option or case}}",
15326
16559
  labels: ["{{Row 1}}", "{{Row 2}}", "{{Row 3}}"],
15327
16560
  columns: [
15328
16561
  {
@@ -15330,21 +16563,49 @@ var client_report_docx_blueprint_default = {
15330
16563
  cells: ["{{0.0}}", "{{0.0}}", "{{0.0}}"]
15331
16564
  },
15332
16565
  {
15333
- header: "{{Change}}",
16566
+ header: "{{Measure (unit)}}",
15334
16567
  cells: ["{{0.0}}", "{{0.0}}", "{{0.0}}"]
15335
16568
  }
15336
16569
  ],
15337
- source: "{{Source: system or document, date}}"
16570
+ notes: "{{Notes: definitions, conditions, exclusions the reader needs to read the figures}}",
16571
+ source: "{{Source: system, run or document, date}}"
16572
+ }
16573
+ }
16574
+ },
16575
+ {
16576
+ name: "paragraph",
16577
+ props: {
16578
+ text: "{{Body: what the table settles and what it leaves open}}"
16579
+ }
16580
+ }
16581
+ ]
16582
+ },
16583
+ {
16584
+ name: "section",
16585
+ children: [
16586
+ {
16587
+ name: "block",
16588
+ props: {
16589
+ ref: "section-opener",
16590
+ slots: {
16591
+ number: "4",
16592
+ title: "{{Section title: options and risks}}"
15338
16593
  }
15339
16594
  }
15340
16595
  },
16596
+ {
16597
+ name: "paragraph",
16598
+ props: {
16599
+ text: "{{Body: each option with its cost, its risk and what it forecloses}}"
16600
+ }
16601
+ },
15341
16602
  {
15342
16603
  name: "block",
15343
16604
  props: {
15344
16605
  ref: "callout",
15345
16606
  slots: {
15346
- label: "{{Note label}}",
15347
- text: "{{Note: a caveat about the numbers, a definition or the method}}"
16607
+ label: "{{Note label: Risk, or Open question}}",
16608
+ text: "{{Note: what could invalidate the recommendation and how it will be checked}}"
15348
16609
  }
15349
16610
  }
15350
16611
  }
@@ -15358,38 +16619,41 @@ var client_report_docx_blueprint_default = {
15358
16619
  props: {
15359
16620
  ref: "section-opener",
15360
16621
  slots: {
15361
- number: "04",
15362
- title: "{{Section title: the finding, as a statement}}"
16622
+ number: "5",
16623
+ title: "{{Section title: recommendation and next steps}}"
15363
16624
  }
15364
16625
  }
15365
16626
  },
15366
16627
  {
15367
16628
  name: "paragraph",
15368
16629
  props: {
15369
- text: "{{Body: two or three short paragraphs of evidence for the section title, each opening with its claim}}"
16630
+ text: "{{Body: the recommendation, its condition and the first three steps with owners and dates}}"
15370
16631
  }
15371
16632
  },
15372
16633
  {
15373
16634
  name: "block",
15374
16635
  props: {
15375
- ref: "footnotes"
16636
+ ref: "footnotes",
16637
+ slots: {
16638
+ title: "References"
16639
+ }
15376
16640
  }
15377
16641
  }
15378
16642
  ]
15379
16643
  }
15380
16644
  ]
15381
16645
  },
15382
- narrative: {
15383
- description: "Argument-led: takeaways, then three sections of prose with one KPI row and one note as evidence, next steps last; one data table in the analysis section carries the numbers the argument leans on.",
15384
- whenToUse: "The brief is a position, an assessment or a recommendation with few numbers; the reader follows an argument.",
16646
+ memo: {
16647
+ description: "A memo in one flowing section: To, From, Date and Subject in place of a cover, the recommendation first, then the question, the options against the requirements in one table, and what would change the answer; references last. No contents list.",
16648
+ whenToUse: "One decision for one reader, argued in under three pages: a vendor or option choice, a go or no-go, a change of approach.",
15385
16649
  pages: {
15386
- min: 3,
15387
- max: 6
16650
+ min: 1,
16651
+ max: 3
15388
16652
  },
15389
16653
  metadata: {
15390
- title: "{{Title: as on the cover}}",
16654
+ title: "{{Title: the subject line}}",
15391
16655
  author: "{{Author or team}}",
15392
- company: "{{Client name}}",
16656
+ company: "{{Team or client name}}",
15393
16657
  date: "{{Month YYYY}}"
15394
16658
  },
15395
16659
  children: [
@@ -15399,131 +16663,72 @@ var client_report_docx_blueprint_default = {
15399
16663
  {
15400
16664
  name: "block",
15401
16665
  props: {
15402
- ref: "cover",
16666
+ ref: "memo-header",
15403
16667
  slots: {
15404
- title: "{{Title: the report's conclusion in one sentence}}",
15405
- subtitle: "{{Subtitle: what the report answers, for whom}}",
15406
- client: "{{Client name}}",
15407
- date: "{{Month YYYY}}",
15408
- confidentiality: "{{Confidentiality: Confidential, or For internal use}}"
16668
+ subject: "{{Subject: the recommendation in one line}}",
16669
+ to: "{{To: the person or group who decides}}",
16670
+ from: "{{From: author or team}}",
16671
+ date: "{{D Month YYYY}}"
15409
16672
  }
15410
16673
  }
15411
- }
15412
- ]
15413
- },
15414
- {
15415
- name: "section",
15416
- children: [
16674
+ },
15417
16675
  {
15418
16676
  name: "block",
15419
16677
  props: {
15420
16678
  ref: "running-head",
15421
16679
  slots: {
15422
- confidentiality: "{{Confidentiality: as on the cover}}",
16680
+ confidentiality: "{{Confidentiality: Internal, or Confidential}}",
15423
16681
  date: "{{Month YYYY}}"
15424
16682
  }
15425
16683
  }
15426
16684
  },
15427
- {
15428
- name: "block",
15429
- props: {
15430
- ref: "section-opener",
15431
- slots: {
15432
- number: "01",
15433
- title: "{{Section title: the finding, as a statement}}"
15434
- }
15435
- }
15436
- },
15437
16685
  {
15438
16686
  name: "block",
15439
16687
  props: {
15440
16688
  ref: "key-takeaways",
15441
16689
  slots: {
16690
+ label: "Recommendation",
15442
16691
  items: [
15443
- "{{Takeaway 1: one claim, one sentence, with its number}}",
15444
- "{{Takeaway 2: one claim, one sentence, with its number}}",
15445
- "{{Takeaway 3: the recommendation that follows}}"
16692
+ "{{Recommendation: what to do, in one sentence}}",
16693
+ "{{Reason 1: the requirement it meets, with its number}}",
16694
+ "{{Reason 2: the cost or risk accepted, with its number}}"
15446
16695
  ]
15447
16696
  }
15448
16697
  }
15449
16698
  },
15450
- {
15451
- name: "paragraph",
15452
- props: {
15453
- text: "{{Body: two or three short paragraphs of evidence for the section title, each opening with its claim}}"
15454
- }
15455
- },
15456
- {
15457
- name: "paragraph",
15458
- props: {
15459
- text: "{{Body: two or three short paragraphs of evidence for the section title, each opening with its claim}}"
15460
- }
15461
- }
15462
- ]
15463
- },
15464
- {
15465
- name: "section",
15466
- children: [
15467
16699
  {
15468
16700
  name: "block",
15469
16701
  props: {
15470
16702
  ref: "section-opener",
15471
16703
  slots: {
15472
- number: "02",
15473
- title: "{{Section title: the finding, as a statement}}"
16704
+ number: "1",
16705
+ title: "{{Section title: the question and its constraints}}"
15474
16706
  }
15475
16707
  }
15476
16708
  },
15477
16709
  {
15478
16710
  name: "paragraph",
15479
16711
  props: {
15480
- text: "{{Body: two or three short paragraphs of evidence for the section title, each opening with its claim}}"
15481
- }
15482
- },
15483
- {
15484
- name: "block",
15485
- props: {
15486
- ref: "callout",
15487
- slots: {
15488
- label: "{{Note label}}",
15489
- text: "{{Note: a caveat about the numbers, a definition or the method}}"
15490
- }
16712
+ text: "{{Body: the requirements, each with its number, and what was considered}}"
15491
16713
  }
15492
16714
  },
15493
- {
15494
- name: "paragraph",
15495
- props: {
15496
- text: "{{Body: two or three short paragraphs of evidence for the section title, each opening with its claim}}"
15497
- }
15498
- }
15499
- ]
15500
- },
15501
- {
15502
- name: "section",
15503
- children: [
15504
16715
  {
15505
16716
  name: "block",
15506
16717
  props: {
15507
16718
  ref: "section-opener",
15508
16719
  slots: {
15509
- number: "03",
15510
- title: "{{Section title: the finding, as a statement}}"
16720
+ number: "2",
16721
+ title: "{{Section title: the options against the requirements}}"
15511
16722
  }
15512
16723
  }
15513
16724
  },
15514
- {
15515
- name: "paragraph",
15516
- props: {
15517
- text: "{{Body: two or three short paragraphs of evidence for the section title, each opening with its claim}}"
15518
- }
15519
- },
15520
16725
  {
15521
16726
  name: "block",
15522
16727
  props: {
15523
16728
  ref: "data-table",
15524
16729
  slots: {
15525
- title: "{{Table title: what it compares, and the period}}",
15526
- labelHeader: "{{Row label}}",
16730
+ title: "{{Table title: options against the requirements}}",
16731
+ labelHeader: "{{Option}}",
15527
16732
  labels: ["{{Row 1}}", "{{Row 2}}", "{{Row 3}}"],
15528
16733
  columns: [
15529
16734
  {
@@ -15531,68 +16736,54 @@ var client_report_docx_blueprint_default = {
15531
16736
  cells: ["{{0.0}}", "{{0.0}}", "{{0.0}}"]
15532
16737
  },
15533
16738
  {
15534
- header: "{{Change}}",
16739
+ header: "{{Measure (unit)}}",
15535
16740
  cells: ["{{0.0}}", "{{0.0}}", "{{0.0}}"]
15536
16741
  }
15537
16742
  ],
15538
- source: "{{Source: system or document, date}}"
16743
+ notes: "{{Notes: definitions, conditions, exclusions the reader needs to read the figures}}",
16744
+ source: "{{Source: system, run or document, date}}"
15539
16745
  }
15540
16746
  }
15541
16747
  },
15542
16748
  {
15543
- name: "block",
16749
+ name: "paragraph",
15544
16750
  props: {
15545
- ref: "kpi-row",
15546
- slots: {
15547
- items: [
15548
- {
15549
- value: "{{0.0}}",
15550
- label: "{{What it measures}}"
15551
- },
15552
- {
15553
- value: "{{0.0}}",
15554
- label: "{{What it measures}}"
15555
- },
15556
- {
15557
- value: "{{0.0}}",
15558
- label: "{{What it measures}}"
15559
- }
15560
- ],
15561
- source: "{{Source: system or document, date}}"
15562
- }
16751
+ text: "{{Body: why the recommended option wins and what the others lose on}}"
15563
16752
  }
15564
16753
  },
15565
16754
  {
15566
- name: "paragraph",
16755
+ name: "block",
15567
16756
  props: {
15568
- text: "{{Body: two or three short paragraphs of evidence for the section title, each opening with its claim}}"
16757
+ ref: "callout",
16758
+ slots: {
16759
+ label: "{{Note label: Assumption}}",
16760
+ text: "{{Note: the assumption the recommendation rests on}}"
16761
+ }
15569
16762
  }
15570
- }
15571
- ]
15572
- },
15573
- {
15574
- name: "section",
15575
- children: [
16763
+ },
15576
16764
  {
15577
16765
  name: "block",
15578
16766
  props: {
15579
16767
  ref: "section-opener",
15580
16768
  slots: {
15581
- number: "04",
15582
- title: "{{Section title: the finding, as a statement}}"
16769
+ number: "3",
16770
+ title: "{{Section title: what would change the answer}}"
15583
16771
  }
15584
16772
  }
15585
16773
  },
15586
16774
  {
15587
16775
  name: "paragraph",
15588
16776
  props: {
15589
- text: "{{Body: two or three short paragraphs of evidence for the section title, each opening with its claim}}"
16777
+ text: "{{Body: the two or three facts that would reverse the recommendation, and who checks them}}"
15590
16778
  }
15591
16779
  },
15592
16780
  {
15593
16781
  name: "block",
15594
16782
  props: {
15595
- ref: "footnotes"
16783
+ ref: "footnotes",
16784
+ slots: {
16785
+ title: "References"
16786
+ }
15596
16787
  }
15597
16788
  }
15598
16789
  ]
@@ -15603,25 +16794,6 @@ var client_report_docx_blueprint_default = {
15603
16794
  };
15604
16795
 
15605
16796
  // src/blueprints/index.ts
15606
- function register(...candidates) {
15607
- const registry2 = {};
15608
- for (const candidate of candidates) {
15609
- const issues = validateBlueprint(candidate);
15610
- if (issues.length > 0)
15611
- throw new Error(
15612
- `Invalid bundled blueprint: ${issues.map((issue) => `${issue.path}: ${issue.message}`).join("; ")}`
15613
- );
15614
- const blueprint = candidate;
15615
- if (blueprint.format !== "docx")
15616
- throw new Error(`Blueprint ${blueprint.id} is not a DOCX blueprint.`);
15617
- if (registry2[blueprint.id])
15618
- throw new Error(
15619
- `Two bundled blueprints share the id "${blueprint.id}"; the later one would silently replace the earlier.`
15620
- );
15621
- registry2[blueprint.id] = blueprint;
15622
- }
15623
- return registry2;
15624
- }
15625
16797
  function scanned(known) {
15626
16798
  let here;
15627
16799
  try {
@@ -15639,119 +16811,23 @@ function scanned(known) {
15639
16811
  return !(typeof id === "string" && id in known);
15640
16812
  });
15641
16813
  }
15642
- var bundled = register(client_report_docx_blueprint_default);
16814
+ var bundled = registerBlueprints("docx", [client_report_docx_blueprint_default, technical_report_docx_blueprint_default]);
15643
16815
  var DOCX_BLUEPRINTS = {
15644
16816
  ...bundled,
15645
- ...register(...scanned(bundled))
16817
+ ...registerBlueprints("docx", scanned(bundled))
15646
16818
  };
15647
16819
  function docxBlueprint(id) {
15648
16820
  return DOCX_BLUEPRINTS[id];
15649
16821
  }
15650
- var MARKER = /^\{\{\s*([\s\S]*?)\s*\}\}$/;
15651
16822
  function instantiateDocxBlueprint(blueprint, options) {
15652
- if (blueprint.format !== "docx")
15653
- throw new Error(
15654
- `Blueprint ${blueprint.id} is a ${blueprint.format} blueprint; this instantiates DOCX ones.`
15655
- );
15656
- const variantId = options.variant ?? Object.keys(blueprint.variants)[0];
15657
- const variant = blueprint.variants[variantId];
15658
- if (!variant)
15659
- throw new Error(
15660
- `Blueprint ${blueprint.id} has no variant "${variantId}"; it has ${Object.keys(
15661
- blueprint.variants
15662
- ).join(", ")}.`
15663
- );
15664
- const children = structuredClone(variant.children);
15665
- const blocks = definitionsFor(children, options.definitions, blueprint);
15666
- const document = {
15667
- name: "docx",
15668
- props: {
15669
- theme: options.theme ?? blueprint.theme,
15670
- qualityProfile: blueprint.profile,
15671
- ...Object.keys(blocks).length > 0 && { blocks },
15672
- metadata: { ...variant.metadata, ...options.metadata }
15673
- },
15674
- children
15675
- };
15676
- return { document, fillMap: fillMap(document, blocks), variant: variantId };
15677
- }
15678
- function definitionsFor(children, available, blueprint) {
15679
- const refs = /* @__PURE__ */ new Set();
15680
- const visit = (node) => {
15681
- if (Array.isArray(node)) return node.forEach(visit);
15682
- if (!node || typeof node !== "object") return;
15683
- const record = node;
15684
- const props = record.props;
15685
- if (record.name === "block" && typeof props?.ref === "string")
15686
- refs.add(props.ref);
15687
- Object.values(record).forEach(visit);
15688
- };
15689
- visit(children);
15690
- const result = {};
15691
- for (const ref of refs) {
15692
- if (!available[ref])
15693
- throw new Error(
15694
- `Blueprint ${blueprint.id} invokes "${ref}", which ${blueprint.definitions} does not define.`
15695
- );
15696
- for (const name of [...blockDependencies(available, ref), ref])
15697
- result[name] ??= structuredClone(available[name]);
15698
- }
15699
- return result;
15700
- }
15701
- function fillMap(document, blocks) {
15702
- return collectPlaceholders2(document).filter((occurrence) => occurrence.match.kind === "scaffold-marker").map((occurrence) => {
15703
- const guidance = occurrence.text.match(MARKER)?.[1] ?? occurrence.text;
15704
- const base = { path: occurrence.path, marker: occurrence.text, guidance };
15705
- if (occurrence.path.startsWith("/props/metadata/"))
15706
- return { ...base, kind: "metadata" };
15707
- const slot = slotAt(document, occurrence.path, blocks);
15708
- return slot ? { ...base, kind: "slot", ...slot } : { ...base, kind: "text" };
16823
+ return instantiateBlueprint(blueprint, options, {
16824
+ format: "docx",
16825
+ metadataPointer: "/props/metadata",
16826
+ markers: (document) => collectPlaceholders2(document).filter(
16827
+ (occurrence) => occurrence.match.kind === "scaffold-marker"
16828
+ )
15709
16829
  });
15710
16830
  }
15711
- function slotAt(document, pointer, blocks) {
15712
- const at = pointer.lastIndexOf("/props/slots/");
15713
- if (at < 0) return void 0;
15714
- const invocation = valueAt(document, pointer.slice(0, at));
15715
- const ref = invocation?.props?.ref;
15716
- if (typeof ref !== "string" || !blocks[ref]) return void 0;
15717
- const segments = pointer.slice(at + "/props/slots/".length).split("/").map(unescape);
15718
- let slot = blocks[ref].slots[segments[0]];
15719
- const names = [segments[0]];
15720
- for (const segment of segments.slice(1)) {
15721
- if (!slot) break;
15722
- if (slot.type === "array" && /^\d+$/.test(segment)) slot = slot.items;
15723
- else if (slot.type === "object") {
15724
- slot = slot.properties?.[segment];
15725
- names.push(segment);
15726
- } else if (slot.type === "component")
15727
- break;
15728
- else slot = void 0;
15729
- }
15730
- if (!slot) return void 0;
15731
- return {
15732
- block: ref,
15733
- slot: names.join("."),
15734
- type: slot.type,
15735
- ...slot.maxWords !== void 0 && { maxWords: slot.maxWords },
15736
- ...slot.maxLength !== void 0 && { maxLength: slot.maxLength },
15737
- ...slot.oneLine !== void 0 && { oneLine: slot.oneLine },
15738
- ...slot.required !== void 0 && { required: slot.required }
15739
- };
15740
- }
15741
- function unescape(segment) {
15742
- return segment.replace(/~1/g, "/").replace(/~0/g, "~");
15743
- }
15744
- function valueAt(root, pointer) {
15745
- if (pointer === "") return root;
15746
- let current = root;
15747
- for (const segment of pointer.split("/").slice(1).map(unescape)) {
15748
- if (Array.isArray(current)) current = current[Number(segment)];
15749
- else if (current && typeof current === "object")
15750
- current = current[segment];
15751
- else return void 0;
15752
- }
15753
- return current;
15754
- }
15755
16831
 
15756
16832
  // src/index.ts
15757
16833
  init_json();