This is an automated email from the ASF dual-hosted git repository.

thiagohp pushed a commit to branch feature/requirejs-less
in repository https://gitbox.apache.org/repos/asf/tapestry-5.git


The following commit(s) were added to refs/heads/feature/requirejs-less by this 
push:
     new ead827a04 TAP5-2810: More needed support code for Require.js-less mode
ead827a04 is described below

commit ead827a0425863649f03697fbfffc6bb84ee9940
Author: Thiago H. de Paula Figueiredo <thi...@arsmachina.com.br>
AuthorDate: Sat Jul 26 12:24:23 2025 -0300

    TAP5-2810: More needed support code for Require.js-less mode
---
 5_10_RELEASE_NOTES.md                              |   11 +-
 .../apache/tapestry5/corelib/components/Zone.java  |    8 +-
 .../internal/services/DocumentLinkerImpl.java      |   29 +-
 .../internal/services/ajax/BaseInitialization.java |   10 +
 .../services/ajax/EsModuleInitializationImpl.java  |   12 +-
 .../internal/services/ajax/EsShimManagerImpl.java  |   66 ++
 .../services/ajax/JavaScriptSupportImpl.java       |   27 +-
 .../services/javascript/EsModuleManagerImpl.java   |   58 +-
 .../services/javascript/EsShimDispatcher.java      |   31 +-
 .../apache/tapestry5/modules/JavaScriptModule.java |  189 ++--
 .../apache/tapestry5/modules/TapestryModule.java   |    7 +-
 .../services/javascript/EsModuleManager.java       |   14 +-
 .../tapestry5/services/javascript/EsShim.java      |   91 +-
 .../services/javascript/EsShimManager.java         |   49 +
 .../javascript/ExtensibleJavaScriptStack.java      |   18 +-
 .../services/javascript/JavaScriptStack.java       |    8 +
 .../services/javascript/StackExtension.java        |   10 +
 .../services/javascript/StackExtensionType.java    |    7 +
 .../META-INF/assets/es-modules/t5/underscore.js    |    5 -
 .../typescript/src/t5/core/t53-compatibility.ts    |   56 +
 .../integration/app1/components/Border.java        |   14 +-
 .../tapestry5/integration/app1/pages/Index.java    | 1150 ++++++++++----------
 .../META-INF/assets/es-modules/app/test-support.js |   14 +
 23 files changed, 1118 insertions(+), 766 deletions(-)

diff --git a/5_10_RELEASE_NOTES.md b/5_10_RELEASE_NOTES.md
index b893fdec3..4a942b709 100644
--- a/5_10_RELEASE_NOTES.md
+++ b/5_10_RELEASE_NOTES.md
@@ -31,13 +31,10 @@ Scratch pad for changes destined for the 5.10.0 release 
notes page.
   
 
 # Notes about Require.js disabled mode
-* When using Bootstrap 3, the `t5/bootstrap/*` modules had automatic dependency
-  management (for example, if you `bootstrap/tooltip`, `bootstrap/transition`
-  would automatically be included too through Require.js). This doesn't happen
-  when Require.js is disabled. So, for example, when importing 
`bootstrap/tooltip`,
-  you should import `bootstrap/trasition` first. Notice Bootstrap 3 JavaScript 
-  files don't have any module management code on it (Require.js nor ES modules)
-  
+* Underscore.js, jQuery and Require.js are not included in the default stack 
+  (i.e. the set of JavaScript files which are included in pages by default).
+  If you need to use Underscore.js or jQuery, they're automatically available 
for   
+  import as `underscore` and `jquery`, respectively.
 
 
 # Overall notes
diff --git 
a/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/Zone.java 
b/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/Zone.java
index b4e9b0282..7bfd9b720 100644
--- 
a/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/Zone.java
+++ 
b/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/Zone.java
@@ -20,6 +20,7 @@ import 
org.apache.tapestry5.corelib.internal.FormSupportAdapter;
 import org.apache.tapestry5.corelib.internal.HiddenFieldPositioner;
 import org.apache.tapestry5.dom.Element;
 import org.apache.tapestry5.internal.services.RequestConstants;
+import org.apache.tapestry5.internal.services.ajax.RequireJsModeHelper;
 import org.apache.tapestry5.ioc.annotations.Inject;
 import org.apache.tapestry5.ioc.annotations.Symbol;
 import org.apache.tapestry5.json.JSONObject;
@@ -68,7 +69,6 @@ import org.slf4j.Logger;
  * @see FormFragment
  */
 @SupportsInformalParameters
-@Import(module = "t5/core/zone")
 public class Zone implements ClientBodyElement
 {
     /**
@@ -144,6 +144,9 @@ public class Zone implements ClientBodyElement
 
     @Inject
     private HiddenFieldLocationRules rules;
+    
+    @Inject
+    private RequireJsModeHelper requireJsModeHelper;
 
     private String clientId;
 
@@ -175,6 +178,9 @@ public class Zone implements ClientBodyElement
 
     void beginRender(MarkupWriter writer)
     {
+        
+        requireJsModeHelper.importModule("t5/core/zone");
+        
         clientId = resources.isBound("id") ? idParameter : 
javascriptSupport.allocateClientId(resources);
 
         Element e = writer.element(elementName,
diff --git 
a/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/DocumentLinkerImpl.java
 
b/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/DocumentLinkerImpl.java
index 8814e7faf..fd885ce87 100644
--- 
a/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/DocumentLinkerImpl.java
+++ 
b/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/DocumentLinkerImpl.java
@@ -53,6 +53,8 @@ public class DocumentLinkerImpl implements DocumentLinker
     private final boolean omitGeneratorMetaTag, enablePageloadingMask;
 
     private final String tapestryBanner;
+    
+    private final boolean requireJsEnabled;
 
     // Initially false; set to true when a scriptURL or any kind of 
initialization is added.
     private boolean hasScriptsOrInitializations;
@@ -66,12 +68,14 @@ public class DocumentLinkerImpl implements DocumentLinker
      * @param tapestryVersion
      */
     public DocumentLinkerImpl(ModuleManager moduleManager, EsModuleManager 
esModuleManager,
-            boolean omitGeneratorMetaTag, boolean enablePageloadingMask, 
String tapestryVersion)
+            boolean omitGeneratorMetaTag, boolean enablePageloadingMask, 
String tapestryVersion,
+            boolean requireJsEnabled)
     {
         this.moduleManager = moduleManager;
         this.esModuleManager = esModuleManager;
         this.omitGeneratorMetaTag = omitGeneratorMetaTag;
         this.enablePageloadingMask = enablePageloadingMask;
+        this.requireJsEnabled = requireJsEnabled;
 
         tapestryBanner = "Apache Tapestry Framework (version " + 
tapestryVersion + ')';
     }
@@ -149,8 +153,6 @@ public class DocumentLinkerImpl implements DocumentLinker
 
             addElementBefore(head, existingMeta, "meta", "name", "generator", 
"content", tapestryBanner);
         }
-
-        addScriptElements(root);
         
         final List<EsModuleInitialization> esModuleInits = 
esModulesinitsManager.getInits();
         if (isHtmlRoot && !esModuleInits.isEmpty())
@@ -158,6 +160,8 @@ public class DocumentLinkerImpl implements DocumentLinker
             esModuleManager.writeImportMap(root.find("head"), 
esModuleConfigurationCallbacks);
             esModuleManager.writeImports(root, esModuleInits);
         }
+
+        addScriptElements(root);
         
     }
 
@@ -252,8 +256,11 @@ public class DocumentLinkerImpl implements DocumentLinker
 
             script.moveToTop(body);
         }
-
-        moduleManager.writeConfiguration(body, moduleConfigurationCallbacks);
+        
+        if (requireJsEnabled)
+        {
+            moduleManager.writeConfiguration(body, 
moduleConfigurationCallbacks);
+        }
 
         // Write the core libraries, which includes RequireJS:
 
@@ -264,9 +271,15 @@ public class DocumentLinkerImpl implements DocumentLinker
                     "src", url);
         }
 
-        // Write the initialization at this point.
-
-        moduleManager.writeInitialization(body, libraryURLs, 
initsManager.getSortedInits());
+        if (requireJsEnabled)
+        {
+            // Write the initialization at this point.
+            moduleManager.writeInitialization(body, libraryURLs, 
initsManager.getSortedInits());
+        }
+        else
+        {
+            esModuleManager.writeInitialization(body, libraryURLs);
+        }
     }
 
     private static Element createTemporaryContainer(Element headElement, 
String existingElementName, String newElementName)
diff --git 
a/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ajax/BaseInitialization.java
 
b/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ajax/BaseInitialization.java
index 589a8850a..7714dc461 100644
--- 
a/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ajax/BaseInitialization.java
+++ 
b/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ajax/BaseInitialization.java
@@ -1,3 +1,13 @@
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
 package org.apache.tapestry5.internal.services.ajax;
 
 import org.apache.tapestry5.ioc.internal.util.InternalUtils;
diff --git 
a/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ajax/EsModuleInitializationImpl.java
 
b/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ajax/EsModuleInitializationImpl.java
index 3b3bfeb4a..eb4e32137 100644
--- 
a/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ajax/EsModuleInitializationImpl.java
+++ 
b/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ajax/EsModuleInitializationImpl.java
@@ -1,3 +1,13 @@
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
 package org.apache.tapestry5.internal.services.ajax;
 
 import java.util.Collections;
@@ -14,7 +24,7 @@ public class EsModuleInitializationImpl extends 
BaseInitialization<EsModuleIniti
     private ImportPlacement placement = ImportPlacement.BODY_BOTTOM;
     private Object[] arguments;
     
-    EsModuleInitializationImpl(String moduleName) 
+    public EsModuleInitializationImpl(String moduleName) 
     {
         super(moduleName);
     }
diff --git 
a/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ajax/EsShimManagerImpl.java
 
b/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ajax/EsShimManagerImpl.java
new file mode 100644
index 000000000..f8a8c0dd8
--- /dev/null
+++ 
b/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ajax/EsShimManagerImpl.java
@@ -0,0 +1,66 @@
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package org.apache.tapestry5.internal.services.ajax;
+
+import java.util.Map;
+
+import org.apache.tapestry5.SymbolConstants;
+import org.apache.tapestry5.commons.Resource;
+import org.apache.tapestry5.ioc.annotations.Symbol;
+import org.apache.tapestry5.services.PathConstructor;
+import org.apache.tapestry5.services.javascript.EsShimManager;
+
+public class EsShimManagerImpl implements EsShimManager
+{
+    
+    private static final String ES_SUBPATH = "es-shims";
+    
+    private final Map<String, Resource> shims;
+    
+    private final PathConstructor pathConstructor;
+    
+    private final String assetPrefix;
+    
+    public EsShimManagerImpl(Map<String, Resource> shims,
+            PathConstructor pathConstructor,
+            @Symbol(SymbolConstants.ASSET_PATH_PREFIX)
+            String assetPrefix) 
+    {
+        super();
+        this.shims = shims;
+        this.assetPrefix = assetPrefix;
+        this.pathConstructor = pathConstructor;
+    }
+
+    /**
+     * Returns the shims as a (module name, module resource) map.
+     * @return a {@code Map<String, Resource>}
+     */
+    @Override
+    public Map<String, Resource> getShims()
+    {
+        return shims;
+    }
+    
+    @Override
+    public String getRequestPrefix(boolean compress)
+    {
+        return pathConstructor.constructDispatchPath(assetPrefix + "/" + 
(compress ? ES_SUBPATH + ".gz" : ES_SUBPATH) + "/");
+    }
+
+    @Override
+    public String getUrl(String moduleName) {
+        return getRequestPrefix(true) + moduleName + ".js";
+    }
+    
+}
diff --git 
a/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ajax/JavaScriptSupportImpl.java
 
b/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ajax/JavaScriptSupportImpl.java
index a065b4b6c..db44db661 100644
--- 
a/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ajax/JavaScriptSupportImpl.java
+++ 
b/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ajax/JavaScriptSupportImpl.java
@@ -34,6 +34,7 @@ import org.apache.tapestry5.ioc.internal.util.InternalUtils;
 import org.apache.tapestry5.ioc.util.IdAllocator;
 import org.apache.tapestry5.json.JSONArray;
 import org.apache.tapestry5.json.JSONObject;
+import org.apache.tapestry5.services.javascript.AbstractInitialization;
 import org.apache.tapestry5.services.javascript.EsModuleConfigurationCallback;
 import org.apache.tapestry5.services.javascript.EsModuleInitialization;
 import org.apache.tapestry5.services.javascript.Initialization;
@@ -46,6 +47,8 @@ import 
org.apache.tapestry5.services.javascript.StylesheetLink;
 
 public class JavaScriptSupportImpl implements JavaScriptSupport
 {
+    private static final String PAGEINIT_MODULE_NAME = "t5/core/pageinit";
+
     private final IdAllocator idAllocator;
 
     private final DocumentLinker linker;
@@ -133,10 +136,21 @@ public class JavaScriptSupportImpl implements 
JavaScriptSupport
     public void commit()
     {
         
+        final String pageInitModuleName = PAGEINIT_MODULE_NAME;
         // TODO make no Require.js version of this
         if (focusFieldId != null)
         {
-            require("t5/core/pageinit").invoke("focus").with(focusFieldId);
+            final AbstractInitialization<?> initialization;
+            
+            if (requireJsEnabled)
+            {
+                initialization = require(pageInitModuleName);
+            }
+            else
+            {
+                initialization = importEsModule(pageInitModuleName);
+            }
+            initialization.invoke("focus").with(focusFieldId);
         }
 
         F.flow(stylesheetLinks).each(new Worker<StylesheetLink>()
@@ -224,7 +238,16 @@ public class JavaScriptSupportImpl implements 
JavaScriptSupport
 
         if (partialMode)
         {
-            
require("t5/core/pageinit").invoke("evalJavaScript").with(newScript);
+            final AbstractInitialization<?> initialization;
+            if (requireJsEnabled)
+            {
+                initialization = require(PAGEINIT_MODULE_NAME);
+            }
+            else
+            {
+                initialization = importEsModule(PAGEINIT_MODULE_NAME);
+            }
+            initialization.invoke("evalJavaScript").with(newScript);
         } else
         {
             linker.addScript(priority, newScript);
diff --git 
a/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/javascript/EsModuleManagerImpl.java
 
b/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/javascript/EsModuleManagerImpl.java
index a73a2fe64..5cfebf058 100644
--- 
a/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/javascript/EsModuleManagerImpl.java
+++ 
b/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/javascript/EsModuleManagerImpl.java
@@ -17,6 +17,7 @@ import java.util.ArrayList;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
+import java.util.stream.Collectors;
 
 import org.apache.tapestry5.Asset;
 import org.apache.tapestry5.SymbolConstants;
@@ -31,15 +32,18 @@ import 
org.apache.tapestry5.internal.services.assets.ResourceChangeTracker;
 import org.apache.tapestry5.ioc.annotations.Symbol;
 import org.apache.tapestry5.ioc.services.ClasspathMatcher;
 import org.apache.tapestry5.ioc.services.ClasspathScanner;
+import org.apache.tapestry5.json.JSONArray;
 import org.apache.tapestry5.json.JSONCollection;
 import org.apache.tapestry5.json.JSONLiteral;
 import org.apache.tapestry5.json.JSONObject;
 import org.apache.tapestry5.services.AssetSource;
+import org.apache.tapestry5.services.Core;
 import org.apache.tapestry5.services.assets.StreamableResourceSource;
 import org.apache.tapestry5.services.javascript.EsModuleConfigurationCallback;
 import org.apache.tapestry5.services.javascript.EsModuleInitialization;
 import org.apache.tapestry5.services.javascript.EsModuleManager;
 import org.apache.tapestry5.services.javascript.ImportPlacement;
+import org.apache.tapestry5.services.javascript.JavaScriptStack;
 
 public class EsModuleManagerImpl implements EsModuleManager
 {
@@ -60,6 +64,8 @@ public class EsModuleManagerImpl implements EsModuleManager
     private final Set<String> extensions;
     
     private final AssetSource assetSource;
+    
+    private final List<EsModuleInitialization> coreStackInits;
 
     // Note: ConcurrentHashMap does not support null as a value, alas. We use 
classpathRoot as a null.
     private final Map<String, String> cache = 
CollectionFactory.newConcurrentMap();
@@ -74,6 +80,8 @@ public class EsModuleManagerImpl implements EsModuleManager
     
     private final List<EsModuleConfigurationCallback> 
globalPerRequestCallbacks;
     
+    private final String infraProvider;
+    
     public EsModuleManagerImpl(
                              List<EsModuleManagerContribution> contributions,
                              AssetSource assetSource,
@@ -82,14 +90,24 @@ public class EsModuleManagerImpl implements EsModuleManager
                              boolean compactJSON,
                              
@Symbol(TapestryHttpSymbolConstants.PRODUCTION_MODE)
                              boolean productionMode,
+                             
@Symbol(SymbolConstants.JAVASCRIPT_INFRASTRUCTURE_PROVIDER)
+                             String infraProvider,                             
                              ClasspathScanner classpathScanner,
-                             ResourceChangeTracker resourceChangeTracker)
+                             ResourceChangeTracker resourceChangeTracker,
+                             @Core JavaScriptStack javaScriptStack)
     {
         this.compactJSON = compactJSON;
         this.assetSource = assetSource;
         this.classpathScanner = classpathScanner;
         this.productionMode = productionMode;
         this.resourceChangeTracker = resourceChangeTracker;
+        this.infraProvider = infraProvider;
+        
+        final List<String> coreStackEsModules = javaScriptStack.getEsModules();
+        
+        coreStackInits = coreStackEsModules.stream()
+                .map(i -> new EsModuleInitializationImpl(i))
+                .collect(Collectors.toList());
         
         baseCallbacks = new ArrayList<>();
         globalPerRequestCallbacks = new ArrayList<>();
@@ -151,12 +169,22 @@ public class EsModuleManagerImpl implements 
EsModuleManager
             final Set<String> scan = classpathScanner.scan(CLASSPATH_ROOT, 
matcher);
             for (String file : scan) 
             {
-                String id = file.replace(CLASSPATH_ROOT, "");
-                id = id.substring(0, id.lastIndexOf('.'));
+                String moduleName = file.replace(CLASSPATH_ROOT, "");
+                moduleName = moduleName.substring(0, 
moduleName.lastIndexOf('.'));
+                
+                if (moduleName.startsWith("t5/core/t5-core-dom-"))
+                {
+                    // They're treated specially.
+                    continue;
+                }
+                else if (moduleName.equals("t5/core/dom"))
+                {
+                    file = file.replace("t5/core/dom", "t5/core/t5-core-dom-" 
+ infraProvider);
+                }
                             
                 final Asset asset = assetSource.getClasspathAsset(file);
                 resourceChangeTracker.trackResource(asset.getResource());
-                imports.put(id, asset.toClientURL());
+                imports.put(moduleName, asset.toClientURL());
             }
         } catch (IOException e) 
         {
@@ -192,7 +220,11 @@ public class EsModuleManagerImpl implements EsModuleManager
         String functionName;
         Object[] arguments;
         
-        for (EsModuleInitialization i : inits) 
+        List<EsModuleInitialization> allInits = new 
ArrayList<>(coreStackInits.size() + inits.size());
+        allInits.addAll(coreStackInits);
+        allInits.addAll(inits);
+        
+        for (EsModuleInitialization i : allInits) 
         {
             
             init = (EsModuleInitializationImpl) i;
@@ -281,6 +313,22 @@ public class EsModuleManagerImpl implements EsModuleManager
         
     }
     
+    @Override
+    public void writeInitialization(Element body, List<String> libraryURLs) 
+    {
+
+        Element element = body.element("script", "type", "module");
+
+        element.raw(String.format("import pageinit from 
\"t5/core/pageinit\";\npageinit(%s, []);",
+                convert(libraryURLs)));
+    }
+    
+    private String convert(List<?> input)
+    {
+        return new JSONArray().putAll(input).toString(compactJSON);
+    }
+
+
     static String convertToJsFunctionParameters(Object[] arguments, boolean 
compactJSON)
     {
         String result;
diff --git 
a/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/javascript/EsShimDispatcher.java
 
b/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/javascript/EsShimDispatcher.java
index fb1a24da9..03ec9874a 100644
--- 
a/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/javascript/EsShimDispatcher.java
+++ 
b/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/javascript/EsShimDispatcher.java
@@ -16,7 +16,6 @@ import java.io.IOException;
 import java.util.HashMap;
 import java.util.Map;
 
-import org.apache.tapestry5.SymbolConstants;
 import org.apache.tapestry5.commons.Resource;
 import org.apache.tapestry5.http.services.Dispatcher;
 import org.apache.tapestry5.http.services.Request;
@@ -26,13 +25,11 @@ import 
org.apache.tapestry5.internal.services.ResourceStreamer;
 import org.apache.tapestry5.internal.services.assets.ResourceChangeTracker;
 import org.apache.tapestry5.ioc.IOOperation;
 import org.apache.tapestry5.ioc.OperationTracker;
-import org.apache.tapestry5.ioc.annotations.Symbol;
-import org.apache.tapestry5.ioc.annotations.UsesMappedConfiguration;
-import org.apache.tapestry5.services.PathConstructor;
 import org.apache.tapestry5.services.assets.StreamableResource;
 import org.apache.tapestry5.services.assets.StreamableResourceProcessing;
 import org.apache.tapestry5.services.assets.StreamableResourceSource;
 import org.apache.tapestry5.services.javascript.EsShim;
+import org.apache.tapestry5.services.javascript.EsShimManager;
 
 import jakarta.servlet.http.HttpServletResponse;
 
@@ -43,12 +40,9 @@ import jakarta.servlet.http.HttpServletResponse;
  *
  * @see EsShim
  */
-@UsesMappedConfiguration(Resource.class)
 public class EsShimDispatcher implements Dispatcher
 {
     
-    private static final String ES_SUBPATH = "es-shims";
-    
     private final ResourceStreamer streamer;
 
     private final OperationTracker tracker;
@@ -59,27 +53,26 @@ public class EsShimDispatcher implements Dispatcher
     
     private Map<String, StreamableResource> shimMap;
 
-    public EsShimDispatcher(Map<String, Resource> configuration,
+    public EsShimDispatcher(EsShimManager esShimManager,
                             StreamableResourceSource streamableResourceSource,
                             ResourceChangeTracker resourceChangeTracker,
                             ResourceStreamer streamer,
                             OperationTracker tracker,
-                            PathConstructor pathConstructor,
-                            @Symbol(SymbolConstants.ASSET_PATH_PREFIX)
-                            String assetPrefix,
                             boolean compress)
     {
         this.streamer = streamer;
         this.tracker = tracker;
         this.compress = compress;
-        this.shimMap = new HashMap<>(configuration.size());
+        
+        final Map<String, Resource> shims = esShimManager.getShims();
+        this.shimMap = new HashMap<>(shims.size());
         
         try
         {
-            for (String moduleName : configuration.keySet())
+            for (String moduleName : shims.keySet())
             {
                 shimMap.put(moduleName, 
streamableResourceSource.getStreamableResource(
-                        configuration.get(moduleName), 
StreamableResourceProcessing.COMPRESSION_ENABLED, resourceChangeTracker));
+                        shims.get(moduleName), 
StreamableResourceProcessing.COMPRESSION_ENABLED, resourceChangeTracker));
             }
         }
         catch (IOException e)
@@ -87,7 +80,7 @@ public class EsShimDispatcher implements Dispatcher
             throw new RuntimeException(e);
         }
 
-        requestPrefix = pathConstructor.constructDispatchPath(assetPrefix + 
"/" + (compress ? ES_SUBPATH + ".gz" : ES_SUBPATH) + "/");
+        requestPrefix = esShimManager.getRequestPrefix(compress);
     }
 
     public boolean dispatch(Request request, Response response) throws 
IOException
@@ -110,11 +103,6 @@ public class EsShimDispatcher implements Dispatcher
 
     }
     
-    public String getUrl(String moduleName)
-    {
-        return requestPrefix + moduleName;
-    }
-
     private boolean handleModuleRequest(String extraPath, Response response) 
throws IOException
     {
         int dotx = extraPath.lastIndexOf('.');
@@ -141,7 +129,8 @@ public class EsShimDispatcher implements Dispatcher
 
                 if (resource != null)
                 {
-                    return streamer.streamResource(resource, 
resource.getChecksum(), ResourceStreamer.DEFAULT_OPTIONS);
+                    final String checksum = resource.getChecksum();
+                    return streamer.streamResource(resource, checksum, 
ResourceStreamer.DEFAULT_OPTIONS);
                 }
 
                 return false;
diff --git 
a/tapestry-core/src/main/java/org/apache/tapestry5/modules/JavaScriptModule.java
 
b/tapestry-core/src/main/java/org/apache/tapestry5/modules/JavaScriptModule.java
index 8b6bf81a0..3ea83348c 100644
--- 
a/tapestry-core/src/main/java/org/apache/tapestry5/modules/JavaScriptModule.java
+++ 
b/tapestry-core/src/main/java/org/apache/tapestry5/modules/JavaScriptModule.java
@@ -14,7 +14,6 @@ package org.apache.tapestry5.modules;
 
 import java.util.Locale;
 
-import org.apache.tapestry5.Asset;
 import org.apache.tapestry5.BooleanHook;
 import org.apache.tapestry5.MarkupWriter;
 import org.apache.tapestry5.SymbolConstants;
@@ -29,6 +28,7 @@ import org.apache.tapestry5.http.services.Request;
 import org.apache.tapestry5.internal.InternalConstants;
 import org.apache.tapestry5.internal.services.DocumentLinker;
 import org.apache.tapestry5.internal.services.ResourceStreamer;
+import org.apache.tapestry5.internal.services.ajax.EsShimManagerImpl;
 import org.apache.tapestry5.internal.services.ajax.JavaScriptSupportImpl;
 import org.apache.tapestry5.internal.services.ajax.RequireJsModeHelper;
 import org.apache.tapestry5.internal.services.ajax.RequireJsModeHelperImpl;
@@ -50,7 +50,6 @@ import org.apache.tapestry5.ioc.annotations.Primary;
 import org.apache.tapestry5.ioc.annotations.Symbol;
 import org.apache.tapestry5.ioc.services.FactoryDefaults;
 import org.apache.tapestry5.ioc.services.SymbolProvider;
-import org.apache.tapestry5.ioc.services.SymbolSource;
 import org.apache.tapestry5.ioc.util.IdAllocator;
 import org.apache.tapestry5.json.JSONObject;
 import org.apache.tapestry5.services.AssetSource;
@@ -64,13 +63,15 @@ import org.apache.tapestry5.services.MarkupRendererFilter;
 import org.apache.tapestry5.services.PartialMarkupRenderer;
 import org.apache.tapestry5.services.PartialMarkupRendererFilter;
 import org.apache.tapestry5.services.PathConstructor;
+import org.apache.tapestry5.services.assets.StreamableResourceSource;
 import org.apache.tapestry5.services.compatibility.Compatibility;
 import org.apache.tapestry5.services.compatibility.Trait;
 import org.apache.tapestry5.services.javascript.AMDWrapper;
-import org.apache.tapestry5.services.javascript.EsShim;
 import org.apache.tapestry5.services.javascript.EsModuleConfigurationCallback;
 import org.apache.tapestry5.services.javascript.EsModuleManager;
 import 
org.apache.tapestry5.services.javascript.EsModuleManager.EsModuleManagerContribution;
+import org.apache.tapestry5.services.javascript.EsShim;
+import org.apache.tapestry5.services.javascript.EsShimManager;
 import org.apache.tapestry5.services.javascript.ExtensibleJavaScriptStack;
 import org.apache.tapestry5.services.javascript.JavaScriptModuleConfiguration;
 import org.apache.tapestry5.services.javascript.JavaScriptStack;
@@ -108,7 +109,7 @@ public class JavaScriptModule
         binder.bind(JavaScriptStack.class, 
ExtensibleJavaScriptStack.class).withMarker(Core.class).withId("CoreJavaScriptStack");
         binder.bind(JavaScriptStack.class, 
ExtensibleJavaScriptStack.class).withMarker(Internal.class).withId("InternalJavaScriptStack");
         binder.bind(RequireJsModeHelper.class, RequireJsModeHelperImpl.class);
-        binder.bind(EsShimDispatcher.class);
+        binder.bind(EsShimManager.class, EsShimManagerImpl.class);
     }
 
     /**
@@ -135,15 +136,15 @@ public class JavaScriptModule
     /**
      * The core JavaScriptStack has a number of entries:
      * <dl>
-     * <dt>requirejs</dt> <dd>The RequireJS AMD JavaScript library</dd>
+     * <dt>requirejs</dt> <dd>The RequireJS AMD JavaScript library (if 
Require.js is enabled)</dd>
      * <dt>scriptaculous.js, effects.js</dt> <dd>Optional JavaScript libraries 
in compatibility mode (see {@link Trait#SCRIPTACULOUS})</dd>
      * <dt>t53-compatibility.js</dt> <dd>Optional JavaScript library (see 
{@link Trait#INITIALIZERS})</dd>
-     * <dt>underscore-library, underscore-module</dt>
+     * <dt>underscore-library, underscore-module (if Require.js is enabled. An 
ES module version of it is provided by Tapestry)</dt>
      * <dt>The Underscore JavaScript library, and the shim that allows 
underscore to be injected</dt>
      * <dt>t5/core/init</dt> <dd>Optional module related to 
t53-compatibility.js</dd>
-     * <dt>jquery-library</dt> <dd>The jQuery library</dd>
-     * <dt>jquery-noconflict</dt> <dd>Switches jQuery to no-conflict mode 
(only present when the infrastructure is "prototype").</dd>
-     * <dt>jquery</dt> <dd>A module shim that allows jQuery to be injected 
(and also switches jQuery to no-conflict mode)</dd>
+     * <dt>jquery-library</dt> <dd>The jQuery library (if Require.js is 
enabled. An ES module version of it is provided by Tapestry)</dd>
+     * <dt>jquery-noconflict</dt> <dd>Switches jQuery to no-conflict mode 
(only present when the infrastructure is "prototype" and Require.js is 
enabled).</dd>
+     * <dt>jquery</dt> <dd>A module shim that allows jQuery to be injected 
(and also switches jQuery to no-conflict mode) (if Require.js is enabled. An ES 
module version of it is provided by Tapestry)</dd>
      * <dt>bootstrap.css, tapestry.css, exception-frame.css, 
tapestry-console.css, tree.css</dt>
      * <dd>CSS files</dd>
      * <dt>t5/core/[...]</dt>
@@ -159,10 +160,14 @@ public class JavaScriptModule
     public static void 
setupCoreJavaScriptStack(OrderedConfiguration<StackExtension> configuration,
                                                 Compatibility compatibility,
                                                 
@Symbol(SymbolConstants.JAVASCRIPT_INFRASTRUCTURE_PROVIDER)
-                                                String provider)
+                                                String provider,
+                                                
@Symbol(SymbolConstants.REQUIRE_JS_ENABLED) boolean requireJsEnabled)
     {
-        configuration.add("requirejs", StackExtension.library(ROOT + 
"/require.js"));
-        configuration.add("underscore-library", StackExtension.library(ROOT + 
"/underscore-1.13.7.js"));
+        if (requireJsEnabled)
+        {
+            configuration.add("requirejs", StackExtension.library(ROOT + 
"/require.js"));
+            configuration.add("underscore-library", 
StackExtension.library(ROOT + "/underscore-1.13.7.js"));
+        }
 
         if (provider.equals("prototype"))
         {
@@ -180,18 +185,32 @@ public class JavaScriptModule
 
         if (compatibility.enabled(Trait.INITIALIZERS))
         {
-            add(configuration, StackExtensionType.LIBRARY, ROOT + 
"/t53-compatibility.js");
-            configuration.add("t5/core/init", new 
StackExtension(StackExtensionType.MODULE, "t5/core/init"));
+            if (requireJsEnabled)
+            {
+                add(configuration, StackExtensionType.LIBRARY, ROOT + 
"/t53-compatibility.js");
+                configuration.add("t5/core/init", new 
StackExtension(StackExtensionType.MODULE, "t5/core/init"));
+            }
+            else
+            {
+                add(configuration, StackExtensionType.ES_MODULE, 
"t5/core/t53-compatibility");
+                add(configuration, StackExtensionType.ES_MODULE, 
"t5/core/init");
+            }
         }
 
-        configuration.add("jquery-library", StackExtension.library(ROOT + 
"/jquery.js"));
+        if (requireJsEnabled)
+        {
+            configuration.add("jquery-library", StackExtension.library(ROOT + 
"/jquery.js"));
+        }
 
-        if (provider.equals("prototype"))
+        if (provider.equals("prototype") && requireJsEnabled)
         {
             configuration.add("jquery-noconflict", StackExtension.library(ROOT 
+ "/jquery-noconflict.js"));
         }
 
-        add(configuration, StackExtensionType.MODULE, "jquery");
+        if (requireJsEnabled)
+        {
+            add(configuration, StackExtensionType.MODULE, "jquery");
+        }
         
         add(configuration, StackExtensionType.STYLESHEET, "${" + 
SymbolConstants.FONT_AWESOME_ROOT + "}/css/font-awesome.css");
 
@@ -289,11 +308,13 @@ public class JavaScriptModule
                                               JavaScriptStackSource 
javaScriptStackSource,
                                               JavaScriptStackPathConstructor 
javaScriptStackPathConstructor,
                                               LocalizationSetter 
localizationSetter,
+                                              EsShimManager esShimManager,
+                                              StreamableResourceSource 
streamableResourceSource,
+                                              ResourceChangeTracker 
resourceChangeTracker,
                                               
@Symbol(SymbolConstants.MODULE_PATH_PREFIX)
                                               String modulePathPrefix,
                                               
@Symbol(SymbolConstants.ASSET_PATH_PREFIX)
-                                              String assetPathPrefix,
-                                              EsShimDispatcher 
esShimDispatcher)
+                                              String assetPathPrefix)
     {
         configuration.add("Modules",
                 new ModuleDispatcher(moduleManager, resourceStreamer, tracker, 
pathConstructor,
@@ -307,7 +328,13 @@ public class JavaScriptModule
                     assetPathPrefix, true),
                 "after:Modules", "before:ComponentEvent");
         
-        configuration.add("EsShims", esShimDispatcher, "after:Asset", 
"before:ComponentEvent");
+        configuration.add("EsShims", new EsShimDispatcher(esShimManager, 
streamableResourceSource, resourceChangeTracker, 
+                resourceStreamer, tracker, false),
+                "before:Asset", "before:ComponentEvent");
+        
+        configuration.add("CompressedEsShims", new 
EsShimDispatcher(esShimManager, streamableResourceSource, 
resourceChangeTracker, 
+                resourceStreamer, tracker, true),
+                "after:EsShims", "before:Asset", "before:ComponentEvent");
 
     }
 
@@ -552,7 +579,7 @@ public class JavaScriptModule
         
     }
 
-    @Contribute(EsShimDispatcher.class)
+    @Contribute(EsShimManager.class)
     public static void setupBaseEsShims(
             MappedConfiguration<String, Resource> configuration,
             @Path("${tapestry.asset.root}/bootstrap/js/transition.js")
@@ -560,11 +587,14 @@ public class JavaScriptModule
             @Path("${tapestry.asset.root}/bootstrap4/js/bootstrap-util.js")
             Resource bootstrapUtil,
             Compatibility compatibility,
-            AssetSource assetSource,
-            EsShimDispatcher esShimDispatcher)
+            AssetSource assetSource)
     {
         
-//        configuration.add("jquery", new 
JavaScriptModuleConfiguration(jqueryShim));
+        final Resource jQuery = 
assetSource.getClasspathAsset("/META-INF/assets/tapestry5/jquery.js")
+                .getResource();
+        configuration.add("jquery", new EsShim(jQuery)
+                .defaultExport("jQuery.noConflict()")
+                .getResource());
         
         if (compatibility.enabled(Trait.BOOTSTRAP_3))
         {
@@ -576,25 +606,23 @@ public class JavaScriptModule
 
             final String popoverModuleName = "bootstrap/popover";
             configuration.add(popoverModuleName,
-                    EsModuleManagerContribution.base(
-                            new 
EsShim(popover).importModule("bootstrap/tooltip"),
-                            createCallback(popoverModuleName, 
esShimDispatcher)));
+                    new EsShim(popover)
+                        .importModule("jquery")
+                        .importModule("bootstrap/tooltip")
+                        .getResource());
         }
 
         if (compatibility.enabled(Trait.BOOTSTRAP_4))
         {
             final String bootstrapUtilModuleName = "bootstrap/bootstrap-util";
             configuration.add(bootstrapUtilModuleName, 
-                    EsModuleManagerContribution.base(
-                            new EsShim(bootstrapUtil), 
-                            createCallback(bootstrapUtilModuleName, 
esShimDispatcher)));
+                    new EsShim(bootstrapUtil)
+                        .getResource());
             
             final String popperModuleName = "bootstrap/popper";
             final Resource popper = bootstrapUtil.forFile("popper.js");
             configuration.add(popperModuleName, 
-                    EsModuleManagerContribution.base(
-                            new EsShim(popper), 
-                            createCallback(popperModuleName, 
esShimDispatcher)));
+                    new EsShim(popper).getResource());
             
             for (String name : new String[]{"alert", "button", "carousel", 
"collapse", "dropdown", "modal",
                     "scrollspy", "tab", "tooltip"})
@@ -604,11 +632,10 @@ public class JavaScriptModule
                 {
                     final String moduleName = "bootstrap/" + name;
                     configuration.add(moduleName, 
-                            EsModuleManagerContribution.base(
-                                    new EsShim(lib)
-                                        .importModule(bootstrapUtilModuleName)
-                                        .importModule(popperModuleName), 
-                                    createCallback(popperModuleName, 
esShimDispatcher)));
+                            new EsShim(lib)
+                                .importModule(bootstrapUtilModuleName)
+                                .importModule(popperModuleName)
+                                .getResource());
                 }
             }
         }
@@ -622,78 +649,16 @@ public class JavaScriptModule
         }
     }
 
-//    @Contribute(EsModuleManager.class)
-//    public static void setupBaseEsModules(
-//            OrderedConfiguration<EsModuleManagerContribution> configuration,
-//            @Path("${tapestry.asset.root}/bootstrap/js/transition.js")
-//            Resource transition,
-//            @Path("${tapestry.asset.root}/bootstrap4/js/bootstrap-util.js")
-//            Resource bootstrapUtil,
-//            Compatibility compatibility,
-//            AssetSource assetSource,
-//            EsShimDispatcher esShimDispatcher)
-//    {
-//        
-////        configuration.add("jquery", new 
JavaScriptModuleConfiguration(jqueryShim));
-//        
-//        if (compatibility.enabled(Trait.BOOTSTRAP_3))
-//        {
-//            final String[] modules = new String[]{"affix", "alert", 
"button", "carousel", "collapse", "dropdown", "modal",
-//                    "scrollspy", "tab", "tooltip"};
-//            addBootstrap3EsShims(configuration, modules, transition);
-//
-//            Resource popover = transition.forFile("popover.js");
-//
-//            final String popoverModuleName = "bootstrap/popover";
-//            configuration.add(popoverModuleName,
-//                    EsModuleManagerContribution.base(
-//                            new 
EsShim(popover).importModule("bootstrap/tooltip"),
-//                            createCallback(popoverModuleName, 
esShimDispatcher)));
-//        }
-//
-//        if (compatibility.enabled(Trait.BOOTSTRAP_4))
-//        {
-//            final String bootstrapUtilModuleName = 
"bootstrap/bootstrap-util";
-//            configuration.add(bootstrapUtilModuleName, 
-//                    EsModuleManagerContribution.base(
-//                            new EsShim(bootstrapUtil), 
-//                            createCallback(bootstrapUtilModuleName, 
esShimDispatcher)));
-//            
-//            final String popperModuleName = "bootstrap/popper";
-//            final Resource popper = bootstrapUtil.forFile("popper.js");
-//            configuration.add(popperModuleName, 
-//                    EsModuleManagerContribution.base(
-//                            new EsShim(popper), 
-//                            createCallback(popperModuleName, 
esShimDispatcher)));
-//            
-//            for (String name : new String[]{"alert", "button", "carousel", 
"collapse", "dropdown", "modal",
-//                    "scrollspy", "tab", "tooltip"})
-//            {
-//                Resource lib = bootstrapUtil.forFile(name + ".js");
-//                if (lib.exists())
-//                {
-//                    final String moduleName = "bootstrap/" + name;
-//                    configuration.add(moduleName, 
-//                            EsModuleManagerContribution.base(
-//                                    new EsShim(lib)
-//                                        
.importModule(bootstrapUtilModuleName)
-//                                        .importModule(popperModuleName), 
-//                                    createCallback(popperModuleName, 
esShimDispatcher)));
-//                }
-//            }
-//        }
-//
-//        // Just the minimum to have alerts and AJAX validation working when 
Bootstrap
-//        // is completely disabled
-//        if (!compatibility.enabled(Trait.BOOTSTRAP_3) && 
!compatibility.enabled(Trait.BOOTSTRAP_4))
-//        {
-//            final String[] modules = new String[]{"alert", "dropdown", 
"collapse"};
-//            addBootstrap3EsShims(configuration, modules, transition);
-//        }
-//    }
-
-    private static EsModuleConfigurationCallback createCallback(final String 
moduleName, EsShimDispatcher esShimDispatcher) {
-        return c -> EsModuleConfigurationCallback.setImport(c, moduleName, 
esShimDispatcher.getUrl(moduleName));
+    @Contribute(EsModuleManager.class)
+    public static void setupBaseEsModules(
+            OrderedConfiguration<EsModuleManagerContribution> configuration,
+            EsShimManager esShimManager)
+    {
+        for (String moduleName : esShimManager.getShims().keySet())
+        {
+            configuration.add(moduleName, EsModuleManagerContribution.base(
+                    c -> EsModuleConfigurationCallback.setImport(c, 
moduleName, esShimManager.getUrl(moduleName))));
+        }
     }
 
     private static void addBootstrap3EsShims(
@@ -707,7 +672,9 @@ public class JavaScriptModule
             final Resource resource = reference.forFile(module + ".js");
             if (resource.exists())
             {
-                configuration.add(moduleId, resource);
+                configuration.add(moduleId, new EsShim(resource)
+                        .importModule("jquery")
+                        .getResource());
             }
         }
     }
diff --git 
a/tapestry-core/src/main/java/org/apache/tapestry5/modules/TapestryModule.java 
b/tapestry-core/src/main/java/org/apache/tapestry5/modules/TapestryModule.java
index 73a69419e..0709fd572 100644
--- 
a/tapestry-core/src/main/java/org/apache/tapestry5/modules/TapestryModule.java
+++ 
b/tapestry-core/src/main/java/org/apache/tapestry5/modules/TapestryModule.java
@@ -1810,6 +1810,9 @@ public final class TapestryModule
 
                                          
@Symbol(SymbolConstants.ENABLE_PAGELOADING_MASK)
                                          final boolean enablePageloadingMask,
+                                         
+                                         
@Symbol(SymbolConstants.REQUIRE_JS_ENABLED)
+                                         final boolean requireJsEnabled,
 
                                          final ValidationDecoratorFactory 
validationDecoratorFactory)
     {
@@ -1817,7 +1820,9 @@ public final class TapestryModule
         {
             public void renderMarkup(MarkupWriter writer, MarkupRenderer 
renderer)
             {
-                DocumentLinkerImpl linker = new 
DocumentLinkerImpl(moduleManager, esModuleManager, omitGeneratorMeta, 
enablePageloadingMask, tapestryVersion);
+                DocumentLinkerImpl linker = new 
DocumentLinkerImpl(moduleManager, 
+                        esModuleManager, omitGeneratorMeta, 
enablePageloadingMask, 
+                        tapestryVersion, requireJsEnabled);
 
                 environment.push(DocumentLinker.class, linker);
 
diff --git 
a/tapestry-core/src/main/java/org/apache/tapestry5/services/javascript/EsModuleManager.java
 
b/tapestry-core/src/main/java/org/apache/tapestry5/services/javascript/EsModuleManager.java
index edd3dfbb0..277d02d99 100644
--- 
a/tapestry-core/src/main/java/org/apache/tapestry5/services/javascript/EsModuleManager.java
+++ 
b/tapestry-core/src/main/java/org/apache/tapestry5/services/javascript/EsModuleManager.java
@@ -45,7 +45,7 @@ public interface EsModuleManager
     /**
      * Invoked by the internal {@link 
org.apache.tapestry5.internal.services.DocumentLinker} service to write the 
      * ES module imports (as per {@link 
JavaScriptSupport#importEsModule(String)} into the page. 
-     * this occurs after the ES module infrastructure
+     * This occurs after the ES module infrastructure
      * has been written into the page, along with the core libraries.
      *
      * @param root
@@ -55,6 +55,18 @@ public interface EsModuleManager
      */
     void writeImports(Element root, List<EsModuleInitialization> inits);
     
+
+    /**
+     * Invoked by the internal {@link 
org.apache.tapestry5.internal.services.DocumentLinker} service to write the 
+     * calls to {@code t5/core/pageinit} module.
+     * this occurs after the ES module infrastructure
+     * has been written into the page, along with the core libraries.
+     *
+     * @param root
+     *         {@code <root>} element of the page.
+     */
+    void writeInitialization(Element body, List<String> libraryURLs);
+    
     /**
      * Encapsulates a contribution to {@linkplain EsModuleManager}.
      *
diff --git 
a/tapestry-core/src/main/java/org/apache/tapestry5/services/javascript/EsShim.java
 
b/tapestry-core/src/main/java/org/apache/tapestry5/services/javascript/EsShim.java
index ca20f71b4..89a2cde2d 100644
--- 
a/tapestry-core/src/main/java/org/apache/tapestry5/services/javascript/EsShim.java
+++ 
b/tapestry-core/src/main/java/org/apache/tapestry5/services/javascript/EsShim.java
@@ -17,8 +17,9 @@ import java.io.IOException;
 import java.io.InputStream;
 import java.io.SequenceInputStream;
 import java.net.URL;
-import java.util.LinkedHashMap;
+import java.util.HashMap;
 import java.util.Map;
+import java.util.Vector;
 
 import org.apache.tapestry5.commons.Resource;
 import org.apache.tapestry5.internal.util.VirtualResource;
@@ -29,7 +30,8 @@ import org.apache.tapestry5.internal.util.VirtualResource;
  *
  * @since 5.10.0
  */
-public class EsShim {
+public class EsShim 
+{
 
     /**
      * The underlying resource, usually a JavaScript library
@@ -41,9 +43,15 @@ public class EsShim {
      * the values being the respective parameter names for the module's factory
      * function.
      */
-    private final Map<String, String> importConfig = new LinkedHashMap<String, 
String>();
+    private final Map<String, String> importConfig = new HashMap<String, 
String>();
+    
+    /**
+     * The default export.
+     */
+    private String defaultExport;
 
-    public EsShim(final Resource resource) {
+    public EsShim(final Resource resource) 
+    {
         this.resource = resource;
     }
 
@@ -54,10 +62,11 @@ public class EsShim {
      *            the name of the required module, e.g. <code>jQuery</code>
      * @param variableName
      *            the module's corresponding variable name
-     * @return this ESWrapper for further configuration
+     * @return this EsShim for further configuration
      */
     public EsShim importModule(final String moduleName,
-            final String variableName) {
+            final String variableName) 
+    {
         importConfig.put(moduleName, variableName);
         return this;
     }
@@ -70,72 +79,104 @@ public class EsShim {
      * @param moduleName
      *            the name of the required module, e.g.
      *            <code>bootstrap/transition</code>
-     * @return this ESWrapper for further configuration
+     * @return this EsShim for further configuration
      */
-    public EsShim importModule(final String moduleName) {
+    public EsShim importModule(final String moduleName) 
+    {
         importConfig.put(moduleName, null);
         return this;
     }
+    
+    /**
+     * Defines the default export of this module.
+     * @param defaultExport the variable or expression to be the 
+     * default export of the module
+     * @return this EsShim for further configuration
+     */
+    public EsShim defaultExport(final String defaultExport)
+    {
+        this.defaultExport = defaultExport;
+        return this;
+    }
 
     /**
-     * Returns a virtual resource representing this wrapper.
+     * Returns a virtual resource representing this shim.
      * @return a {@linkplain Resource}.
      */
-    public Resource getResource() {
-        return new ESModuleWrapperResource(resource, importConfig);
+    public Resource getResource() 
+    {
+        return new ESModuleWrapperResource(resource, importConfig, 
defaultExport);
     }
 
     /**
-     * A virtual resource that wraps a plain JavaScript library as an AMD
+     * A virtual resource that wraps a plain JavaScript library as an ES
      * module.
-     *
      */
     private final static class ESModuleWrapperResource extends VirtualResource 
     {
         private final Resource resource;
         private final Map<String, String> importConfig;
+        private final String defaultExport;
 
         public ESModuleWrapperResource(final Resource resource,
-                final Map<String, String> importConfig) 
+                final Map<String, String> importConfig, 
+                final String defaultExport) 
         {
             this.resource = resource;
             this.importConfig = importConfig;
+            this.defaultExport = defaultExport;
         }
 
         @Override
         public InputStream openStream() throws IOException 
         {
-            StringBuilder sb = new StringBuilder();
+            StringBuilder imports = new StringBuilder();
             
             for (String module : importConfig.keySet())
             {
                 final String variableName = importConfig.get(module);
-                sb.append("import ");
+                imports.append("import ");
                 if (variableName != null) 
                 {
-                    sb.append(variableName);
-                    sb.append(" from ");
+                    imports.append(variableName);
+                    imports.append(" from ");
                 }
-                sb.append("\"");
-                sb.append(module);
-                sb.append("\";\n");
+                imports.append("\"");
+                imports.append(module);
+                imports.append("\";\n");
             }
             
-            return new SequenceInputStream(toInputStream(sb), 
resource.openStream());
+            
+            // Vector since SequenceInputStream doesn't have a varargs 
constructor
+            // nor something better than an Enumeration when you have more 
than 
+            // 2 InputStreams to join.
+            Vector<InputStream> v = new Vector<>();
+            v.add(toInputStream(imports));
+            v.add(resource.openStream());
+            if (defaultExport != null)
+            {
+                v.add(toInputStream(String.format("\n export default %s;\n",
+                        defaultExport)));
+            }
+            
+            return new SequenceInputStream(v.elements());
         }
 
         @Override
-        public String getFile() {
+        public String getFile() 
+        {
             return "generated-module-for-" + resource.getFile();
         }
 
         @Override
-        public URL toURL() {
+        public URL toURL() 
+        {
             return null;
         }
 
         @Override
-        public String toString() {
+        public String toString() 
+        {
             return "ES module wrapper for " + resource.toString();
         }
 
diff --git 
a/tapestry-core/src/main/java/org/apache/tapestry5/services/javascript/EsShimManager.java
 
b/tapestry-core/src/main/java/org/apache/tapestry5/services/javascript/EsShimManager.java
new file mode 100644
index 000000000..f9d5c5f13
--- /dev/null
+++ 
b/tapestry-core/src/main/java/org/apache/tapestry5/services/javascript/EsShimManager.java
@@ -0,0 +1,49 @@
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package org.apache.tapestry5.services.javascript;
+
+import java.util.Map;
+
+import org.apache.tapestry5.commons.Resource;
+import org.apache.tapestry5.ioc.annotations.UsesMappedConfiguration;
+
+/**
+ * Service managing the ES shims.
+ *
+ * @since 5.10.0
+ */
+@UsesMappedConfiguration(Resource.class)
+public interface EsShimManager
+{
+    
+    /**
+     * Returns the shims as a (module name, module resource) map.
+     * @return a {@code Map<String, Resource>}
+     */
+    Map<String, Resource> getShims();
+
+    /**
+     * Returns the request prefix to be used for ES shim URLs.
+     * @param compress a {@code boolean} to inform whether it's the compressed 
asset URL or not.
+     * @return the request prefix.
+     */
+    String getRequestPrefix(boolean compress);
+    
+    /**
+     * Returns the full URL of a module.
+     * @param moduleName a module name.
+     * @return its URL.
+     */
+    String getUrl(String moduleName);
+    
+}
diff --git 
a/tapestry-core/src/main/java/org/apache/tapestry5/services/javascript/ExtensibleJavaScriptStack.java
 
b/tapestry-core/src/main/java/org/apache/tapestry5/services/javascript/ExtensibleJavaScriptStack.java
index 8fa030fe5..0845431dd 100644
--- 
a/tapestry-core/src/main/java/org/apache/tapestry5/services/javascript/ExtensibleJavaScriptStack.java
+++ 
b/tapestry-core/src/main/java/org/apache/tapestry5/services/javascript/ExtensibleJavaScriptStack.java
@@ -12,6 +12,8 @@
 
 package org.apache.tapestry5.services.javascript;
 
+import java.util.List;
+
 import org.apache.tapestry5.Asset;
 import org.apache.tapestry5.func.F;
 import org.apache.tapestry5.func.Flow;
@@ -23,8 +25,6 @@ import 
org.apache.tapestry5.ioc.annotations.UsesOrderedConfiguration;
 import org.apache.tapestry5.ioc.internal.util.InternalUtils;
 import org.apache.tapestry5.services.AssetSource;
 
-import java.util.List;
-
 /**
  * An extensible implementation of {@link JavaScriptStack} that can be used as 
the implementation of a service.
  * The contributions to the service are used to supply the libraries, 
stylesheets, and initialization for a
@@ -50,6 +50,8 @@ public class ExtensibleJavaScriptStack implements 
JavaScriptStack
     private final List<String> stacks;
 
     private final List<String> modules;
+    
+    private final List<String> esModules;
 
     private final String initialization;
 
@@ -116,6 +118,8 @@ public class ExtensibleJavaScriptStack implements 
JavaScriptStack
         stacks = 
extensions.filter(by(StackExtensionType.STACK)).map(extractValue).toList();
 
         modules = 
extensions.filter(by(StackExtensionType.MODULE)).map(extractValue).toList();
+        
+        esModules = 
extensions.filter(by(StackExtensionType.ES_MODULE)).map(extractValue).toList();
 
         stylesheets = 
extensions.filter(by(StackExtensionType.STYLESHEET)).map(extractValue).map(stringToAsset)
                 .map(assetToStylesheetLink).toList();
@@ -147,31 +151,41 @@ public class ExtensibleJavaScriptStack implements 
JavaScriptStack
         }
     }
 
+    @Override
     public List<String> getStacks()
     {
         return stacks;
     }
 
+    @Override
     public List<Asset> getJavaScriptLibraries()
     {
         return libraries;
     }
 
+    @Override
     public List<StylesheetLink> getStylesheets()
     {
         return stylesheets;
     }
 
+    @Override
     public String getInitialization()
     {
         return initialization;
     }
 
+    @Override
     public List<String> getModules()
     {
         return modules;
     }
 
+    @Override
+    public List<String> getEsModules() {
+        return esModules;
+    }
+
     @Override
     public JavaScriptAggregationStrategy getJavaScriptAggregationStrategy()
     {
diff --git 
a/tapestry-core/src/main/java/org/apache/tapestry5/services/javascript/JavaScriptStack.java
 
b/tapestry-core/src/main/java/org/apache/tapestry5/services/javascript/JavaScriptStack.java
index 777c7a118..25555e396 100644
--- 
a/tapestry-core/src/main/java/org/apache/tapestry5/services/javascript/JavaScriptStack.java
+++ 
b/tapestry-core/src/main/java/org/apache/tapestry5/services/javascript/JavaScriptStack.java
@@ -72,6 +72,14 @@ public interface JavaScriptStack
      * @since 5.4
      */
     List<String> getModules();
+    
+    /**
+     * Returns a list of ES modules to be automatically included in all pages.
+     * 
+     * @see EsModuleManager
+     * @since 5.10.0
+     */
+    List<String> getEsModules();
 
     /**
      * Identifies how to aggregate JavaScript within the stack.
diff --git 
a/tapestry-core/src/main/java/org/apache/tapestry5/services/javascript/StackExtension.java
 
b/tapestry-core/src/main/java/org/apache/tapestry5/services/javascript/StackExtension.java
index 67cc22d7b..42c463f38 100644
--- 
a/tapestry-core/src/main/java/org/apache/tapestry5/services/javascript/StackExtension.java
+++ 
b/tapestry-core/src/main/java/org/apache/tapestry5/services/javascript/StackExtension.java
@@ -62,6 +62,16 @@ public class StackExtension
         return new StackExtension(StackExtensionType.MODULE, name);
     }
 
+    /**
+     * Convenience for defining an ES_MODULE.
+     *
+     * @since 5.10.0
+     */
+    public static StackExtension esModule(String name)
+    {
+        return new StackExtension(StackExtensionType.ES_MODULE, name);
+    }
+
     /**
      * Convenience for defining a STYLESHEET.
      *
diff --git 
a/tapestry-core/src/main/java/org/apache/tapestry5/services/javascript/StackExtensionType.java
 
b/tapestry-core/src/main/java/org/apache/tapestry5/services/javascript/StackExtensionType.java
index a4f0d7b48..0dccf2e44 100644
--- 
a/tapestry-core/src/main/java/org/apache/tapestry5/services/javascript/StackExtensionType.java
+++ 
b/tapestry-core/src/main/java/org/apache/tapestry5/services/javascript/StackExtensionType.java
@@ -69,6 +69,13 @@ public enum StackExtensionType
      * @since 5.4
      */
     MODULE,
+    
+    /**
+     * An ES module to be automatically imported.
+     * 
+     * @since 5.10.0
+     */
+    ES_MODULE,
 
     /**
      * Overrides the {@linkplain 
JavaScriptStack#getJavaScriptAggregationStrategy() JavaScript aggregation 
strategy}
diff --git 
a/tapestry-core/src/main/resources/META-INF/assets/es-modules/t5/underscore.js 
b/tapestry-core/src/main/resources/META-INF/assets/es-modules/t5/underscore.js
deleted file mode 100644
index dd5899219..000000000
--- 
a/tapestry-core/src/main/resources/META-INF/assets/es-modules/t5/underscore.js
+++ /dev/null
@@ -1,5 +0,0 @@
-//     Underscore.js 1.13.7
-//     https://underscorejs.org
-//     (c) 2009-2024 Jeremy Ashkenas, Julian Gonggrijp, and DocumentCloud and 
Investigative Reporters & Editors
-//     Underscore may be freely distributed under the MIT license.
-var VERSION="1.13.7",root="object"==typeof 
self&&self.self===self&&self||"object"==typeof 
global&&global.global===global&&global||Function("return 
this")()||{},ArrayProto=Array.prototype,ObjProto=Object.prototype,SymbolProto="undefined"!=typeof
 
Symbol?Symbol.prototype:null,push=ArrayProto.push,slice=ArrayProto.slice,toString=ObjProto.toString,hasOwnProperty=ObjProto.hasOwnProperty,supportsArrayBuffer="undefined"!=typeof
 ArrayBuffer,supportsDataView="undefined"!=typeof DataView,nativeIsAr [...]
\ No newline at end of file
diff --git a/tapestry-core/src/main/typescript/src/t5/core/t53-compatibility.ts 
b/tapestry-core/src/main/typescript/src/t5/core/t53-compatibility.ts
new file mode 100644
index 000000000..5edf150a1
--- /dev/null
+++ b/tapestry-core/src/main/typescript/src/t5/core/t53-compatibility.ts
@@ -0,0 +1,56 @@
+// Copyright 2012, 2015 The Apache Software Foundation
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http:#www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Provides a small amount of backwards compatibility to the Tapestry 5.3 
approach.
+// This provides placeholders for the following:
+//
+// * `T5` namespace, including `extend`, `define`, and `initializers`, 
`extendInitializers`, and `_` properties
+//
+// * `Tapestry` namespace: just the `Initializer` property, as an alias of 
`T5.initializers`
+
+import _ from "underscore";
+
+// @ts-ignore
+var T5, Tapestry;
+T5 = {
+    _: _,
+    // @ts-ignore
+    extend: function(destination, source) {
+        if (_.isFunction(source)) {
+            source = source();
+        }
+        return _.extend(destination, source);
+    },
+    // @ts-ignore
+    define: function(name, source) {
+        var namespace;
+        namespace = {};
+        T5[name] = namespace;
+        // @ts-ignore
+        return T5.extend(namespace, source);
+    },
+    initializers: {},
+    // @ts-ignore
+    extendInitializers: function(source) {
+        // @ts-ignore
+        return T5.extend(T5.initializers, source);
+    }
+};
+Tapestry = {
+    Initializer: T5.initializers
+};
+// @ts-ignore
+window.T5 = T5;
+// @ts-ignore
+window.Tapestry = Tapestry;
diff --git 
a/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/components/Border.java
 
b/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/components/Border.java
index b5a6d8e13..5ffe581ea 100644
--- 
a/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/components/Border.java
+++ 
b/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/components/Border.java
@@ -13,9 +13,11 @@
 package org.apache.tapestry5.integration.app1.components;
 
 import org.apache.tapestry5.ComponentResources;
+import org.apache.tapestry5.annotations.BeginRender;
 import org.apache.tapestry5.annotations.Import;
 import org.apache.tapestry5.annotations.Property;
 import org.apache.tapestry5.http.services.Request;
+import org.apache.tapestry5.internal.services.ajax.RequireJsModeHelper;
 import org.apache.tapestry5.ioc.annotations.Inject;
 import org.apache.tapestry5.services.pageload.PageClassLoaderContextManager;
 
@@ -25,7 +27,7 @@ import java.util.Calendar;
  * Here's a component with a template, including a t:body element. Really 
should rename this to "Layout" as that's the
  * T5 naming.
  */
-@Import(stylesheet = "context:css/app.css", module = {"bootstrap/collapse", 
"app/test-support"})
+@Import(stylesheet = "context:css/app.css")
 public class Border
 {
     @Inject
@@ -37,6 +39,9 @@ public class Border
     
     @Inject @Property
     private PageClassLoaderContextManager pccm; 
+    
+    @Inject
+    private RequireJsModeHelper requireJsModeHelper;
 
     public static final int year;
 
@@ -67,4 +72,11 @@ public class Border
         return version + " from " + System.getProperty("java.vendor");
     }
     
+    @BeginRender
+    void beginRender()
+    {
+        requireJsModeHelper.importModule("bootstrap/collapse");
+        requireJsModeHelper.importModule("app/test-support");
+    }
+    
 }
diff --git 
a/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/Index.java
 
b/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/Index.java
index 42338f94a..fcad59e0a 100644
--- 
a/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/Index.java
+++ 
b/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/Index.java
@@ -58,581 +58,581 @@ public class Index
     private static final List<Item> ITEMS = CollectionFactory
             .newList(
                     
-//                    new Item("PublishEventDemo", "@PublishEvent Demo", 
"Publishing server-side events to client-side code (JavaScript)"),
-//
-//                    new Item("StaticActivationContextValueDemo", 
"@StaticActivationContextValue Demo", "Demonstrates the usage of 
@StaticActivationContextValue"),
-//                    
-//                    new Item("rest/RestWithOnEventDemo", "REST with @OnEvent 
Demo", "Demonstrates the usage of @OnEvent to handle REST requests"),           
         
-//                    
-//                    new Item("rest/RestWithEventHandlerMethodNameDemo", 
"REST with Event Handler Method Name Demo", "Demonstrates the usage of event 
handler method names to handle REST requests"),
-//
-//                    new Item("Html5DateFieldDemo", "Html5DateField Demo", 
"Choosing dates using the native HTML5 date picker"),
-//
-////                    new Item("ZoneFormDemo", "Zone Form Decoration", 
"Fields inside an Ajax-updatd Form are still decorated properly."),
-//
-//                    new Item("AjaxValidationDemo", "Ajax Validation", 
"Demonstrated proper integration of server-side validation and client-side 
field decoration."),
-//
-//                    new Item("OverrideEventHandlerDemo", "Event Handler 
Override Demo", "Event Handler methods overridden by sub-classes invoke 
base-class correctly."),
-//
-//                    new Item("LogoSubclass", "Base class Assets in 
sub-classes", "Assets are resolved for the parent class if that's where the 
annotations are."),
-//
-//                    new Item("MissingRequiredARP", "Missing Query Parameter 
for @ActivationRequestParameter", "Activating a page with a required 
@ActivationRequestParameter, but no matching query parameter, is an error."),
-//
-////                    new Item("DateFieldValidationDemo", "DateField 
Validation Demo",
-////                            "Use of DateField component when client 
validation is disabled."),
-//
-//                    new Item("MixinParameters54", "Strict Mixin Parameters", 
"In the 5.4 DTD, Parameter Mixins must be qualified with the mixin id."),
-//
-//                    new Item("AsyncDemo", "Async Links and Forms Demo", 
"Async (XHR) Updates without a containing Zone."),
-//
-//                    new Item("FormCancelActionDemo", "Form Cancel Action 
Demo", "FormSupport.addCancel() support"),
-//
-//                    new Item("AjaxRadioDemo", "Ajax Radio Demo", "Radio 
components inside an Ajax form"),
-//
-//                    new Item("TimeIntervalDemo", "TimeInterval Demo", 
"Interval component, based on Moment.js"),
-//
-//                    new Item("LocalDateDemo", "LocalDate Demo", "LocalDate 
component, based on Moment.js"),
-//
-//                    new Item("EmptyIfDemo", "Empty If Demo", "Ensure an 
empty If can still render."),
-//
-//                    new Item("MissingAssetDemo", "Missing Asset Demo", 
"Error when injecting an asset that does not exist."),
-//
-//                    new Item("ConfirmDemo", "Confirm Mixin Demo", "Confirm 
an action when clicking it."),
-//
-//                    new Item("SingleErrorDemo", "Single Error", "Using Error 
component to customize where the errors for a field will be displayed."),
-//
-//                    new Item("JavaScriptTests", "JavaScript Tests", 
"Client-side tests using Mocha and Chai"),
-//
-//                    new Item("ModuleInitDemo", "Module-based Initialization 
Demo", "Invoke a module function to perform page initialization"),
-//
-//                    new Item("OperationWorkerDemo", "Operation Worker Demo", 
"Demonstrate use of @Operation annotation on component methods"),
-//
-//                    new Item("MixinParameterDefault", "Mixin Parameter with 
Default", "Ensure that a mixin parameter with a default value is not reported 
as unbound."),
-//
-//                    new Item("MixinVsInformalParameter", "Mixin Parameter 
vs. Informal Parameter", "Informal Paramters vs. Mixin parameter of same name"),
-//
-//                    new Item("inherit/childa", "TAP5-1656 Demo", "Test a 
reported bug in component inheritance"),
-//
-//                    new Item("ComponentInsideBlockDemo", "Component Inside 
Block Demo", "Verify that a component, inside a block, is still an embedded "),
-//
-//                    new Item("EventMethodUnmatchedComponentId", "Unmatched 
Component Id in Event Method Demo", "Show that referencing a component that 
does not exist in an event handler method name is an error."),
-//
-//                    new Item("AlertsDemo", "Alerts Demo", "Managing alerts 
both traditional and Ajax"),
-//
-//                    new Item("ClientConsoleDemo", "Client Console Demo", 
"Demo for the JavaScript client-side console"),
-//
-//                    new Item("InvalidFormalParameterDemo", "Unmatched Formal 
Parameter with @Component", "Parameters specified with @Component annotation 
must match formal parameters"),
-//
-//                    new Item("NullBindingToPrimitive", "Null Bound to 
Primitive Demo", "Correct exception when a primitive parameter is bound to 
null"),
-//
-//                    new Item("TreeDemo", "Tree Component Demo", "Demo of 
Tree Component"),
-//
-//                    new Item("TreeSelectionDemo", "Tree Component Selection 
Demo", "Demo of Selection with Tree Component"),
-//
-//                    new Item("TreeNoRootsDemo", "Tree Component No Roots 
Demo", "Demo of No Roots with Tree Component"),
-//
-//                    new Item("InvalidExpressionInDynamicTemplate", "Invalid 
Dynamic Expression",
-//                            "Invalid expression in a Dynamic Template"),
-//
-//                    new Item("DynamicDemo", "Dynamic Demo", "Basic Dynamic 
component tests"),
-//
-//                    new Item("DynamicExpansionsDemo", "Expansions in Dynamic 
Templates",
-//                            "Expansions inside Dynamic component content and 
attributes"),
-//
-//                    new Item("PACAnnotationDemo", "PageActivationContext 
Demo",
-//                            "Shows that @PageActivationContext fields are 
set before calls to the activate event handler."),
-//
-//                    new Item("PACMultipleAnnotationDemo", 
"PageActivationContext Multiple Demo",
-//                            "Demonstrates multiple @PageActivationContext 
fields."),
-//
-//                    new Item("PublicFieldAccessDemo", "Public Field Access 
Demo", "Demonstrates TAP5-1222 fix"),
-//
-//                    new Item("ActivationRequestParameterDemo", 
"ActivationRequestParameter Annotation Demo",
-//                            "Use of @ActivationRequestParameter to encode 
page state into query parameters"),
-//
-//                    new Item("LibraryMessagesDemo", "Library Messages Demo",
-//                            "Demo ability to contribute additional message 
catalog resources to the application global catalog."),
-//
-//                    new Item("MultiZoneUpdateInsideForm", "MultiZone Update 
inside a Form",
-//                            "Update multiple zones within a single Form."),
-//
-//                    new Item("ZoneFormUpdateDemo", "Zone/Form Update Demo", 
"Updating a Zone inside a Form"),
-//
-//                    new Item("MultiZoneStringBodyDemo", "MultiZone String 
Body Demo",
-//                            "Multi-zone updates in a loop using strings 
coerced into blocks"),
-//
-//                    new Item("RenderNotificationDemo", "RenderNotification 
Demo", "Use of RenderNotification mixin"),
-//
-//                    new Item("InjectMessagesDemo", "Inject Global Messages 
into Service Demo",
-//                            "Ensure that it is possible to inject the 
application global message catalog into a service"),
-//
-//                    new Item("ReloadDemo", "Reloadable Service 
Implementation Demo",
-//                            "Used when manually testing service reloads"),
-//
-//                    new Item("RequestParameterDemo", "RequestParameter 
Annotation Demo",
-//                            "Use of @RequestParameter annotation on event 
handler method parameters"),
-//
-//                    new Item("CancelDemo", "Cancel Demo", "Use of the cancel 
option with Submit"),
-//
-//                    new Item("CanceledEventDemo", "Canceled Event Demo", 
"Triggering of the canceled event from a form."),
-//
-//                    new Item("PageResetDemo", "PageReset Annotation Demo",
-//                            "Use of PageReset annotation to re-initialize 
page state"),
-//
-//                    new Item("TestOnlyServiceDemo", "Test Only Service Demo",
-//                            "IoC module available via web.xml 
configuration"),
-//
-//                    new Item("RenderObjectExceptionDemo", "RenderObject 
Exception Demo",
-//                            "Demonstrate how exceptions when rendering 
default objects are displayed."),
-//
-//                    new Item("MultiLevelInheritDemo", "Multi-Level Inherit 
Demo",
-//                            "Use of inherit: binding prefix across three 
levels"),
-//
-//                    new Item("HiddenDemo", "Hidden Demo", "Demo the use of 
the Hidden component."),
-//
-//                    new Item("FormZoneDemo", "Form Zone Demo", "Use a form 
to update a zone."),
-//
-//                    new Item("ZoneUpdateNamespace", "Zone/Namespace 
Interaction", "Prove that TAP5-573 is fixed"),
-//
-//                    new Item("AbstractComponentDemo", "Abstract Component 
Demo", "Error when a component is abstract"),
-//
-//                    new Item("TemplateOverrideDemo", "Template Override 
Demo",
-//                            "Child component extends and overrides parent 
template."),
-//
-//                    new Item("MultiZoneUpdateDemo", "Multiple Zone Update 
Demo",
-//                            "A single request can now update multiple 
Zones"),
-//
-//                    new Item("LinkSubmitInZoneDemo", "LinkSubmit inside 
Zone",
-//                            "Ensure that a LinkSubmit works correctly when 
its containing Form updates a Zone"),
-//
-//                    new Item("ProgressiveDemo", "ProgressiveDisplay Demo", 
"Progressive Enhancement via a component"),
-//
-//                    new Item("ClientNumericValidationDemo", "Client-Side 
Numeric Validation",
-//                            "Client-side locale-specific validation"),
-//
-//                    new Item("PublishParametersDemo", "Publish Parameters 
Demo",
-//                            "Use of @Component.publishParameters 
attribute."),
-//
-//                    new Item("LinkSubmitDemo", "LinkSubmit Demo", 
"JavaScript LinkSubmit component"),
-//
-//                    new Item("LinkSubmitWithoutValidatorDemo", "LinkSubmit 
Without Validator Demo",
-//                            "Demonstrates that the LinkSubmit component is 
working without a validator on any of fields in the form"),
-//
-//                    new Item("PerFormValidationMessageDemo", "Per-Form 
Validation Messages",
-//                            "Per-form configuration of validation messages 
and constraints."),
-//
-//                    new Item("EmptyLoopDemo", "Empty Loop Demo", "Use of 
empty parameter with the Loop component."),
-//
-//                    new Item("GenericLoopDemo", "Generic Loop Demo",
-//                            "Use of generic parameters with the Loop 
component."),
-//
-//                    new Item("LoopWithMixinDemo", "Loop With Mixin Demo",
-//                            "Use a mixin with a Loop component."),
-//
-//                    new Item("BlankPasswordDemo", "Blank Password Demo",
-//                            "Show that a blank value in a PasswordField does 
not update the server side value."),
-//
-//                    new Item("GridFormEncoderDemo", "Grid Form Encoder Demo",
-//                            "Grid inside a Form using the ValueEncoder 
option"),
-//
-//                    new Item("GridFormWithInitialSortMixinDemo", "Grid Form 
With Initial Sort Mixin Demo",
-//                            "Grid inside a Form using the InitialSort 
mixin"),
-//
-//                    new Item("DateFieldAjaxFormLoop", "DateField inside 
AjaxFormLoop",
-//                            "Show that DateField component works correctly 
inside AjaxFormLoop"),
-//
-//                    new Item("NestedForm", "Nested Form Demo", "Error when a 
Form is nested inside another Form."),
-//
-//                    new Item("UnhandledEventDemo", "Unhandled Event Demo",
-//                            "Events that don't have matching event handlers 
cause exceptions"),
-//
-//                    new Item("PrimitiveDefaultDemo", "Primitive Default 
Demo",
-//                            "Primitive value returned from parameter default 
method"),
-//
-//                    new Item("ValidateFormValidationExceptionDemo", 
"ValidationForm ValidationException Demo",
-//                            "Throwing a ValidationException from the 
validateForm event handler."),
-//
-//                    new Item("ClientFormatDemo", "Client Format Validation", 
"Client-side input format validation"),
-//
-//                    new Item("ShortGrid", "Short Grid",
-//                            "Grid where the number of claimed rows is less 
than the number of actual rows"),
-//
-//                    new Item("NullParameterDemo", "Null Parameter Demo", 
"Binding a not-null parameter to null."),
-//
-//                    new Item("nestedbeaneditor", "Nested BeanEditor",
-//                            "BeanEditor as override for property editor in 
BeanEditForm"),
-//
-//                    new Item("actionpage", "Action Page", "tests fixture for 
ActionLink component"),
-//
-//                    new Item("cleancachedemo", "Clean Cache Demo", "cache 
cleared properly during Ajax calls"),
-//
-//                    new Item("numberbeaneditordemo", "Number BeanEditor 
Demo",
-//                            "use of nulls and wrapper types with 
BeanEditor"),
-//
-//                    new Item("forminjectordemo", "FormInjector Demo", 
"extending a form dynamically via Ajax"),
-//
-//                    new Item("music", "Music Page", "demo handling of edge 
cases of page naming"),
-//
-//                    new Item("PersistentDemo", "Persistent Demo", "storing 
and clearing persistent properties"),
-//
-//                    new Item("ActionViaLinkDemo", "Action via Link Demo", 
"tests creating an action link explicitly"),
-//
-//                    new Item("FormFragmentDemo", "Form Fragment Demo", "page 
with dynamic form sections"),
-//
-//                    new Item("BooleanDemo", "Boolean Property Demo",
-//                            "demo boolean properties using both is and get 
prefixes"),
-//
-//                    new Item("DeleteFromGridDemo", "Delete From Grid", "demo 
deleting items form a Grid"),
-//
-//                    new Item("RenderErrorDemo", "Render Error Demo", 
"reporting of errors while rendering"),
-//
-//                    new Item("nested/AssetDemo", "AssetDemo", "declaring an 
image using Assets"),
-//
-//                    new Item("nested/ActionDemo", "Action With Context Demo",
-//                            "using action links with context on page with 
activation context"),
-//
-//                    new Item("blockdemo", "BlockDemo", "use of blocks to 
control rendering"),
-//
-//                    new Item("countdown", "Countdown Page", "defining 
component using @Component annotation"),
-//
-//                    new Item("injectdemo", "Inject Demo", "use of various 
kinds of injection"),
-//
-//                    new Item("instancemixin", "InstanceMixin", "mixin added 
to a particular component instance"),
-//
-//                    new Item("TextFieldWrapperTypeDemo", "TextField Wrapper 
Types",
-//                            "use of TextField to edit numeric wrapper types 
(not primitives) "),
-//
-//                    new Item("EnvironmentalDemo", "Environmental Annotation 
Usage",
-//                            "Storing and retrieving Environmental values"),
-//
-//                    new Item("Expansion", "Expansion Page", "Use of 
expansions in templates"),
-//
-//                    new Item("ExpansionSubclass", "ExpansionSubclass",
-//                            "components can inherit templates from base 
classes"),
-//
-//                    new Item("Localization", "Localization", "access 
localized messages from the component catalog"),
-//
-//                    new Item("NumberSelect", "NumberSelect", 
"passivate/activate page context demo"),
-//
-//                    new Item("ParameterConflict", "Template Overridden by 
Class Page",
-//                            "Parameters in the class override those in the 
template"),
-//
-//                    new Item("ParameterDefault", "ParameterDefault", 
"defaulter methods for component parameters"),
-//
-//                    new Item("passwordfielddemo", "PasswordFieldDemo", "test 
for the PasswordField component"),
-//
-//                    new Item("rendercomponentdemo", "RenderComponentDemo",
-//                            "components that \"nominate\" other components 
to render"),
-//
-//                    new Item("renderphaseorder", "RenderPhaseOrder",
-//                            "order of operations when invoking render phase 
methods"),
-//
-//                    new Item("simpleform", "SimpleForm", "first pass at 
writing Form and TextField components"),
-//
-//                    new Item("OptionGroupForm", "OptionGroupForm Demo", 
"Select with Option Group"),
-//
-//                    new Item("validform", "ValidForm", "server-side input 
validation"),
-//
-//                    new Item("ToDoListVolatile", "ToDo List (Volatile)", 
"Loops and Submit inside Form, volatile mode"),
-//
-//                    new Item("MissingTemplate", "Missing Template Demo",
-//                            "Demo for what happens when a template is not 
found for a page"),
-//
-//                    new Item("nested/zonedemo", "Zone Demo", "dynamic 
updates within a page"),
-//
-//                    new Item("todolist", "ToDo List", "Loops and Submit 
inside Form using primary key encoder"),
-//
-//                    new Item("flashdemo", "FlashDemo", "demonstrate 'flash' 
persistence"),
-//
-//                    new Item("beaneditordemo", "BeanEditor Demo", 
"demonstrate the BeanEditor mega-component"),
-//
-//                    new Item("pageloadeddemo", "PageLoaded Demo", "shows 
that page lifecycle methods are invoked"),
-//
-//                    new Item("griddemo", "Grid Demo", "default Grid 
component"),
-//
-//                    new Item("GridInLoopDemo", "Grid In Loop Demo", "Grid 
inside loop with different model on each iteration"),
-//
-//                    new Item("nullgrid", "Null Grid", "handling of null 
source for Grid"),
-//
-//                    new Item("gridsetdemo", "Grid Set Demo", "handling of 
Set sources for Grid"),
-//
-//                    new Item("gridenumdemo", "Grid Enum Demo", "handling of 
enum types in the Grid"),
-//
-//                    new Item("GridRemoveReorderDemo", "Grid Remove/Reorder 
Demo",
-//                            "handling of remove and reorder parameters"),
-//
-//                    new Item("EmptyGrid", "Empty Grid Demo", "show table for 
empty data sources"),
-//                    
-//                    new Item("GridEarlyPagingDemo", "Grid Early Paging", 
"set a Grid's current page before rendering"),
-//
-//                    new Item("protected", "Protected Page",
-//                            "Demonstrate result of non-void return from a 
page's activate method"),
-//
-//                    new Item("Kicker", "Kicker", "demos complex page and 
component context in links"),
-//
-//                    new Item("simpletrackgriddemo", "SimpleTrack Grid Demo",
-//                            "customizing the model for a Grid around an 
interface"),
-//
-//                    new Item("pagelinkcontext", "PageLink Context Demo",
-//                            "passing explicit context in a page render 
link"),
-//
-//                    new Item("pagecontextinform", "Page Context in Form", 
"passivate/activate page context in Form",
-//                            "betty", "wilma", "context with spaces", 
"context/with/slashes"),
-//
-//                    new Item("ValidBeanEditorDemo", "Client Validation 
Demo", "BeanEditor with validation enabled"),
-//
-//                    new Item("Unreachable", "Unreachable Page", "page not 
reachable due to IgnoredPathsFilter"),
-//
-//                    new Item("renderabledemo", "Renderable Demo",
-//                            "shows that render phase methods can return a 
Renderable"),
-//
-//                    new Item("inheritedbindingsdemo", "Inherited Bindings 
Demo",
-//                            "Tests for components that inherit bindings from 
containing components"),
-//
-//                    new Item("ClientPersistenceDemo", "Client Persistence 
Demo",
-//                            "component field values persisted on the client 
side"),
-//
-//                    new Item("attributeExpansionsDemo", "Attribute 
Expansions Demo",
-//                            "use expansions inside attributes of ordinary 
elements"),
-//
-//                    new Item("PaletteDemo", "Palette Demo", "multiple 
selection component"),
-//                    new Item("PaletteGroupedDemo", "Palette Grouped Demo", 
"multiple selection component (grouped)"),
-//
-//                    new Item("ReturnTypes", "Return Types", "tests various 
event handler return types"),
-//
-//                    new Item("FormEncodingType", "Form Encoding Type",
-//                            "Test ability to set an encoding type for a 
Form"),
-//
-//                    new Item("RadioDemo", "RadioDemo", "Use of the 
RadioGroup and Radio components"),
-//
-//                    new Item("RegexpDemo", "Regexp Demo", "Use of the Regexp 
validator"),
-//
-//                    new Item("BeanEditRemoveReorder", "BeanEdit 
Remove/Reorder",
-//                            "Use of the remove and reorder parameters with 
BeanEditForm"),
-//
-//                    new Item("MultiBeanEditDemo", "MultiBeanEdit Demo",
-//                            "Multiple BeanEditor components in a single 
form"),
-//
-//                    new Item("GridFormDemo", "Grid Form Demo", "Grid 
operating inside a Form"),
-//
-//                    new Item("DateFieldDemo", "DateField Demo", "using 
DateField by itself on a page"),
-//
-//                    new Item("BeanEditDateDemo", "BeanEditor / Date Demo",
-//                            "Use of date properties inside BeanEditor and 
BeanDisplay"),
-//
-//                    new Item("eventmethodtranslate", "EventMethod 
Translator",
-//                            "Demo ability to provide toclient and 
parseclient event handler methods"),
-//
-//                    new Item("autocompletedemo", "Autocomplete Mixin Demo",
-//                            "Demo the autocomplete mixin for text fields"),
-//
-//                    new Item("componentparameter", "ComponentParameter Demo",
-//                            " Demo using a component type as a parameter 
type and succesfully passing a component"),
-//
-//                    new Item("inheritinformalsdemo", "Inherit Informal 
Parameters Demo",
-//                            "Demo a component which inherits informal 
parameters from its container"),
-//
-//                    new Item("disabledfields", "Disabled Fields",
-//                            "Demonstrate a bunch of disabled fields, to 
verify that the RenderDisabled mixin works and is being used properly"),
-//
-//                    new Item("BeanEditorOverride", "BeanEditor Override",
-//                            "Property editor overrides work for the 
BeanEditor component itself (not just the BeanEditForm component)"),
-//
-//                    new Item("varbindingdemo", "Var Binding Demo", "use of 
the var: binding prefix"),
-//
-//                    new Item("leangriddemo", "Lean Grid Demo",
-//                            "Grid component with lean parameter turned on, 
to eliminate CSS class attributes in TD and TH elements"),
-//
-//                    new Item("blockcaller", "Action Links off of Active 
Page",
-//                            "Actions can exist on pages other than the 
active page, via Blocks."),
-//
-//                    new Item("unlessdemo", "Unless Demo", "use of the Unless 
component"),
-//
-//                    new Item("delegateinline", "Inline Delegate",
-//                            "Using the delegate component to create inline 
components"),
-//
-//                    new Item("MagicValueEncoder", "Magic ValueEncoder Demo",
-//                            "Automatic creation of ValueEncoder using the 
TypeCoercer"),
-//
-//                    new Item("NullStrategyDemo", "Null Field Strategy Demo", 
"use of the nulls parameter of TextField"),
-//
-//                    new Item("OverrideValidationDecorator", "Override 
Validation Decorator",
-//                            "override the default validation decorator"),
-//
-//                    new Item("ExceptionEventDemo", "Exception Event Demo", 
"handling component event exceptions"),
-//
-//                    new Item("AddedGridColumnsDemo", "Added Grid Columns 
Demo", "programatically adding grid columns"),
-//
-//                    new Item("PrimitiveArrayParameterDemo", "Primitive Array 
Parameter Demo",
-//                            "use primitive array as parameter type"),
-//
-//                    new Item("RenderPhaseMethodExceptionDemo", "Render Phase 
Method Exception Demo",
-//                            "render phase methods may throw checked 
exceptions"),
-//
-//                    new Item("TrackEditor", "Generic Page Class Demo",
-//                            "demo use of generics with component classes 
and, particularily, with property types"),
-//
-//                    new Item("IndirectProtectedFields", "Protected Fields 
Demo",
-//                            "demo exception when component class contains 
protected fields"),
-//
-//                    new Item("injectcomponentdemo", "Inject Component Demo", 
"inject component defined in template"),
-//
-//                    new Item("cachedpage", "Cached Annotation", "Caching 
method return values"),
-//
-//                    new Item("cachedpage2", "Cached Annotation2", "Caching 
method return values w/ inheritence"),
-//
-//                    new Item("inplacegriddemo", "In-Place Grid Demo", "Grid 
that updates in-place using Ajax"),
-//
-//                    new Item("methodadvicedemo", "Method Advice Demo", 
"Advising component methods."),
-//
-//                    new Item("HasBodyDemo", "Has Body Demo", "Verify the 
hasBody() method of ComponentResources"),
-//
-//                    new Item("BeanEditorBeanEditContext", "BeanEditor 
BeanEditContext",
-//                            "BeanEditContext is pushed into enviroment by 
BeanEditor."),
-//
-//                    new Item("InformalParametersDemo", "Informal Parameters 
Demo",
-//                            "Access to informal parameters names and 
values"),
-//
-//                    new Item("FormFieldOutsideForm", "Form Field Outside 
Form",
-//                            "Nice exception message for common problem of 
form fields outside forms"),
-//
-//                    new Item("SubmitWithContext", "Submit With Context", 
"Providing a context for Submit component"),
-//
-//                    new Item("MessageConstraintGeneratorDemo", "Validation 
Constraints From Messages",
-//                            "Providing validators to apply from a properties 
file"),
-//
-//                    new Item("RenderClientIdDemo", "RenderClientId Mixin",
-//                            "Force render of client-side id of a client 
element via the RenderClientId mixin"),
-//
-//                    new Item("BindParameterDemo", "BindParameter mixin 
annotation",
-//                            "Accessing component parameter values from a 
mixin"),
-//
-//                    new Item("BindParameterNoSuchParameter", "BindParameter 
error handling",
-//                            "BindParameter throws exception if the 
containing component doesn't have a matching parameter"),
-//
-//                    new Item("BindParameterOnComponent", "BindParameter on 
component",
-//                            "Verify that BindParameter can only be used on 
mixin fields"),
-//
-//                    new Item("MixinOrderingDemo", "Mixin Ordering Demo", 
"Various mixin-ordering scenarios"),
-//
-//                    new Item(
-//                            "MissingComponentClassException",
-//                            "Missing Component Class Exception",
-//                            "Meaningful exception message thrown when 
component class can't be determined from template or field in containing 
component."),
-//
-//                    new Item("SessionAttributeDemo", "SessionAttribute Demo",
-//                            "Annotation to map a field to a specific session 
attribute"),
-//
-//                    new Item("BeanEditCalendarDemo", "BeanEditor / Calendar 
Demo",
-//                            "Use of calendar properties inside BeanEditor 
and BeanDisplay"),
-//
-//                    new Item("TriggerDemo", "Trigger Demo", "Use of Trigger 
component"),
-//
-//                    new Item("ImageSubmitDemo", "Submit with an Image Demo",
-//                            "Make sure that submit with the image parameter 
set triggers the 'selected' event."),
-//
-//                    new Item("SelectZoneDemo", "Select Zone Demo", "Use a 
Select component to update a zone."),
-//
-//                    new Item("AssetProtectionDemo", "Asset Protection Demo",
-//                            "AssetProtectionDispatcher is properly 
contributed and functioning"),
-//
-//                    new Item("BeanDisplayEnumDemo", "BeanDisplay Enum Demo",
-//                            "User represenation of enum values is correctly 
read from messages"),
-//
-//                    new Item("unavailablecomponentdemo", "Report Location of 
Unavailable Component",
-//                            "Report Location of Unavailable Component"),
-//
-//                    new Item("discardafterdemo", "@DiscardAfter Demo", "Demo 
using @DiscardAfter annotation"),
-//
-//                    new Item("SelectDemo", "Select Demo", "Validation 
decoration for Select"),
-//
-//                    new Item("SelectModelFromObjectsAndPropertyNameDemo", 
"SelectModel from objects and property name",
-//                            "Creating a SelectModel from a list of objects 
and a label property name"),
-//
-//                    new Item("SelectModelFromObjectsDemo", "SelectModel from 
objects",
-//                            "Creating a SelectModel from a list of objects"),
-//
-//                    new Item("SelectModelCoercionDemo", "SelectModel 
coercion",
-//                            "Creating a SelectModel from a list of objects 
using coercion"),
-//
-//                    new Item("DecoratePageRenderLinkDemo", "Decorate Page 
Render Link Demo",
-//                            "Decorating page render links"),
-//
-//                    new Item("DecorateComponentEventLinkDemo", "Decorate 
Component Event Link Demo",
-//                            "Decorating event links"),
-//
-//                    new Item("ValidatorMacroDemo", "Validator Macro Demo", 
"Using validator macros"),
-//
-//                    new Item("AtInjectDemo", "@jakarta.inject.Inject Demo", 
"Using @jakarta.inject.Inject for injection"),
-//
-//                    new Item("LinkQueryParameters", "Link Query Parameters 
Demo",
-//                            "Providing Query Parameters directly to link 
components as a map of key=parameter name, value=parameter values"),
-//
-//                    new Item("ChecklistDemo", "Checklist Demo", "Use 
Checklist component"),
-//
-//                    new Item("BeanEditFormPrepareBubbling", "BeanEditor 
Prepare Bubbling Demo", "Prepare event bubbling"),
-//
-//                    new Item("NestedFormFragment", "Nested Form Fragment 
Demo", "Nesting Form Fragments work properly"),
-//
-//                    new Item("MapExpressionInExpansions", "Map Expressions 
in Expansions Demo", "Maps can be used in expansions"),
-//
-//                    new Item("ExpressionInJsFunction", "Expressions in JS 
Functions Demo", "Expressions can be used inside javascript functions"),
-//
-//                    new Item("FormFieldFocusDemo", "FormFieldFocus 
(DEPRECATED) Demo", "Setting the Form focus on a specific field"),
-//
-//                    new Item("FormFragmentExplicitVisibleBoundsDemo", "Form 
Fragment Explicit Visible Bounds Demo", "Check for form fragment parent 
visibility can be bounded to"),
-//
-//                    new Item("OverrideFieldFocusDemo", "OverrideFieldFocus 
Demo", "Setting the focus in a form to a specific field"),
-//
-//                    new Item("OverrideLabelClassDemo", "Override Label Class 
Demo", "Setting class attribute on Label component"),
-//
-//                    new Item("FormLinkParameters", "FormLinkParameters 
Demo", "Form link parameters should be unescaped for a hidden field"),
-//
-//                    new Item("KnownActivationContextDemo", "Known Activation 
Context Demo", "Page is displayed normally if called without context 
(TAP5-2070)",
-//                            "Exact"),
-//
-//                    new Item("UnknownActivationContextDemo", "Unknown 
Activation Context Demo", "Page refuse to serve if called with an unknown 
activation context (TAP5-2070)",
-//                            "Unwanted", "context"),
-//
-//                    new Item("ModuleConfigurationCallbackDemo", 
"ModuleConfigurationCallback Demo", "Shows an example of changing the 
Require.js configuration using JavaScriptSupport.addModuleConfigurationDemo()"),
-//
-//                    new Item("PartialTemplateRendererDemo", 
"PartialTemplateRenderer Demo", "Shows some examples of rendering blocks and 
components to a String using PartialTemplateRenderer"),
-//
-//                    new Item("nested/PageThatThrowsException", "Reload on 
nested page", "Tests a page reload from a nested page's exception report"),
-//
-//                    new Item("inplacegridinloopdemo", "In-Place Grid in a 
Loop Demo", "In-place grid in a loop"),
-//
-//                    new Item("GenericTypeDemo", "Generic bound type demo", 
"Tests that generic type info is available for generic bindings"),
-//
-//                    new Item("FormFieldClientIdParameterDemo", "Form Field 
clientId Parameter Demo", "Shows and tests how to explicitly set the id of a 
form field component"),
-//
-//                    new Item("gridwithsubmitwithcontextdemo", "Grid with 
Submit with context", "A grid whose rows contain a Submit component with 
context"),
-//
-//                    new Item("textfieldwithnullvalidateparameter", 
"TextField with null validate parameter", "A TextField whose validate parameter 
is bound to null"),
-//
-//                    new Item("validateCheckboxMustBeChecked", "Validate 
Checkbox Must Be Checked", "A form that trigger validate in " +
-//                            "error event on submit when checkbox is not 
checked"),
-//
-//                    new Item("validateCheckboxMustBeUnchecked", "Validate 
Checkbox Must Be Unchecked", "A form that trigger validate in " +
-//                             "error event on submit when checkbox is 
checked"),
-//                    
-//                    new Item("validateInErrorEvent", "Validate in error 
Event", "A form that trigger validate in " +
-//                            "error event on submit when textfield is empty"),
-//
-//                    new Item("onactivateredirect", "OnActivateRedirect 
Demo", "A page that redirects to itself from"
-//                        + " its activation method"),
-//
-//                    new Item("BeanEditorWithFormFragmentDemo", "Bean Editor 
With Form Fragment Demo", "TriggerFragment mixin used inside a BeanEditor"),
-//
-//                    new Item("ObjectEditorDemo","Object Editor Demo","Edit 
Bean with address objects"),
-//                    
-//                    new Item("IfDemo","If Demo","If component with all its 
options"),
-//                    
-//                    new Item("RecursiveDemo","Recursive Demo","Recursive 
component example"),
-//                    
-//                    new Item("SelfRecursiveDemo", "Self-Recursive Demo", 
"check for handling of self-recursive components"),
-//                    
-//                    new Item("EsModuleDemo", "ES Module Demo", "tests and 
demonstrations for the ES module support")
+                    new Item("PublishEventDemo", "@PublishEvent Demo", 
"Publishing server-side events to client-side code (JavaScript)"),
+
+                    new Item("StaticActivationContextValueDemo", 
"@StaticActivationContextValue Demo", "Demonstrates the usage of 
@StaticActivationContextValue"),
+                    
+                    new Item("rest/RestWithOnEventDemo", "REST with @OnEvent 
Demo", "Demonstrates the usage of @OnEvent to handle REST requests"),           
         
+                    
+                    new Item("rest/RestWithEventHandlerMethodNameDemo", "REST 
with Event Handler Method Name Demo", "Demonstrates the usage of event handler 
method names to handle REST requests"),
+
+                    new Item("Html5DateFieldDemo", "Html5DateField Demo", 
"Choosing dates using the native HTML5 date picker"),
+
+//                    new Item("ZoneFormDemo", "Zone Form Decoration", "Fields 
inside an Ajax-updatd Form are still decorated properly."),
+
+                    new Item("AjaxValidationDemo", "Ajax Validation", 
"Demonstrated proper integration of server-side validation and client-side 
field decoration."),
+
+                    new Item("OverrideEventHandlerDemo", "Event Handler 
Override Demo", "Event Handler methods overridden by sub-classes invoke 
base-class correctly."),
+
+                    new Item("LogoSubclass", "Base class Assets in 
sub-classes", "Assets are resolved for the parent class if that's where the 
annotations are."),
+
+                    new Item("MissingRequiredARP", "Missing Query Parameter 
for @ActivationRequestParameter", "Activating a page with a required 
@ActivationRequestParameter, but no matching query parameter, is an error."),
+
+//                    new Item("DateFieldValidationDemo", "DateField 
Validation Demo",
+//                            "Use of DateField component when client 
validation is disabled."),
+
+                    new Item("MixinParameters54", "Strict Mixin Parameters", 
"In the 5.4 DTD, Parameter Mixins must be qualified with the mixin id."),
+
+                    new Item("AsyncDemo", "Async Links and Forms Demo", "Async 
(XHR) Updates without a containing Zone."),
+
+                    new Item("FormCancelActionDemo", "Form Cancel Action 
Demo", "FormSupport.addCancel() support"),
+
+                    new Item("AjaxRadioDemo", "Ajax Radio Demo", "Radio 
components inside an Ajax form"),
+
+                    new Item("TimeIntervalDemo", "TimeInterval Demo", 
"Interval component, based on Moment.js"),
+
+                    new Item("LocalDateDemo", "LocalDate Demo", "LocalDate 
component, based on Moment.js"),
+
+                    new Item("EmptyIfDemo", "Empty If Demo", "Ensure an empty 
If can still render."),
+
+                    new Item("MissingAssetDemo", "Missing Asset Demo", "Error 
when injecting an asset that does not exist."),
+
+                    new Item("ConfirmDemo", "Confirm Mixin Demo", "Confirm an 
action when clicking it."),
+
+                    new Item("SingleErrorDemo", "Single Error", "Using Error 
component to customize where the errors for a field will be displayed."),
+
+                    new Item("JavaScriptTests", "JavaScript Tests", 
"Client-side tests using Mocha and Chai"),
+
+                    new Item("ModuleInitDemo", "Module-based Initialization 
Demo", "Invoke a module function to perform page initialization"),
+
+                    new Item("OperationWorkerDemo", "Operation Worker Demo", 
"Demonstrate use of @Operation annotation on component methods"),
+
+                    new Item("MixinParameterDefault", "Mixin Parameter with 
Default", "Ensure that a mixin parameter with a default value is not reported 
as unbound."),
+
+                    new Item("MixinVsInformalParameter", "Mixin Parameter vs. 
Informal Parameter", "Informal Paramters vs. Mixin parameter of same name"),
+
+                    new Item("inherit/childa", "TAP5-1656 Demo", "Test a 
reported bug in component inheritance"),
+
+                    new Item("ComponentInsideBlockDemo", "Component Inside 
Block Demo", "Verify that a component, inside a block, is still an embedded "),
+
+                    new Item("EventMethodUnmatchedComponentId", "Unmatched 
Component Id in Event Method Demo", "Show that referencing a component that 
does not exist in an event handler method name is an error."),
+
+                    new Item("AlertsDemo", "Alerts Demo", "Managing alerts 
both traditional and Ajax"),
+
+                    new Item("ClientConsoleDemo", "Client Console Demo", "Demo 
for the JavaScript client-side console"),
+
+                    new Item("InvalidFormalParameterDemo", "Unmatched Formal 
Parameter with @Component", "Parameters specified with @Component annotation 
must match formal parameters"),
+
+                    new Item("NullBindingToPrimitive", "Null Bound to 
Primitive Demo", "Correct exception when a primitive parameter is bound to 
null"),
+
+                    new Item("TreeDemo", "Tree Component Demo", "Demo of Tree 
Component"),
+
+                    new Item("TreeSelectionDemo", "Tree Component Selection 
Demo", "Demo of Selection with Tree Component"),
+
+                    new Item("TreeNoRootsDemo", "Tree Component No Roots 
Demo", "Demo of No Roots with Tree Component"),
+
+                    new Item("InvalidExpressionInDynamicTemplate", "Invalid 
Dynamic Expression",
+                            "Invalid expression in a Dynamic Template"),
+
+                    new Item("DynamicDemo", "Dynamic Demo", "Basic Dynamic 
component tests"),
+
+                    new Item("DynamicExpansionsDemo", "Expansions in Dynamic 
Templates",
+                            "Expansions inside Dynamic component content and 
attributes"),
+
+                    new Item("PACAnnotationDemo", "PageActivationContext Demo",
+                            "Shows that @PageActivationContext fields are set 
before calls to the activate event handler."),
+
+                    new Item("PACMultipleAnnotationDemo", 
"PageActivationContext Multiple Demo",
+                            "Demonstrates multiple @PageActivationContext 
fields."),
+
+                    new Item("PublicFieldAccessDemo", "Public Field Access 
Demo", "Demonstrates TAP5-1222 fix"),
+
+                    new Item("ActivationRequestParameterDemo", 
"ActivationRequestParameter Annotation Demo",
+                            "Use of @ActivationRequestParameter to encode page 
state into query parameters"),
+
+                    new Item("LibraryMessagesDemo", "Library Messages Demo",
+                            "Demo ability to contribute additional message 
catalog resources to the application global catalog."),
+
+                    new Item("MultiZoneUpdateInsideForm", "MultiZone Update 
inside a Form",
+                            "Update multiple zones within a single Form."),
+
+                    new Item("ZoneFormUpdateDemo", "Zone/Form Update Demo", 
"Updating a Zone inside a Form"),
+
+                    new Item("MultiZoneStringBodyDemo", "MultiZone String Body 
Demo",
+                            "Multi-zone updates in a loop using strings 
coerced into blocks"),
+
+                    new Item("RenderNotificationDemo", "RenderNotification 
Demo", "Use of RenderNotification mixin"),
+
+                    new Item("InjectMessagesDemo", "Inject Global Messages 
into Service Demo",
+                            "Ensure that it is possible to inject the 
application global message catalog into a service"),
+
+                    new Item("ReloadDemo", "Reloadable Service Implementation 
Demo",
+                            "Used when manually testing service reloads"),
+
+                    new Item("RequestParameterDemo", "RequestParameter 
Annotation Demo",
+                            "Use of @RequestParameter annotation on event 
handler method parameters"),
+
+                    new Item("CancelDemo", "Cancel Demo", "Use of the cancel 
option with Submit"),
+
+                    new Item("CanceledEventDemo", "Canceled Event Demo", 
"Triggering of the canceled event from a form."),
+
+                    new Item("PageResetDemo", "PageReset Annotation Demo",
+                            "Use of PageReset annotation to re-initialize page 
state"),
+
+                    new Item("TestOnlyServiceDemo", "Test Only Service Demo",
+                            "IoC module available via web.xml configuration"),
+
+                    new Item("RenderObjectExceptionDemo", "RenderObject 
Exception Demo",
+                            "Demonstrate how exceptions when rendering default 
objects are displayed."),
+
+                    new Item("MultiLevelInheritDemo", "Multi-Level Inherit 
Demo",
+                            "Use of inherit: binding prefix across three 
levels"),
+
+                    new Item("HiddenDemo", "Hidden Demo", "Demo the use of the 
Hidden component."),
+
+                    new Item("FormZoneDemo", "Form Zone Demo", "Use a form to 
update a zone."),
+
+                    new Item("ZoneUpdateNamespace", "Zone/Namespace 
Interaction", "Prove that TAP5-573 is fixed"),
+
+                    new Item("AbstractComponentDemo", "Abstract Component 
Demo", "Error when a component is abstract"),
+
+                    new Item("TemplateOverrideDemo", "Template Override Demo",
+                            "Child component extends and overrides parent 
template."),
+
+                    new Item("MultiZoneUpdateDemo", "Multiple Zone Update 
Demo",
+                            "A single request can now update multiple Zones"),
+
+                    new Item("LinkSubmitInZoneDemo", "LinkSubmit inside Zone",
+                            "Ensure that a LinkSubmit works correctly when its 
containing Form updates a Zone"),
+
+                    new Item("ProgressiveDemo", "ProgressiveDisplay Demo", 
"Progressive Enhancement via a component"),
+
+                    new Item("ClientNumericValidationDemo", "Client-Side 
Numeric Validation",
+                            "Client-side locale-specific validation"),
+
+                    new Item("PublishParametersDemo", "Publish Parameters 
Demo",
+                            "Use of @Component.publishParameters attribute."),
+
+                    new Item("LinkSubmitDemo", "LinkSubmit Demo", "JavaScript 
LinkSubmit component"),
+
+                    new Item("LinkSubmitWithoutValidatorDemo", "LinkSubmit 
Without Validator Demo",
+                            "Demonstrates that the LinkSubmit component is 
working without a validator on any of fields in the form"),
+
+                    new Item("PerFormValidationMessageDemo", "Per-Form 
Validation Messages",
+                            "Per-form configuration of validation messages and 
constraints."),
+
+                    new Item("EmptyLoopDemo", "Empty Loop Demo", "Use of empty 
parameter with the Loop component."),
+
+                    new Item("GenericLoopDemo", "Generic Loop Demo",
+                            "Use of generic parameters with the Loop 
component."),
+
+                    new Item("LoopWithMixinDemo", "Loop With Mixin Demo",
+                            "Use a mixin with a Loop component."),
+
+                    new Item("BlankPasswordDemo", "Blank Password Demo",
+                            "Show that a blank value in a PasswordField does 
not update the server side value."),
+
+                    new Item("GridFormEncoderDemo", "Grid Form Encoder Demo",
+                            "Grid inside a Form using the ValueEncoder 
option"),
+
+                    new Item("GridFormWithInitialSortMixinDemo", "Grid Form 
With Initial Sort Mixin Demo",
+                            "Grid inside a Form using the InitialSort mixin"),
+
+                    new Item("DateFieldAjaxFormLoop", "DateField inside 
AjaxFormLoop",
+                            "Show that DateField component works correctly 
inside AjaxFormLoop"),
+
+                    new Item("NestedForm", "Nested Form Demo", "Error when a 
Form is nested inside another Form."),
+
+                    new Item("UnhandledEventDemo", "Unhandled Event Demo",
+                            "Events that don't have matching event handlers 
cause exceptions"),
+
+                    new Item("PrimitiveDefaultDemo", "Primitive Default Demo",
+                            "Primitive value returned from parameter default 
method"),
+
+                    new Item("ValidateFormValidationExceptionDemo", 
"ValidationForm ValidationException Demo",
+                            "Throwing a ValidationException from the 
validateForm event handler."),
+
+                    new Item("ClientFormatDemo", "Client Format Validation", 
"Client-side input format validation"),
+
+                    new Item("ShortGrid", "Short Grid",
+                            "Grid where the number of claimed rows is less 
than the number of actual rows"),
+
+                    new Item("NullParameterDemo", "Null Parameter Demo", 
"Binding a not-null parameter to null."),
+
+                    new Item("nestedbeaneditor", "Nested BeanEditor",
+                            "BeanEditor as override for property editor in 
BeanEditForm"),
+
+                    new Item("actionpage", "Action Page", "tests fixture for 
ActionLink component"),
+
+                    new Item("cleancachedemo", "Clean Cache Demo", "cache 
cleared properly during Ajax calls"),
+
+                    new Item("numberbeaneditordemo", "Number BeanEditor Demo",
+                            "use of nulls and wrapper types with BeanEditor"),
+
+                    new Item("forminjectordemo", "FormInjector Demo", 
"extending a form dynamically via Ajax"),
+
+                    new Item("music", "Music Page", "demo handling of edge 
cases of page naming"),
+
+                    new Item("PersistentDemo", "Persistent Demo", "storing and 
clearing persistent properties"),
+
+                    new Item("ActionViaLinkDemo", "Action via Link Demo", 
"tests creating an action link explicitly"),
+
+                    new Item("FormFragmentDemo", "Form Fragment Demo", "page 
with dynamic form sections"),
+
+                    new Item("BooleanDemo", "Boolean Property Demo",
+                            "demo boolean properties using both is and get 
prefixes"),
+
+                    new Item("DeleteFromGridDemo", "Delete From Grid", "demo 
deleting items form a Grid"),
+
+                    new Item("RenderErrorDemo", "Render Error Demo", 
"reporting of errors while rendering"),
+
+                    new Item("nested/AssetDemo", "AssetDemo", "declaring an 
image using Assets"),
+
+                    new Item("nested/ActionDemo", "Action With Context Demo",
+                            "using action links with context on page with 
activation context"),
+
+                    new Item("blockdemo", "BlockDemo", "use of blocks to 
control rendering"),
+
+                    new Item("countdown", "Countdown Page", "defining 
component using @Component annotation"),
+
+                    new Item("injectdemo", "Inject Demo", "use of various 
kinds of injection"),
+
+                    new Item("instancemixin", "InstanceMixin", "mixin added to 
a particular component instance"),
+
+                    new Item("TextFieldWrapperTypeDemo", "TextField Wrapper 
Types",
+                            "use of TextField to edit numeric wrapper types 
(not primitives) "),
+
+                    new Item("EnvironmentalDemo", "Environmental Annotation 
Usage",
+                            "Storing and retrieving Environmental values"),
+
+                    new Item("Expansion", "Expansion Page", "Use of expansions 
in templates"),
+
+                    new Item("ExpansionSubclass", "ExpansionSubclass",
+                            "components can inherit templates from base 
classes"),
+
+                    new Item("Localization", "Localization", "access localized 
messages from the component catalog"),
+
+                    new Item("NumberSelect", "NumberSelect", 
"passivate/activate page context demo"),
+
+                    new Item("ParameterConflict", "Template Overridden by 
Class Page",
+                            "Parameters in the class override those in the 
template"),
+
+                    new Item("ParameterDefault", "ParameterDefault", 
"defaulter methods for component parameters"),
+
+                    new Item("passwordfielddemo", "PasswordFieldDemo", "test 
for the PasswordField component"),
+
+                    new Item("rendercomponentdemo", "RenderComponentDemo",
+                            "components that \"nominate\" other components to 
render"),
+
+                    new Item("renderphaseorder", "RenderPhaseOrder",
+                            "order of operations when invoking render phase 
methods"),
+
+                    new Item("simpleform", "SimpleForm", "first pass at 
writing Form and TextField components"),
+
+                    new Item("OptionGroupForm", "OptionGroupForm Demo", 
"Select with Option Group"),
+
+                    new Item("validform", "ValidForm", "server-side input 
validation"),
+
+                    new Item("ToDoListVolatile", "ToDo List (Volatile)", 
"Loops and Submit inside Form, volatile mode"),
+
+                    new Item("MissingTemplate", "Missing Template Demo",
+                            "Demo for what happens when a template is not 
found for a page"),
+
+                    new Item("nested/zonedemo", "Zone Demo", "dynamic updates 
within a page"),
+
+                    new Item("todolist", "ToDo List", "Loops and Submit inside 
Form using primary key encoder"),
+
+                    new Item("flashdemo", "FlashDemo", "demonstrate 'flash' 
persistence"),
+
+                    new Item("beaneditordemo", "BeanEditor Demo", "demonstrate 
the BeanEditor mega-component"),
+
+                    new Item("pageloadeddemo", "PageLoaded Demo", "shows that 
page lifecycle methods are invoked"),
+
+                    new Item("griddemo", "Grid Demo", "default Grid 
component"),
+
+                    new Item("GridInLoopDemo", "Grid In Loop Demo", "Grid 
inside loop with different model on each iteration"),
+
+                    new Item("nullgrid", "Null Grid", "handling of null source 
for Grid"),
+
+                    new Item("gridsetdemo", "Grid Set Demo", "handling of Set 
sources for Grid"),
+
+                    new Item("gridenumdemo", "Grid Enum Demo", "handling of 
enum types in the Grid"),
+
+                    new Item("GridRemoveReorderDemo", "Grid Remove/Reorder 
Demo",
+                            "handling of remove and reorder parameters"),
+
+                    new Item("EmptyGrid", "Empty Grid Demo", "show table for 
empty data sources"),
+                    
+                    new Item("GridEarlyPagingDemo", "Grid Early Paging", "set 
a Grid's current page before rendering"),
+
+                    new Item("protected", "Protected Page",
+                            "Demonstrate result of non-void return from a 
page's activate method"),
+
+                    new Item("Kicker", "Kicker", "demos complex page and 
component context in links"),
+
+                    new Item("simpletrackgriddemo", "SimpleTrack Grid Demo",
+                            "customizing the model for a Grid around an 
interface"),
+
+                    new Item("pagelinkcontext", "PageLink Context Demo",
+                            "passing explicit context in a page render link"),
+
+                    new Item("pagecontextinform", "Page Context in Form", 
"passivate/activate page context in Form",
+                            "betty", "wilma", "context with spaces", 
"context/with/slashes"),
+
+                    new Item("ValidBeanEditorDemo", "Client Validation Demo", 
"BeanEditor with validation enabled"),
+
+                    new Item("Unreachable", "Unreachable Page", "page not 
reachable due to IgnoredPathsFilter"),
+
+                    new Item("renderabledemo", "Renderable Demo",
+                            "shows that render phase methods can return a 
Renderable"),
+
+                    new Item("inheritedbindingsdemo", "Inherited Bindings 
Demo",
+                            "Tests for components that inherit bindings from 
containing components"),
+
+                    new Item("ClientPersistenceDemo", "Client Persistence 
Demo",
+                            "component field values persisted on the client 
side"),
+
+                    new Item("attributeExpansionsDemo", "Attribute Expansions 
Demo",
+                            "use expansions inside attributes of ordinary 
elements"),
+
+                    new Item("PaletteDemo", "Palette Demo", "multiple 
selection component"),
+                    new Item("PaletteGroupedDemo", "Palette Grouped Demo", 
"multiple selection component (grouped)"),
+
+                    new Item("ReturnTypes", "Return Types", "tests various 
event handler return types"),
+
+                    new Item("FormEncodingType", "Form Encoding Type",
+                            "Test ability to set an encoding type for a Form"),
+
+                    new Item("RadioDemo", "RadioDemo", "Use of the RadioGroup 
and Radio components"),
+
+                    new Item("RegexpDemo", "Regexp Demo", "Use of the Regexp 
validator"),
+
+                    new Item("BeanEditRemoveReorder", "BeanEdit 
Remove/Reorder",
+                            "Use of the remove and reorder parameters with 
BeanEditForm"),
+
+                    new Item("MultiBeanEditDemo", "MultiBeanEdit Demo",
+                            "Multiple BeanEditor components in a single form"),
+
+                    new Item("GridFormDemo", "Grid Form Demo", "Grid operating 
inside a Form"),
+
+                    new Item("DateFieldDemo", "DateField Demo", "using 
DateField by itself on a page"),
+
+                    new Item("BeanEditDateDemo", "BeanEditor / Date Demo",
+                            "Use of date properties inside BeanEditor and 
BeanDisplay"),
+
+                    new Item("eventmethodtranslate", "EventMethod Translator",
+                            "Demo ability to provide toclient and parseclient 
event handler methods"),
+
+                    new Item("autocompletedemo", "Autocomplete Mixin Demo",
+                            "Demo the autocomplete mixin for text fields"),
+
+                    new Item("componentparameter", "ComponentParameter Demo",
+                            " Demo using a component type as a parameter type 
and succesfully passing a component"),
+
+                    new Item("inheritinformalsdemo", "Inherit Informal 
Parameters Demo",
+                            "Demo a component which inherits informal 
parameters from its container"),
+
+                    new Item("disabledfields", "Disabled Fields",
+                            "Demonstrate a bunch of disabled fields, to verify 
that the RenderDisabled mixin works and is being used properly"),
+
+                    new Item("BeanEditorOverride", "BeanEditor Override",
+                            "Property editor overrides work for the BeanEditor 
component itself (not just the BeanEditForm component)"),
+
+                    new Item("varbindingdemo", "Var Binding Demo", "use of the 
var: binding prefix"),
+
+                    new Item("leangriddemo", "Lean Grid Demo",
+                            "Grid component with lean parameter turned on, to 
eliminate CSS class attributes in TD and TH elements"),
+
+                    new Item("blockcaller", "Action Links off of Active Page",
+                            "Actions can exist on pages other than the active 
page, via Blocks."),
+
+                    new Item("unlessdemo", "Unless Demo", "use of the Unless 
component"),
+
+                    new Item("delegateinline", "Inline Delegate",
+                            "Using the delegate component to create inline 
components"),
+
+                    new Item("MagicValueEncoder", "Magic ValueEncoder Demo",
+                            "Automatic creation of ValueEncoder using the 
TypeCoercer"),
+
+                    new Item("NullStrategyDemo", "Null Field Strategy Demo", 
"use of the nulls parameter of TextField"),
+
+                    new Item("OverrideValidationDecorator", "Override 
Validation Decorator",
+                            "override the default validation decorator"),
+
+                    new Item("ExceptionEventDemo", "Exception Event Demo", 
"handling component event exceptions"),
+
+                    new Item("AddedGridColumnsDemo", "Added Grid Columns 
Demo", "programatically adding grid columns"),
+
+                    new Item("PrimitiveArrayParameterDemo", "Primitive Array 
Parameter Demo",
+                            "use primitive array as parameter type"),
+
+                    new Item("RenderPhaseMethodExceptionDemo", "Render Phase 
Method Exception Demo",
+                            "render phase methods may throw checked 
exceptions"),
+
+                    new Item("TrackEditor", "Generic Page Class Demo",
+                            "demo use of generics with component classes and, 
particularily, with property types"),
+
+                    new Item("IndirectProtectedFields", "Protected Fields 
Demo",
+                            "demo exception when component class contains 
protected fields"),
+
+                    new Item("injectcomponentdemo", "Inject Component Demo", 
"inject component defined in template"),
+
+                    new Item("cachedpage", "Cached Annotation", "Caching 
method return values"),
+
+                    new Item("cachedpage2", "Cached Annotation2", "Caching 
method return values w/ inheritence"),
+
+                    new Item("inplacegriddemo", "In-Place Grid Demo", "Grid 
that updates in-place using Ajax"),
+
+                    new Item("methodadvicedemo", "Method Advice Demo", 
"Advising component methods."),
+
+                    new Item("HasBodyDemo", "Has Body Demo", "Verify the 
hasBody() method of ComponentResources"),
+
+                    new Item("BeanEditorBeanEditContext", "BeanEditor 
BeanEditContext",
+                            "BeanEditContext is pushed into enviroment by 
BeanEditor."),
+
+                    new Item("InformalParametersDemo", "Informal Parameters 
Demo",
+                            "Access to informal parameters names and values"),
+
+                    new Item("FormFieldOutsideForm", "Form Field Outside Form",
+                            "Nice exception message for common problem of form 
fields outside forms"),
+
+                    new Item("SubmitWithContext", "Submit With Context", 
"Providing a context for Submit component"),
+
+                    new Item("MessageConstraintGeneratorDemo", "Validation 
Constraints From Messages",
+                            "Providing validators to apply from a properties 
file"),
+
+                    new Item("RenderClientIdDemo", "RenderClientId Mixin",
+                            "Force render of client-side id of a client 
element via the RenderClientId mixin"),
+
+                    new Item("BindParameterDemo", "BindParameter mixin 
annotation",
+                            "Accessing component parameter values from a 
mixin"),
+
+                    new Item("BindParameterNoSuchParameter", "BindParameter 
error handling",
+                            "BindParameter throws exception if the containing 
component doesn't have a matching parameter"),
+
+                    new Item("BindParameterOnComponent", "BindParameter on 
component",
+                            "Verify that BindParameter can only be used on 
mixin fields"),
+
+                    new Item("MixinOrderingDemo", "Mixin Ordering Demo", 
"Various mixin-ordering scenarios"),
+
+                    new Item(
+                            "MissingComponentClassException",
+                            "Missing Component Class Exception",
+                            "Meaningful exception message thrown when 
component class can't be determined from template or field in containing 
component."),
+
+                    new Item("SessionAttributeDemo", "SessionAttribute Demo",
+                            "Annotation to map a field to a specific session 
attribute"),
+
+                    new Item("BeanEditCalendarDemo", "BeanEditor / Calendar 
Demo",
+                            "Use of calendar properties inside BeanEditor and 
BeanDisplay"),
+
+                    new Item("TriggerDemo", "Trigger Demo", "Use of Trigger 
component"),
+
+                    new Item("ImageSubmitDemo", "Submit with an Image Demo",
+                            "Make sure that submit with the image parameter 
set triggers the 'selected' event."),
+
+                    new Item("SelectZoneDemo", "Select Zone Demo", "Use a 
Select component to update a zone."),
+
+                    new Item("AssetProtectionDemo", "Asset Protection Demo",
+                            "AssetProtectionDispatcher is properly contributed 
and functioning"),
+
+                    new Item("BeanDisplayEnumDemo", "BeanDisplay Enum Demo",
+                            "User represenation of enum values is correctly 
read from messages"),
+
+                    new Item("unavailablecomponentdemo", "Report Location of 
Unavailable Component",
+                            "Report Location of Unavailable Component"),
+
+                    new Item("discardafterdemo", "@DiscardAfter Demo", "Demo 
using @DiscardAfter annotation"),
+
+                    new Item("SelectDemo", "Select Demo", "Validation 
decoration for Select"),
+
+                    new Item("SelectModelFromObjectsAndPropertyNameDemo", 
"SelectModel from objects and property name",
+                            "Creating a SelectModel from a list of objects and 
a label property name"),
+
+                    new Item("SelectModelFromObjectsDemo", "SelectModel from 
objects",
+                            "Creating a SelectModel from a list of objects"),
+
+                    new Item("SelectModelCoercionDemo", "SelectModel coercion",
+                            "Creating a SelectModel from a list of objects 
using coercion"),
+
+                    new Item("DecoratePageRenderLinkDemo", "Decorate Page 
Render Link Demo",
+                            "Decorating page render links"),
+
+                    new Item("DecorateComponentEventLinkDemo", "Decorate 
Component Event Link Demo",
+                            "Decorating event links"),
+
+                    new Item("ValidatorMacroDemo", "Validator Macro Demo", 
"Using validator macros"),
+
+                    new Item("AtInjectDemo", "@jakarta.inject.Inject Demo", 
"Using @jakarta.inject.Inject for injection"),
+
+                    new Item("LinkQueryParameters", "Link Query Parameters 
Demo",
+                            "Providing Query Parameters directly to link 
components as a map of key=parameter name, value=parameter values"),
+
+                    new Item("ChecklistDemo", "Checklist Demo", "Use Checklist 
component"),
+
+                    new Item("BeanEditFormPrepareBubbling", "BeanEditor 
Prepare Bubbling Demo", "Prepare event bubbling"),
+
+                    new Item("NestedFormFragment", "Nested Form Fragment 
Demo", "Nesting Form Fragments work properly"),
+
+                    new Item("MapExpressionInExpansions", "Map Expressions in 
Expansions Demo", "Maps can be used in expansions"),
+
+                    new Item("ExpressionInJsFunction", "Expressions in JS 
Functions Demo", "Expressions can be used inside javascript functions"),
+
+                    new Item("FormFieldFocusDemo", "FormFieldFocus 
(DEPRECATED) Demo", "Setting the Form focus on a specific field"),
+
+                    new Item("FormFragmentExplicitVisibleBoundsDemo", "Form 
Fragment Explicit Visible Bounds Demo", "Check for form fragment parent 
visibility can be bounded to"),
+
+                    new Item("OverrideFieldFocusDemo", "OverrideFieldFocus 
Demo", "Setting the focus in a form to a specific field"),
+
+                    new Item("OverrideLabelClassDemo", "Override Label Class 
Demo", "Setting class attribute on Label component"),
+
+                    new Item("FormLinkParameters", "FormLinkParameters Demo", 
"Form link parameters should be unescaped for a hidden field"),
+
+                    new Item("KnownActivationContextDemo", "Known Activation 
Context Demo", "Page is displayed normally if called without context 
(TAP5-2070)",
+                            "Exact"),
+
+                    new Item("UnknownActivationContextDemo", "Unknown 
Activation Context Demo", "Page refuse to serve if called with an unknown 
activation context (TAP5-2070)",
+                            "Unwanted", "context"),
+
+                    new Item("ModuleConfigurationCallbackDemo", 
"ModuleConfigurationCallback Demo", "Shows an example of changing the 
Require.js configuration using JavaScriptSupport.addModuleConfigurationDemo()"),
+
+                    new Item("PartialTemplateRendererDemo", 
"PartialTemplateRenderer Demo", "Shows some examples of rendering blocks and 
components to a String using PartialTemplateRenderer"),
+
+                    new Item("nested/PageThatThrowsException", "Reload on 
nested page", "Tests a page reload from a nested page's exception report"),
+
+                    new Item("inplacegridinloopdemo", "In-Place Grid in a Loop 
Demo", "In-place grid in a loop"),
+
+                    new Item("GenericTypeDemo", "Generic bound type demo", 
"Tests that generic type info is available for generic bindings"),
+
+                    new Item("FormFieldClientIdParameterDemo", "Form Field 
clientId Parameter Demo", "Shows and tests how to explicitly set the id of a 
form field component"),
+
+                    new Item("gridwithsubmitwithcontextdemo", "Grid with 
Submit with context", "A grid whose rows contain a Submit component with 
context"),
+
+                    new Item("textfieldwithnullvalidateparameter", "TextField 
with null validate parameter", "A TextField whose validate parameter is bound 
to null"),
+
+                    new Item("validateCheckboxMustBeChecked", "Validate 
Checkbox Must Be Checked", "A form that trigger validate in " +
+                            "error event on submit when checkbox is not 
checked"),
+
+                    new Item("validateCheckboxMustBeUnchecked", "Validate 
Checkbox Must Be Unchecked", "A form that trigger validate in " +
+                               "error event on submit when checkbox is 
checked"),
+                    
+                    new Item("validateInErrorEvent", "Validate in error 
Event", "A form that trigger validate in " +
+                            "error event on submit when textfield is empty"),
+
+                    new Item("onactivateredirect", "OnActivateRedirect Demo", 
"A page that redirects to itself from"
+                        + " its activation method"),
+
+                    new Item("BeanEditorWithFormFragmentDemo", "Bean Editor 
With Form Fragment Demo", "TriggerFragment mixin used inside a BeanEditor"),
+
+                    new Item("ObjectEditorDemo","Object Editor Demo","Edit 
Bean with address objects"),
+                    
+                    new Item("IfDemo","If Demo","If component with all its 
options"),
+                    
+                    new Item("RecursiveDemo","Recursive Demo","Recursive 
component example"),
+                    
+                    new Item("SelfRecursiveDemo", "Self-Recursive Demo", 
"check for handling of self-recursive components"),
+                    
+                    new Item("EsModuleDemo", "ES Module Demo", "tests and 
demonstrations for the ES module support")
                 );
 
     static
diff --git 
a/tapestry-core/src/test/resources/META-INF/assets/es-modules/app/test-support.js
 
b/tapestry-core/src/test/resources/META-INF/assets/es-modules/app/test-support.js
new file mode 100644
index 000000000..7728ef0c1
--- /dev/null
+++ 
b/tapestry-core/src/test/resources/META-INF/assets/es-modules/app/test-support.js
@@ -0,0 +1,14 @@
+// Provide test support functions that can be addressed via Selenium.
+
+// TODO: Maybe move this to main, for external re-use?
+
+import dom from "t5/core/dom";
+
+const exports = {
+  findCSSMatchCount(selector) { return dom.body.find(selector).length; },
+  doesNotExist(elementId) { return (dom(elementId)) === null; }
+};
+
+window.testSupport = exports;
+
+export default exports;


Reply via email to