@projectdochelp/s3te 3.2.2 → 3.2.3

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 (2) hide show
  1. package/README.md +401 -25
  2. package/package.json +1 -1
package/README.md CHANGED
@@ -17,7 +17,7 @@ This README is the user guide for the rewrite generation. The deeper implementat
17
17
  - [Usage](#usage)
18
18
  - [Daily Workflow](#daily-workflow)
19
19
  - [CLI Commands](#cli-commands)
20
- - [Template Commands](#template-commands)
20
+ - [Template Commands](#template-commands)
21
21
  - [Optional: Sitemap](#optional-sitemap)
22
22
  - [Optional: Webiny CMS](#optional-webiny-cms)
23
23
 
@@ -488,46 +488,138 @@ Once Webiny is installed and the stack is deployed with Webiny enabled, CMS cont
488
488
 
489
489
  </details>
490
490
 
491
- ### Template Commands
491
+ ## Template Commands
492
492
 
493
- These are the core S3TE commands you will use even in a plain HTML-only project.
493
+ S3TE uses literal HTML-like tags inside your `.html` and `.part` files. The tags are case-sensitive, always lowercase, and never use attributes. JSON-based commands must contain valid JSON and reject unknown properties.
494
+
495
+ The commands below are grouped by purpose:
496
+
497
+ - `Core Features` work in every S3TE project.
498
+ - `Webiny Features` are the content-driven commands. Despite the name, they also work with local content files under `offline/content/` when you are not using Webiny yet.
499
+
500
+ ### Core Features
494
501
 
495
502
  <details>
496
- <summary><code>&lt;part&gt;</code> - reuse a partial file</summary>
503
+ <summary><code>&lt;part&gt;</code> - reuse a partial file from <code>partDir</code></summary>
504
+
505
+ **Action**
506
+
507
+ Loads another template fragment from the current variant's `partDir`, renders it recursively, and inserts the result at the current position.
508
+
509
+ **Syntax**
497
510
 
498
511
  ```html
499
512
  <part>head.part</part>
500
513
  ```
501
514
 
515
+ The payload must be a relative path inside `partDir`. Leading `/` and `..` are invalid.
516
+
517
+ **Example**
518
+
519
+ ```html
520
+ <head>
521
+ <part>head.part</part>
522
+ </head>
523
+ ```
524
+
502
525
  </details>
503
526
 
504
527
  <details>
505
528
  <summary><code>&lt;if&gt;</code> - render inline HTML only when a condition matches</summary>
506
529
 
530
+ **Action**
531
+
532
+ Evaluates one inline JSON rule and renders its `template` only when the rule matches the current render target.
533
+
534
+ **Syntax**
535
+
507
536
  ```html
508
537
  <if>{
509
538
  "env": "prod",
539
+ "file": "index.html",
540
+ "not": false,
510
541
  "template": "<meta name='robots' content='all'>"
511
542
  }</if>
512
543
  ```
513
544
 
545
+ Supported JSON properties:
546
+
547
+ - `env` optional: matches the current environment name case-insensitively
548
+ - `file` optional: matches the current output filename, for example `index.html`
549
+ - `not` optional: inverts the final result when `true`
550
+ - `template` required: inline HTML to render when the rule matches
551
+
552
+ If both `env` and `file` are present, both must match.
553
+
554
+ If both conditions are omitted, the tag behaves like an inline template include and always renders its `template`.
555
+
556
+ **Example**
557
+
558
+ ```html
559
+ <if>{
560
+ "env": "prod",
561
+ "template": "<meta name='robots' content='all'>"
562
+ }</if>
563
+ <if>{
564
+ "env": "test",
565
+ "template": "<meta name='robots' content='noindex'>"
566
+ }</if>
567
+ ```
568
+
514
569
  </details>
515
570
 
516
571
  <details>
517
572
  <summary><code>&lt;fileattribute&gt;</code> - print metadata of the current output file</summary>
518
573
 
574
+ **Action**
575
+
576
+ Prints metadata of the file currently being rendered.
577
+
578
+ **Syntax**
579
+
519
580
  ```html
520
581
  <fileattribute>filename</fileattribute>
521
582
  ```
522
583
 
584
+ Currently supported values:
585
+
586
+ - `filename`: the output key relative to the target bucket, for example `news/article-one.html`
587
+
588
+ **Example**
589
+
590
+ ```html
591
+ <link rel="canonical" href="https://<lang>baseurl</lang>/<fileattribute>filename</fileattribute>">
592
+ ```
593
+
523
594
  </details>
524
595
 
525
596
  <details>
526
- <summary><code>&lt;lang&gt;</code> - print the current language metadata</summary>
597
+ <summary><code>&lt;lang&gt;</code> - print current language metadata</summary>
598
+
599
+ **Action**
600
+
601
+ Prints language-related metadata of the current render target.
602
+
603
+ **Syntax**
604
+
605
+ ```html
606
+ <lang>2</lang>
607
+ <lang>baseurl</lang>
608
+ ```
609
+
610
+ Currently supported values:
611
+
612
+ - `2`: the current language code such as `en` or `de`
613
+ - `baseurl`: the resolved base hostname for the current language and environment
614
+
615
+ **Example**
527
616
 
528
617
  ```html
529
618
  <html lang="<lang>2</lang>">
530
- <link rel="canonical" href="https://<lang>baseurl</lang>">
619
+ <head>
620
+ <link rel="canonical" href="https://<lang>baseurl</lang>">
621
+ </head>
622
+ </html>
531
623
  ```
532
624
 
533
625
  </details>
@@ -535,6 +627,12 @@ These are the core S3TE commands you will use even in a plain HTML-only project.
535
627
  <details>
536
628
  <summary><code>&lt;switchlang&gt;</code> - choose inline content by language</summary>
537
629
 
630
+ **Action**
631
+
632
+ Selects the block whose tag name matches the current language and renders only that block.
633
+
634
+ **Syntax**
635
+
538
636
  ```html
539
637
  <switchlang>
540
638
  <de>Willkommen</de>
@@ -542,9 +640,270 @@ These are the core S3TE commands you will use even in a plain HTML-only project.
542
640
  </switchlang>
543
641
  ```
544
642
 
643
+ There is no fallback to `defaultLanguage`. If the current language block is missing, S3TE renders an empty string and records a warning.
644
+
645
+ **Example**
646
+
647
+ ```html
648
+ <p>
649
+ <switchlang>
650
+ <de>Dein ultimatives Website-Werkzeug</de>
651
+ <en>Your ultimate website tool</en>
652
+ </switchlang>
653
+ </p>
654
+ ```
655
+
545
656
  </details>
546
657
 
547
- If you also want content-driven commands such as `dbmulti` or `dbmultifile`, continue with the optional Webiny section below. The same commands can also read from local `offline/content/*.json` files when you are not using Webiny yet.
658
+ ### Webiny Features
659
+
660
+ These commands read from the resolved content repository. With Webiny enabled, that means mirrored Webiny content. Without Webiny, the same commands can read from local JSON files under `offline/content/`.
661
+
662
+ <details>
663
+ <summary><code>&lt;dbpart&gt;</code> - insert one content fragment by <code>contentId</code></summary>
664
+
665
+ **Action**
666
+
667
+ Loads a single content item by `contentId` and inserts its content fragment.
668
+
669
+ S3TE first tries the language-specific field `content&lt;lang&gt;`, for example `contentde`, and falls back to `content` if the language-specific field does not exist.
670
+
671
+ **Syntax**
672
+
673
+ ```html
674
+ <dbpart>impressum</dbpart>
675
+ ```
676
+
677
+ The payload is the content ID, not the internal database record ID.
678
+
679
+ **Example**
680
+
681
+ ```html
682
+ <body>
683
+ <dbpart>impressum</dbpart>
684
+ </body>
685
+ ```
686
+
687
+ </details>
688
+
689
+ <details>
690
+ <summary><code>&lt;dbmulti&gt;</code> - render one inline template for multiple content items</summary>
691
+
692
+ **Action**
693
+
694
+ Queries matching content items and renders the given inline template once for each result.
695
+
696
+ **Syntax**
697
+
698
+ ```html
699
+ <dbmulti>{
700
+ "filter": [
701
+ {"forWebsite": {"BOOL": true}}
702
+ ],
703
+ "filtertype": "equals",
704
+ "limit": 3,
705
+ "template": "<article><h2><dbitem>headline</dbitem></h2></article>"
706
+ }</dbmulti>
707
+ ```
708
+
709
+ Supported JSON properties:
710
+
711
+ - `filter` required: array of legacy DynamoDB-style filter clauses
712
+ - `filtertype` optional: `equals` or `contains`, default is `equals`
713
+ - `limit` optional: maximum number of items to render
714
+ - `template` required: inline template rendered once per match
715
+
716
+ Filter notes:
717
+
718
+ - every filter clause contains exactly one field
719
+ - multiple clauses are combined with logical `AND`
720
+ - `__typename` matches the content model, for example `article`
721
+ - supported legacy value wrappers are `S`, `N`, `BOOL`, `NULL`, and `L`
722
+ - results are sorted deterministically; numeric `order` comes first, then `contentId`, then `id`
723
+
724
+ **Example**
725
+
726
+ ```html
727
+ <dbmulti>{
728
+ "filter": [
729
+ {"__typename": {"S": "article"}},
730
+ {"forWebsite": {"BOOL": true}}
731
+ ],
732
+ "limit": 3,
733
+ "template": "<a href='article-<dbitem>slug</dbitem>.html'><h2><dbitem>headline</dbitem></h2></a>"
734
+ }</dbmulti>
735
+ ```
736
+
737
+ </details>
738
+
739
+ <details>
740
+ <summary><code>&lt;dbmultifile&gt;</code> - generate one output file per content item</summary>
741
+
742
+ **Action**
743
+
744
+ Turns one source template into multiple output files. The content items are selected by filter, and each item produces one rendered file.
745
+
746
+ **Syntax**
747
+
748
+ ```html
749
+ <dbmultifile>{
750
+ "filenamesuffix": "slug",
751
+ "filter": [
752
+ {"__typename": {"S": "article"}}
753
+ ],
754
+ "limit": 10
755
+ }</dbmultifile>
756
+ <!doctype html>
757
+ <html>
758
+ <body>
759
+ <h1><dbmultifileitem>headline</dbmultifileitem></h1>
760
+ </body>
761
+ </html>
762
+ ```
763
+
764
+ Supported JSON properties:
765
+
766
+ - `filenamesuffix` required: field whose value becomes the filename suffix
767
+ - `filter` required: array of legacy DynamoDB-style filter clauses
768
+ - `filtertype` optional: `equals` or `contains`, default is `equals`
769
+ - `limit` optional: maximum number of files to generate
770
+
771
+ Rules:
772
+
773
+ - `dbmultifile` must be the first non-whitespace construct in the file
774
+ - the control block itself is not part of the output
775
+ - generated filenames follow the pattern `<basename>-<suffix>.<ext>`
776
+ - the suffix must not be empty and must not contain `/`, `\\`, or `:`
777
+ - suffixes must be unique within that template
778
+
779
+ **Example**
780
+
781
+ If the source file is `article.html` and the current item has `"slug": "first-article"`, the generated output becomes `article-first-article.html`.
782
+
783
+ ```html
784
+ <dbmultifile>{
785
+ "filenamesuffix": "slug",
786
+ "filter": [
787
+ {"__typename": {"S": "article"}}
788
+ ]
789
+ }</dbmultifile>
790
+ <article>
791
+ <h1><dbmultifileitem>headline</dbmultifileitem></h1>
792
+ </article>
793
+ ```
794
+
795
+ </details>
796
+
797
+ <details>
798
+ <summary><code>&lt;dbitem&gt;</code> - print one field of the current content item</summary>
799
+
800
+ **Action**
801
+
802
+ Reads one field from the current content item. This works inside `dbmulti` templates and inside `dbmultifile` bodies.
803
+
804
+ **Syntax**
805
+
806
+ ```html
807
+ <dbitem>headline</dbitem>
808
+ ```
809
+
810
+ Special field names:
811
+
812
+ - `__typename`
813
+ - `contentId`
814
+ - `id`
815
+ - `locale`
816
+ - `tenant`
817
+ - `_version`
818
+ - `_lastChangedAt`
819
+
820
+ For the field name `content`, S3TE again prefers `content&lt;lang&gt;` over `content`.
821
+
822
+ If the field value is a string array, S3TE serializes it as concatenated HTML links.
823
+
824
+ **Example**
825
+
826
+ ```html
827
+ <dbmulti>{
828
+ "filter": [{"__typename": {"S": "article"}}],
829
+ "template": "<article><h2><dbitem>headline</dbitem></h2><div><dbitem>content</dbitem></div></article>"
830
+ }</dbmulti>
831
+ ```
832
+
833
+ </details>
834
+
835
+ <details>
836
+ <summary><code>&lt;dbmultifileitem&gt;</code> - print or transform fields inside a <code>dbmultifile</code> body</summary>
837
+
838
+ **Action**
839
+
840
+ Reads one field from the current content item and can apply one transformation mode. It is primarily meant for `dbmultifile` bodies, but works wherever a current content item exists.
841
+
842
+ **Syntax**
843
+
844
+ Simple field output:
845
+
846
+ ```html
847
+ <dbmultifileitem>headline</dbmultifileitem>
848
+ ```
849
+
850
+ JSON command mode:
851
+
852
+ ```html
853
+ <dbmultifileitem>{"field":"content","limit":160}</dbmultifileitem>
854
+ ```
855
+
856
+ Supported JSON properties:
857
+
858
+ - `field` required
859
+ - `limit` optional: truncate text to a maximum length and append `...`
860
+ - `limitlow` optional: choose a random length between `limitlow` and `limit`
861
+ - `format` optional: currently only `date`
862
+ - `locale` optional: used with `format: "date"`
863
+ - `divideattag` optional: cut a section out of the field value
864
+ - `startnumber` optional: 1-based occurrence number for the divide start
865
+ - `endnumber` optional: 1-based occurrence number for the divide end
866
+
867
+ Only one transform mode is allowed at a time:
868
+
869
+ - limit mode: `limit` with optional `limitlow`
870
+ - date mode: `format: "date"`
871
+ - divide mode: `divideattag`
872
+
873
+ Date mode formats `de` as `dd.mm.yyyy`. All other locales currently format as `mm/dd/yyyy`.
874
+
875
+ **Examples**
876
+
877
+ Simple field output:
878
+
879
+ ```html
880
+ <dbmultifileitem>headline</dbmultifileitem>
881
+ ```
882
+
883
+ Truncated teaser text:
884
+
885
+ ```html
886
+ <dbmultifileitem>{"field":"content","limit":160}</dbmultifileitem>
887
+ ```
888
+
889
+ Date formatting:
890
+
891
+ ```html
892
+ <dbmultifileitem>{"field":"publishedAt","format":"date","locale":"de"}</dbmultifileitem>
893
+ ```
894
+
895
+ Extract one section from a larger HTML field:
896
+
897
+ ```html
898
+ <dbmultifileitem>{
899
+ "field":"content",
900
+ "divideattag":"<h2>",
901
+ "startnumber":2,
902
+ "endnumber":3
903
+ }</dbmultifileitem>
904
+ ```
905
+
906
+ </details>
548
907
 
549
908
  ## Optional: Sitemap
550
909
 
@@ -609,6 +968,8 @@ You do not need Webiny to use S3TE. Start with plain HTML first. Add Webiny only
609
968
 
610
969
  The supported target for this optional path is Webiny 6.x on its standard AWS deployment model.
611
970
 
971
+ Important for the Webiny path: S3TE does not turn on DynamoDB Streams on your Webiny table for you. You must enable the stream manually on the Webiny source table. S3TE uses that stream as the trigger source for CMS-driven rerendering.
972
+
612
973
  ![S3TE with Webiny](https://user-images.githubusercontent.com/100029932/174443536-7af050de-eea7-4456-81aa-a173863b6ec9.png)
613
974
 
614
975
  <details>
@@ -625,7 +986,10 @@ This section assumes that S3TE is already installed and deployed. The S3TE-speci
625
986
 
626
987
  1. Install Webiny in AWS and finish the Webiny setup first.
627
988
  2. Find the Webiny DynamoDB table that contains the CMS entries you want S3TE to mirror.
628
- 3. Upgrade your existing S3TE config for Webiny:
989
+ 3. Manually enable DynamoDB Streams on that Webiny table before the first S3TE deploy with Webiny enabled.
990
+ Use `NEW_AND_OLD_IMAGES`.
991
+ Without that stream, `s3te deploy --env <name>` cannot wire the Webiny trigger and fails because the table has no `LatestStreamArn`.
992
+ 4. Upgrade your existing S3TE config for Webiny:
629
993
 
630
994
  ```bash
631
995
  npx s3te migrate --enable-webiny --webiny-source-table webiny-1234567 --webiny-tenant root --webiny-model article --write
@@ -633,6 +997,22 @@ npx s3te migrate --enable-webiny --webiny-source-table webiny-1234567 --webiny-t
633
997
 
634
998
  `staticContent` and `staticCodeContent` are kept automatically. Add `--webiny-model` once per custom model you want S3TE to mirror.
635
999
 
1000
+ `--webiny-model article` means:
1001
+
1002
+ - `article` is the technical Webiny model ID, not the human-readable label shown in the CMS UI.
1003
+ - S3TE adds that model ID to `integrations.webiny.relevantModels` in `s3te.config.json`.
1004
+ - Only Webiny stream records whose model is listed in `relevantModels` are mirrored into the S3TE content table and can trigger rerendering.
1005
+ - If you omit `--webiny-model`, only the built-in defaults `staticContent` and `staticCodeContent` are mirrored.
1006
+ - You can pass the flag multiple times for multiple models, for example `--webiny-model article --webiny-model news --webiny-model event`.
1007
+
1008
+ That makes the migration example above equivalent to a config that contains:
1009
+
1010
+ ```json
1011
+ "relevantModels": ["article", "staticContent", "staticCodeContent"]
1012
+ ```
1013
+
1014
+ Use this for every Webiny model whose entries should be available to S3TE template commands like `dbitem`, `dbmulti`, `dbmultifile`, `dbmultifileitem`, or `dbpart`.
1015
+
636
1016
  If different environments should read from different Webiny installations or tenants, run the migration per environment:
637
1017
 
638
1018
  ```bash
@@ -640,16 +1020,18 @@ npx s3te migrate --env test --enable-webiny --webiny-source-table webiny-test-12
640
1020
  npx s3te migrate --env prod --enable-webiny --webiny-source-table webiny-live-1234567 --webiny-tenant root --write
641
1021
  ```
642
1022
 
643
- 4. Turn on DynamoDB Streams for the Webiny source table with `NEW_AND_OLD_IMAGES`.
644
- 5. If your S3TE language keys are not identical to your Webiny locales, add `webinyLocale` per language in `s3te.config.json`, for example `"en": { "webinyLocale": "en-US" }`.
645
- 6. If your Webiny installation hosts multiple tenants, keep `integrations.webiny.tenant` set so S3TE only mirrors the intended tenant.
646
- 7. Check the project again:
1023
+ 5. Verify again that DynamoDB Streams are enabled on the Webiny source table with `NEW_AND_OLD_IMAGES`.
1024
+ You enable this manually in the AWS console on the Webiny DynamoDB table under `Exports and streams`.
1025
+ S3TE creates the Lambda event source mapping during deploy, but it does not create or enable the table stream itself.
1026
+ 6. If your S3TE language keys are not identical to your Webiny locales, add `webinyLocale` per language in `s3te.config.json`, for example `"en": { "webinyLocale": "en-US" }`.
1027
+ 7. If your Webiny installation hosts multiple tenants, keep `integrations.webiny.tenant` set so S3TE only mirrors the intended tenant.
1028
+ 8. Check the project again:
647
1029
 
648
1030
  ```bash
649
1031
  npx s3te doctor --env prod
650
1032
  ```
651
1033
 
652
- 8. Redeploy the existing S3TE environment:
1034
+ 9. Redeploy the existing S3TE environment:
653
1035
 
654
1036
  ```bash
655
1037
  npx s3te deploy --env prod
@@ -657,6 +1039,11 @@ npx s3te deploy --env prod
657
1039
 
658
1040
  That deploy updates the existing environment stack and adds the Webiny mirror resources to it. You do not need a fresh S3TE installation. After that, Webiny content changes flow through the deployed AWS resources automatically; only template or asset changes still need `s3te sync --env <name>`.
659
1041
 
1042
+ Manual versus automatic responsibilities in this step:
1043
+
1044
+ - Manual: enable DynamoDB Streams on the Webiny source table
1045
+ - Automatic during `s3te deploy`: read `LatestStreamArn`, create the Lambda event source mapping, and wire the S3TE Webiny mirror Lambda into the environment stack
1046
+
660
1047
  </details>
661
1048
 
662
1049
  <details>
@@ -702,15 +1089,4 @@ For localized Webiny projects, the language block can also carry the mapping exp
702
1089
 
703
1090
  </details>
704
1091
 
705
- <details>
706
- <summary>Content template commands</summary>
707
-
708
- These commands are useful both with Webiny and with local JSON content files:
709
-
710
- - `dbpart`
711
- - `dbmulti`
712
- - `dbmultifile`
713
- - `dbitem`
714
- - `dbmultifileitem`
715
-
716
- </details>
1092
+ The content-driven tags are documented in [Template Commands](#template-commands), section [Webiny Features](#webiny-features).
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@projectdochelp/s3te",
3
- "version": "3.2.2",
3
+ "version": "3.2.3",
4
4
  "description": "CLI, render core, AWS adapter, and testkit for S3TemplateEngine projects",
5
5
  "repository": {
6
6
  "type": "git",