Modified: websites/production/tapestry/content/developer-bible.html
==============================================================================
--- websites/production/tapestry/content/developer-bible.html (original)
+++ websites/production/tapestry/content/developer-bible.html Sat Nov 26 
13:17:27 2022
@@ -32,10 +32,10 @@
   <link rel="apple-touch-icon-precomposed" 
href="/images/apache-tapestry-icon-57.png">
   <link rel="shortcut icon" href="/images/apache-tapestry-icon-32.png">
 
-  <link rel="stylesheet" 
href="https://fonts.googleapis.com/css2?family=Sarabun:ital,wght@0,400;0,700;1,400;1,700&display=swap";>
 
-  <link rel="stylesheet" 
href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css"; 
integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh"
 crossorigin="anonymous">
+  <link rel="stylesheet" href="/resources/bootstrap/bootstrap.min.css">
   <link rel="stylesheet" 
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.13.0/css/all.min.css";>
   <link rel="stylesheet" 
href="https://cdnjs.cloudflare.com/ajax/libs/prism/1.20.0/themes/prism.min.css";>
+  <link rel="stylesheet" href="/resources/fonts/fonts.css">
   <link rel="stylesheet" href="/styles/main.css">
 
   <script type="text/javascript">
@@ -46,7 +46,7 @@
 
   <script src="https://code.jquery.com/jquery-3.4.1.slim.min.js"; 
integrity="sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n"
 crossorigin="anonymous" defer></script>
   <script 
src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js"; 
integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo"
 crossorigin="anonymous" defer></script>
-  <script 
src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js"; 
integrity="sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6"
 crossorigin="anonymous" defer></script>
+  <script src="stylesheet" href="/resources/bootstrap/bootstrap.min.js">
   <script 
src="https://cdnjs.cloudflare.com/ajax/libs/prism/1.20.0/prism.min.js"; 
defer></script>
        <script 
src="https://cdnjs.cloudflare.com/ajax/libs/prism/1.20.0/plugins/autoloader/prism-autoloader.min.js";
 defer></script>
 
@@ -160,7 +160,7 @@
                 <span class="icon aui-icon content-type-page" 
title="Page">Page:</span>        </div>
 
         <div class="details">
-                        <a href="release-process.html">Release Process</a>
+                        <a href="developer-bible.html">Developer Bible</a>
                 
                         
                     </div>
@@ -169,7 +169,7 @@
                 <span class="icon aui-icon content-type-page" 
title="Page">Page:</span>        </div>
 
         <div class="details">
-                        <a href="developer-information.html">Developer 
Information</a>
+                        <a href="version-numbers.html">Version Numbers</a>
                 
                         
                     </div>
@@ -178,7 +178,7 @@
                 <span class="icon aui-icon content-type-page" 
title="Page">Page:</span>        </div>
 
         <div class="details">
-                        <a href="building-tapestry-from-source.html">Building 
Tapestry from Source</a>
+                        <a href="developer-information.html">Developer 
Information</a>
                 
                         
                     </div>
@@ -187,7 +187,7 @@
                 <span class="icon aui-icon content-type-page" 
title="Page">Page:</span>        </div>
 
         <div class="details">
-                        <a href="version-numbers.html">Version Numbers</a>
+                        <a href="release-process.html">Release Process</a>
                 
                         
                     </div>
@@ -196,7 +196,7 @@
                 <span class="icon aui-icon content-type-page" 
title="Page">Page:</span>        </div>
 
         <div class="details">
-                        <a href="developer-bible.html">Developer Bible</a>
+                        <a href="building-tapestry-from-source.html">Building 
Tapestry from Source</a>
                 
                         
                     </div>
@@ -213,7 +213,7 @@
 </div>
 
 
-<h2 id="DeveloperBible-IDEChoices">IDE Choices</h2><h3 
id="DeveloperBible-IntelliJ">IntelliJ</h3><p>It's a free license for all 
committers and it's just better. Yes, the first few days can be an unpleasant 
fumble because everything is almost, but not quite, familiar. Pretty soon 
you'll love IDEA and recognize that Eclipse has been bending you over and doing 
unspeakable things.</p><p>There are shared code formatting settings in the <a 
class="external-link" 
href="https://git-wip-us.apache.org/repos/asf?p=tapestry-5.git;a=tree;f=support";>support
 directory</a> (idea-settings.jar). This will prevent unexpected conflicts due 
to formatting.</p><h3 id="DeveloperBible-Eclipse">Eclipse</h3><p>Howard uses 
this ... because he can't manage to switch IDEs constantly (he uses Eclipse for 
training). Lately its gotten better.</p><p>As with IntelliJ, there are shared 
code formatting settings for Eclipse in the <a class="external-link" 
href="https://git-wip-us.apache.org/repos/asf?p=tapestry-5.git;a=t
 ree;f=support">support directory</a> (tapestry-indent-eclipse.xml).</p><h2 
id="DeveloperBible-Copyrights">Copyrights</h2><p>All source files should have 
the ASF copyright comment on top, except where such a comment would interfere 
with its behavior. For example, component template files omit the 
comment.</p><p>As you make changes to files, update the copyright to add the 
current year to the list. The goal is that the copyright notice includes the 
year in which files change. When creating a new file, don't back date the 
copyright year ... start with the current year. Try not to change the copyright 
year on files that haven't actually changed.</p><p>IntelliJ has a great 
comparison view: Cmd-9 to see the local changes, the Cmd-D to see the 
differences. You can whip through the changes (using Cmd-forward arrow) and 
make sure copyrights are up to date as you review the changes prior to a 
commit.</p><h2 id="DeveloperBible-CommitMessages">Commit Messages</h2><p>Always 
provide a commit mess
 age. Howard generally tries to work off the JIRA, so his commit message is 
often:</p><blockquote><p>TAP5-1234: Make the Foo Widget more 
Ajax-tastic!</p></blockquote><p>It is <em>very important</em> to include the 
JIRA issue id in the commit. This is used in many places: JIRA links issues to 
the Git&#160;commits for that issue (very handy for seeing what changed as part 
of a bug fix). The Hudson CI server does as well, and will actually link 
Git&#160;commits to issues after succesfully building.</p><h2 
id="DeveloperBible-JIRAProcedures">JIRA Procedures</h2><p>All Tapestry 
committers should be registerred with JIRA and part of the tapestry-developers 
JIRA group.</p><p>Every committer is invited to look at the list of <a 
class="external-link" 
href="https://issues.apache.org/jira/secure/IssueNavigator.jspa?mode=hide&amp;requestId=12317068";>'Review
 for closing'</a> issues and review them as it contains probably outdated or no 
more valid issues.</p><p>There's also a list of all <a class="
 external-link" 
href="https://issues.apache.org/jira/secure/IssueNavigator.jspa?mode=hide&amp;requestId=12316792";>Open</a>
 issue about the project.</p><p>Ideally, we would always work top priortity to 
low priority. Howard sometimes jump out of order, if there's something cool to 
work on that fits in an available time slot. Alternately, you are always 
allowed to change the priority of a bug before or as you work it.</p><p>As a 
general rule issues which are "<em>Invalid</em>" or "<em>Won't</em> 
<em>Fix</em>" shouldn't have a "<em>Fix</em> <em>version</em>".</p><h3 
id="DeveloperBible-Startingwork">Starting work</h3><p>When you start to work on 
an issue, make sure it is <em>assigned to you</em> and use the <em>start 
progress</em> option.</p><p>Add comments about the state of the fix, or the 
challenges in creating a fix. This often spurs the Issue's adder to provide 
more details.</p><p>Update the issue description to make it more legible and 
more precise if needed, i.e., "NPE in CheckUpda
 tes" might become "NullPointerException when checking for updates to files 
that have been deleted". Verbose is good.</p><h3 
id="DeveloperBible-Closingbugs">Closing bugs</h3><p>Is it a bug fix without 
tests? <strong>No.</strong> A good plan is to write a test that fails then work 
the code until the test passes. Often code works in a unit test but fails 
unexpectedly in an integration test. As the G-Man says <em>"Expect unforeseen 
consequences"</em>.</p><p>When you check in a fix, you should 
<strong>close</strong> the issue and make sure the <strong>fix release</strong> 
is correct.</p><p>We're playing fast and loose &#8211; a better procedure would 
be to mark the bug resolved and verify the fix before closing it. That's ok, we 
have a community to double check our work <img class="emoticon emoticon-smile" 
src="https://cwiki.apache.org/confluence/s/-7iq2vk/8301/13280cd41a592ca5883bbc1ae415b58671505365/_/images/icons/emoticons/smile.svg";
 data-emoticon-name="smile" alt="(smile)">.</p><p>Fo
 r anything non-trivial, wait for the Hudson CI server to build. It catches a 
lot of things ... such as files that were not added to Git. And even IntelliJ 
has a bit of trouble with wildly refactored code. Hudson will catch all 
that.</p><h3 id="DeveloperBible-Invalidissuesandduplicates">Invalid issues and 
duplicates</h3><p>Always provide comments about why_ an issue is invalid 
(<em>"A Ruby implementation of Tapestry is out of scope for the 
project."</em>), or at least, a link to the duplicate issues.</p><p>Consider 
writing new tests to prove that an issue is not valid and then leave the tests 
in place &#8211; then close the bug as invalid.</p><p>Close the issue but 
<em>make sure the fix release is blank</em>. Otherwise, the issue <em>will be 
listed in the release notes</em>, which we don't want.</p><h2 
id="DeveloperBible-Publicvs.Private/Internal">Public vs. 
Private/Internal</h2><p>This is a real big deal. As long as code is in the 
internal package, we have a high degree of carte-bla
 nche to change it. As soon as code is public, we become handcuffed to 
backwards compatibility.</p><p><em>Interfaces are public, implementations are 
private</em>. You can see this is the bulk of the code, where 
org.apache.tapestry5.services is almost all interfaces and the implementations 
are in org.apache.tapestry5.internal.services.</p><p>Many more services have 
both the interface and the implementation in 
org.apache.tapestry5.internal.services.</p><p>We absolutely <em>do not</em> 
want to make Page or ComponentPageElement public. You will often see public 
service facades that take a page name as a method parameter, and convert it to 
a page instance before invoking methods on internal services.</p><h2 
id="DeveloperBible-EvolvingComponents">Evolving Components</h2><p>We do not 
have a specific plan for this yet. Future Tapestry 5 will add features to allow 
clean renames of parameters, and a way to deprecated and eventually remove 
components.</p><h2 id="DeveloperBible-EvolvingInterface
 s">Evolving Interfaces</h2><p>Tapestry uses interfaces quite 
extensively.</p><p>Interfaces fall into two categories: service interfaces 
called by user code, and interfaces implemented by user code.</p><p>Internal 
interfaces may be changed at any time. That's why so much is kept 
internal.</p><h3 id="DeveloperBible-ServiceInterfaces">Service 
Interfaces</h3><p>New methods may be added if absolutely necessary, but this 
should be avoided if at all possible. Don't forget the <code>@since</code> 
Javadoc annotation.</p><p>Consider having a stable public facade service whose 
implementation calls into one or more internal service.</p><h3 
id="DeveloperBible-UserInterfaces">User Interfaces</h3><p>These should be 
frozen, no changes once released. Failure to do so causes <em>non-backwards 
compatible upgrade problems</em>; that is, classes that implement the (old) 
interface are suddenly invalid, missing methods from the (new) 
interface.</p><p>Consider introducing a new interface that extends the o
 ld one and adds new methods. Make sure you support both.</p><p>You can see 
this with ServiceDef and ServiceDef2 (which extends ServiceDef). Yes this can 
be a bit ugly.</p><p>Howard uses utility methods that convert from ServiceDef 
to ServiceDef2, adding a wrapper implementation around a ServiceDef instance if 
necessary:</p><div class="code panel pdl" style="border-width: 1px;"><div 
class="codeContent panelContent pdl">
+<h2 id="DeveloperBible-IDEChoices">IDE Choices</h2><h3 
id="DeveloperBible-IntelliJ">IntelliJ</h3><p>It's a free license for all 
committers and it's just better. Yes, the first few days can be an unpleasant 
fumble because everything is almost, but not quite, familiar. Pretty soon 
you'll love IDEA and recognize that Eclipse has been bending you over and doing 
unspeakable things.</p><p>There are shared code formatting settings in the <a 
class="external-link" 
href="https://git-wip-us.apache.org/repos/asf?p=tapestry-5.git;a=tree;f=support";>support
 directory</a> (idea-settings.jar). This will prevent unexpected conflicts due 
to formatting.</p><h3 id="DeveloperBible-Eclipse">Eclipse</h3><p>Howard uses 
this ... because he can't manage to switch IDEs constantly (he uses Eclipse for 
training). Lately its gotten better.</p><p>As with IntelliJ, there are shared 
code formatting settings for Eclipse in the <a class="external-link" 
href="https://git-wip-us.apache.org/repos/asf?p=tapestry-5.git;a=t
 ree;f=support">support directory</a> (tapestry-indent-eclipse.xml).</p><h2 
id="DeveloperBible-Copyrights">Copyrights</h2><p>All source files should have 
the ASF copyright comment on top, except where such a comment would interfere 
with its behavior. For example, component template files omit the 
comment.</p><p>As you make changes to files, update the copyright to add the 
current year to the list. The goal is that the copyright notice includes the 
year in which files change. When creating a new file, don't back date the 
copyright year ... start with the current year. Try not to change the copyright 
year on files that haven't actually changed.</p><p>IntelliJ has a great 
comparison view: Cmd-9 to see the local changes, the Cmd-D to see the 
differences. You can whip through the changes (using Cmd-forward arrow) and 
make sure copyrights are up to date as you review the changes prior to a 
commit.</p><h2 id="DeveloperBible-CommitMessages">Commit Messages</h2><p>Always 
provide a commit mess
 age. Howard generally tries to work off the JIRA, so his commit message is 
often:</p><blockquote><p>TAP5-1234: Make the Foo Widget more 
Ajax-tastic!</p></blockquote><p>It is <em>very important</em> to include the 
JIRA issue id in the commit. This is used in many places: JIRA links issues to 
the Git&#160;commits for that issue (very handy for seeing what changed as part 
of a bug fix). The Hudson CI server does as well, and will actually link 
Git&#160;commits to issues after succesfully building.</p><h2 
id="DeveloperBible-JIRAProcedures">JIRA Procedures</h2><p>All Tapestry 
committers should be registerred with JIRA and part of the tapestry-developers 
JIRA group.</p><p>Every committer is invited to look at the list of <a 
class="external-link" 
href="https://issues.apache.org/jira/secure/IssueNavigator.jspa?mode=hide&amp;requestId=12317068";>'Review
 for closing'</a> issues and review them as it contains probably outdated or no 
more valid issues.</p><p>There's also a list of all <a class="
 external-link" 
href="https://issues.apache.org/jira/secure/IssueNavigator.jspa?mode=hide&amp;requestId=12316792";>Open</a>
 issue about the project.</p><p>Ideally, we would always work top priortity to 
low priority. Howard sometimes jump out of order, if there's something cool to 
work on that fits in an available time slot. Alternately, you are always 
allowed to change the priority of a bug before or as you work it.</p><p>As a 
general rule issues which are "<em>Invalid</em>" or "<em>Won't</em> 
<em>Fix</em>" shouldn't have a "<em>Fix</em> <em>version</em>".</p><h3 
id="DeveloperBible-Startingwork">Starting work</h3><p>When you start to work on 
an issue, make sure it is <em>assigned to you</em> and use the <em>start 
progress</em> option.</p><p>Add comments about the state of the fix, or the 
challenges in creating a fix. This often spurs the Issue's adder to provide 
more details.</p><p>Update the issue description to make it more legible and 
more precise if needed, i.e., "NPE in CheckUpda
 tes" might become "NullPointerException when checking for updates to files 
that have been deleted". Verbose is good.</p><h3 
id="DeveloperBible-Closingbugs">Closing bugs</h3><p>Is it a bug fix without 
tests? <strong>No.</strong> A good plan is to write a test that fails then work 
the code until the test passes. Often code works in a unit test but fails 
unexpectedly in an integration test. As the G-Man says <em>"Expect unforeseen 
consequences"</em>.</p><p>When you check in a fix, you should 
<strong>close</strong> the issue and make sure the <strong>fix release</strong> 
is correct.</p><p>We're playing fast and loose &#8211; a better procedure would 
be to mark the bug resolved and verify the fix before closing it. That's ok, we 
have a community to double check our work <img class="emoticon emoticon-smile" 
src="https://cwiki.apache.org/confluence/s/-wgxcy0/8703/98yf4s/_/images/icons/emoticons/smile.svg";
 data-emoticon-name="smile" alt="(smile)">.</p><p>For anything non-trivial, 
wait for t
 he Hudson CI server to build. It catches a lot of things ... such as files 
that were not added to Git. And even IntelliJ has a bit of trouble with wildly 
refactored code. Hudson will catch all that.</p><h3 
id="DeveloperBible-Invalidissuesandduplicates">Invalid issues and 
duplicates</h3><p>Always provide comments about why_ an issue is invalid 
(<em>"A Ruby implementation of Tapestry is out of scope for the 
project."</em>), or at least, a link to the duplicate issues.</p><p>Consider 
writing new tests to prove that an issue is not valid and then leave the tests 
in place &#8211; then close the bug as invalid.</p><p>Close the issue but 
<em>make sure the fix release is blank</em>. Otherwise, the issue <em>will be 
listed in the release notes</em>, which we don't want.</p><h2 
id="DeveloperBible-Publicvs.Private/Internal">Public vs. 
Private/Internal</h2><p>This is a real big deal. As long as code is in the 
internal package, we have a high degree of carte-blanche to change it. As soon 
as code
  is public, we become handcuffed to backwards 
compatibility.</p><p><em>Interfaces are public, implementations are 
private</em>. You can see this is the bulk of the code, where 
org.apache.tapestry5.services is almost all interfaces and the implementations 
are in org.apache.tapestry5.internal.services.</p><p>Many more services have 
both the interface and the implementation in 
org.apache.tapestry5.internal.services.</p><p>We absolutely <em>do not</em> 
want to make Page or ComponentPageElement public. You will often see public 
service facades that take a page name as a method parameter, and convert it to 
a page instance before invoking methods on internal services.</p><h2 
id="DeveloperBible-EvolvingComponents">Evolving Components</h2><p>We do not 
have a specific plan for this yet. Future Tapestry 5 will add features to allow 
clean renames of parameters, and a way to deprecated and eventually remove 
components.</p><h2 id="DeveloperBible-EvolvingInterfaces">Evolving 
Interfaces</h2><p>Tape
 stry uses interfaces quite extensively.</p><p>Interfaces fall into two 
categories: service interfaces called by user code, and interfaces implemented 
by user code.</p><p>Internal interfaces may be changed at any time. That's why 
so much is kept internal.</p><h3 id="DeveloperBible-ServiceInterfaces">Service 
Interfaces</h3><p>New methods may be added if absolutely necessary, but this 
should be avoided if at all possible. Don't forget the <code>@since</code> 
Javadoc annotation.</p><p>Consider having a stable public facade service whose 
implementation calls into one or more internal service.</p><h3 
id="DeveloperBible-UserInterfaces">User Interfaces</h3><p>These should be 
frozen, no changes once released. Failure to do so causes <em>non-backwards 
compatible upgrade problems</em>; that is, classes that implement the (old) 
interface are suddenly invalid, missing methods from the (new) 
interface.</p><p>Consider introducing a new interface that extends the old one 
and adds new methods. Make 
 sure you support both.</p><p>You can see this with ServiceDef and ServiceDef2 
(which extends ServiceDef). Yes this can be a bit ugly.</p><p>Howard uses 
utility methods that convert from ServiceDef to ServiceDef2, adding a wrapper 
implementation around a ServiceDef instance if necessary:</p><div class="code 
panel pdl" style="border-width: 1px;"><div class="codeContent panelContent pdl">
 <pre><code class="language-java">  public static ServiceDef2 
toServiceDef2(final ServiceDef sd)
   {
     if (sd instanceof ServiceDef2)
@@ -235,7 +235,7 @@
     };
   }
 </code></pre>
-</div></div><h2 id="DeveloperBible-Useof@since">Use of @since</h2><p>When 
adding new classes or interface, or adding new methods to existing types, add 
an @since Javadoc comment.</p><p>Use the complete version number of the release 
in which the type or method was added: i.e., <em>@since 5.1.0.3</em>.</p><h2 
id="DeveloperBible-CodeStyle&amp;Formatting">Code Style &amp; 
Formatting</h2><p>Yes, at one time Howard used leading underscores for field 
names. He has since changed my mind, but this unfortunately infected other 
people; please try to make your code blend in when modifying existing 
source.</p><p>Long ago, Tapestry (3) code used the regrettable 
"leading-I-on-interfaces" style. Don't do that. Instead, name the 
implementation class with an "Impl" at the end.</p><p>Howard prefers braces on 
a new line (and thus, open braces lined up with close braces), so that's what 
the default code formatting is set up for. It's okay to omit braces for trivial 
one-liner if statements, such as <code
 >if (!test) return;</code>.</p><p>Indent with 4 spaces instead of 
 >tabs.</p><p>Use a lot of vertical whitespace to break methods into logical 
 >sections.</p><p>We're coding Java, not Pascal; it's better to have a few 
 >checks early on with quick returns or exceptions than have ten-levels deep 
 >block nesting just so a method can have a single return statement. In other 
 >words, <em>else considered harmful</em>. Low code complexity is better, more 
 >readable, more maintainable code.</p><p>Don't bother alphabetizing things, 
 >because the IDE lets you jump around easily.</p><p><em>Final is the new 
 >private.</em> Final fields are great for multi-threaded code. Especially when 
 >creating service implementations with dependencies, store those dependencies 
 >into final fields. Once we're all running on 100 core workstations, you'll 
 >thank me. Seriously, Java's memory model is seriously twisted stuff, and 
 >assigning to a non-final field from a constructor opens up a tiny window of 
 >non-thread safety.</p><h2 id=
 "DeveloperBible-Comments">Comments</h2><p>Comments are overwhelmingly 
important. Try to capture the <em>why</em> of a class or method. Add lots of 
links, to code that will be invoked by the method, to related methods or 
classes, and so forth. For instance, you may often have an annotation, a worker 
class for the annotation, and a related service all cross-linked.</p><p>Comment 
the <em>interfaces</em> and don't get worked up on the 
<em>implementations</em>. Javadoc does a perfectly good job of copying 
interface comments to implementations, so this falls under the <em>Don't Repeat 
Yourself</em> guideline.</p><p>Be very careful about documenting what methods 
can accept null, and what methods may return null. Generally speaking, people 
will assume that null is not allowed for parameters, and method will never 
return null, unless it is explicitly documented that null is allowed (or 
potentially returned).</p><h2 
id="DeveloperBible-Documentation">Documentation</h2><p>Try and keep the docum
 entation up-to date as you make changes; it is <em>much</em> harder to do so 
later. This is now much easier using the Confluence wiki (you're reading the 
result <img class="emoticon emoticon-smile" 
src="https://cwiki.apache.org/confluence/s/-7iq2vk/8301/13280cd41a592ca5883bbc1ae415b58671505365/_/images/icons/emoticons/smile.svg";
 data-emoticon-name="smile" alt="(smile)">).</p><p>Documentation was at one 
point the <em>#1 criticism</em> of Tapestry!</p><h2 
id="DeveloperBible-ClassandMethodNamingConventions">Class and Method Naming 
Conventions</h2><p>Naming things is hard. Names that make sense to one person 
won't to another.</p><p>That being said, Howard has tried to be somewhat 
consistent with naming. Not perfectly.</p><h3 
id="DeveloperBible-Factory,Creator">Factory, Creator</h3><p>A factory class 
creates new objects. Methods will often be prefixed with "create" or "new". 
Don't expect a Factory to cache anything, it just creates new things.</p><h3 
id="DeveloperBible-Source">Source</h3
 ><p>A source is a level up from a Factory. It <em>may</em> combine multiple 
 >factories together. It <em>usually</em> will cache the result. Method are 
 >often prefixed with "get".</p><h3 id="DeveloperBible-Findvs.Get">Find vs. 
 >Get</h3><p>For methods: A "find" prefix indicates that a non-match is valid 
 >and null may be returned. A "get" prefix indicates that a non-match is 
 >invalid and an exception will be thrown in that case (and null will never be 
 >returned).</p><h3 id="DeveloperBible-Contribution">Contribution</h3><p>A data 
 >object usually associated with a Tapestry IoC service's configuration.</p><h3 
 >id="DeveloperBible-Filter">Filter</h3><p>Part of a pipeline, where there's an 
 >associated main interface, and the Filter wraps around that main interface. 
 >Each main interface method is duplicated in the Filter, with an extra 
 >parameter used to chain the interface.</p><h3 
 >id="DeveloperBible-Manager">Manager</h3><p>Often a wrapper around a service 
 >configuration, it provides access to the contri
 buted values (possibly after some transformation).</p><h3 
id="DeveloperBible-To">To</h3><p>A method prefix that indicates a conversion or 
coersion from one type to another. I.e., 
<code>toUserPresentable()</code>.</p><h3 
id="DeveloperBible-Worker">Worker</h3><p>An object that peforms a specific job. 
Workers will be stateless, but will be passed a stateful object to perform some 
operation upon.</p><h3 id="DeveloperBible-Builder">Builder</h3><p>An object 
whose job is to create other objects, typically in the context of creating a 
core service implementation for a Tapestry IoC service (such as PipelineBuilder 
or ChainBuilder).</p><h3 id="DeveloperBible-Support">Support</h3><p>An object 
that provides supporting operations to other objects; this is a kind of "loose 
aggregation".</p><h3 id="DeveloperBible-Parameters">Parameters</h3><p>A data 
object that holds a number of related values that would otherwise be separate 
parameter values to a method. This tends to streamline code (especially 
 when using a Filter interface) and allows the parameters to be evolved without 
changing the method signature.</p><h3 
id="DeveloperBible-Strategy">Strategy</h3><p>An object that "plugs into" some 
other code, allowing certain decisions to be deferred to the Strategy. Often a 
Strategy is selected based on the type of some object being operated 
upon.</p><h3 id="DeveloperBible-Context">Context</h3><p>Captures some stateful 
information that may be passed around between stateless services.</p><h3 
id="DeveloperBible-Constants">Constants</h3><p>A non-instantiable class that 
contains public static fields that are referenced in multiple places.</p><h3 
id="DeveloperBible-Hub">Hub</h3><p>An object that allows listeners to be 
registered. Often includes a method prefixed with "trigger" that will send 
notifications to listeners.</p><h2 
id="DeveloperBible-ImplementtoString()">Implement 
<code>toString()</code></h2><p>Objects that are exposed to user code should 
generally implement a meaningful toStri
 ng() method. And that method should be tested.</p><h2 
id="DeveloperBible-Subclassing">Subclassing</h2><p>You'll notice there isn't a 
lot of inheritance in Tapestry. Given the function of the IoC container, it is 
much more common to use some variation of <em>aggregation</em> rather than 
<em>inheritance</em>.</p><p>Where subclassing exists, the guideline for 
constructor parameters is: the subclass should include all the constructor 
parameters of the superclass, in the same positions. Thus subclass constructor 
parameters are appended to the list of super-class constructor 
parameters.</p></div>
+</div></div><h2 id="DeveloperBible-Useof@since">Use of @since</h2><p>When 
adding new classes or interface, or adding new methods to existing types, add 
an @since Javadoc comment.</p><p>Use the complete version number of the release 
in which the type or method was added: i.e., <em>@since 5.1.0.3</em>.</p><h2 
id="DeveloperBible-CodeStyle&amp;Formatting">Code Style &amp; 
Formatting</h2><p>Yes, at one time Howard used leading underscores for field 
names. He has since changed my mind, but this unfortunately infected other 
people; please try to make your code blend in when modifying existing 
source.</p><p>Long ago, Tapestry (3) code used the regrettable 
"leading-I-on-interfaces" style. Don't do that. Instead, name the 
implementation class with an "Impl" at the end.</p><p>Howard prefers braces on 
a new line (and thus, open braces lined up with close braces), so that's what 
the default code formatting is set up for. It's okay to omit braces for trivial 
one-liner if statements, such as <code
 >if (!test) return;</code>.</p><p>Indent with 4 spaces instead of 
 >tabs.</p><p>Use a lot of vertical whitespace to break methods into logical 
 >sections.</p><p>We're coding Java, not Pascal; it's better to have a few 
 >checks early on with quick returns or exceptions than have ten-levels deep 
 >block nesting just so a method can have a single return statement. In other 
 >words, <em>else considered harmful</em>. Low code complexity is better, more 
 >readable, more maintainable code.</p><p>Don't bother alphabetizing things, 
 >because the IDE lets you jump around easily.</p><p><em>Final is the new 
 >private.</em> Final fields are great for multi-threaded code. Especially when 
 >creating service implementations with dependencies, store those dependencies 
 >into final fields. Once we're all running on 100 core workstations, you'll 
 >thank me. Seriously, Java's memory model is seriously twisted stuff, and 
 >assigning to a non-final field from a constructor opens up a tiny window of 
 >non-thread safety.</p><h2 id=
 "DeveloperBible-Comments">Comments</h2><p>Comments are overwhelmingly 
important. Try to capture the <em>why</em> of a class or method. Add lots of 
links, to code that will be invoked by the method, to related methods or 
classes, and so forth. For instance, you may often have an annotation, a worker 
class for the annotation, and a related service all cross-linked.</p><p>Comment 
the <em>interfaces</em> and don't get worked up on the 
<em>implementations</em>. Javadoc does a perfectly good job of copying 
interface comments to implementations, so this falls under the <em>Don't Repeat 
Yourself</em> guideline.</p><p>Be very careful about documenting what methods 
can accept null, and what methods may return null. Generally speaking, people 
will assume that null is not allowed for parameters, and method will never 
return null, unless it is explicitly documented that null is allowed (or 
potentially returned).</p><h2 
id="DeveloperBible-Documentation">Documentation</h2><p>Try and keep the docum
 entation up-to date as you make changes; it is <em>much</em> harder to do so 
later. This is now much easier using the Confluence wiki (you're reading the 
result <img class="emoticon emoticon-smile" 
src="https://cwiki.apache.org/confluence/s/-wgxcy0/8703/98yf4s/_/images/icons/emoticons/smile.svg";
 data-emoticon-name="smile" alt="(smile)">).</p><p>Documentation was at one 
point the <em>#1 criticism</em> of Tapestry!</p><h2 
id="DeveloperBible-ClassandMethodNamingConventions">Class and Method Naming 
Conventions</h2><p>Naming things is hard. Names that make sense to one person 
won't to another.</p><p>That being said, Howard has tried to be somewhat 
consistent with naming. Not perfectly.</p><h3 
id="DeveloperBible-Factory,Creator">Factory, Creator</h3><p>A factory class 
creates new objects. Methods will often be prefixed with "create" or "new". 
Don't expect a Factory to cache anything, it just creates new things.</p><h3 
id="DeveloperBible-Source">Source</h3><p>A source is a level up from a 
 Factory. It <em>may</em> combine multiple factories together. It 
<em>usually</em> will cache the result. Method are often prefixed with 
"get".</p><h3 id="DeveloperBible-Findvs.Get">Find vs. Get</h3><p>For methods: A 
"find" prefix indicates that a non-match is valid and null may be returned. A 
"get" prefix indicates that a non-match is invalid and an exception will be 
thrown in that case (and null will never be returned).</p><h3 
id="DeveloperBible-Contribution">Contribution</h3><p>A data object usually 
associated with a Tapestry IoC service's configuration.</p><h3 
id="DeveloperBible-Filter">Filter</h3><p>Part of a pipeline, where there's an 
associated main interface, and the Filter wraps around that main interface. 
Each main interface method is duplicated in the Filter, with an extra parameter 
used to chain the interface.</p><h3 
id="DeveloperBible-Manager">Manager</h3><p>Often a wrapper around a service 
configuration, it provides access to the contributed values (possibly after 
some 
 transformation).</p><h3 id="DeveloperBible-To">To</h3><p>A method prefix that 
indicates a conversion or coersion from one type to another. I.e., 
<code>toUserPresentable()</code>.</p><h3 
id="DeveloperBible-Worker">Worker</h3><p>An object that peforms a specific job. 
Workers will be stateless, but will be passed a stateful object to perform some 
operation upon.</p><h3 id="DeveloperBible-Builder">Builder</h3><p>An object 
whose job is to create other objects, typically in the context of creating a 
core service implementation for a Tapestry IoC service (such as PipelineBuilder 
or ChainBuilder).</p><h3 id="DeveloperBible-Support">Support</h3><p>An object 
that provides supporting operations to other objects; this is a kind of "loose 
aggregation".</p><h3 id="DeveloperBible-Parameters">Parameters</h3><p>A data 
object that holds a number of related values that would otherwise be separate 
parameter values to a method. This tends to streamline code (especially when 
using a Filter interface) and
  allows the parameters to be evolved without changing the method 
signature.</p><h3 id="DeveloperBible-Strategy">Strategy</h3><p>An object that 
"plugs into" some other code, allowing certain decisions to be deferred to the 
Strategy. Often a Strategy is selected based on the type of some object being 
operated upon.</p><h3 id="DeveloperBible-Context">Context</h3><p>Captures some 
stateful information that may be passed around between stateless 
services.</p><h3 id="DeveloperBible-Constants">Constants</h3><p>A 
non-instantiable class that contains public static fields that are referenced 
in multiple places.</p><h3 id="DeveloperBible-Hub">Hub</h3><p>An object that 
allows listeners to be registered. Often includes a method prefixed with 
"trigger" that will send notifications to listeners.</p><h2 
id="DeveloperBible-ImplementtoString()">Implement 
<code>toString()</code></h2><p>Objects that are exposed to user code should 
generally implement a meaningful toString() method. And that method shoul
 d be tested.</p><h2 id="DeveloperBible-Subclassing">Subclassing</h2><p>You'll 
notice there isn't a lot of inheritance in Tapestry. Given the function of the 
IoC container, it is much more common to use some variation of 
<em>aggregation</em> rather than <em>inheritance</em>.</p><p>Where subclassing 
exists, the guideline for constructor parameters is: the subclass should 
include all the constructor parameters of the superclass, in the same 
positions. Thus subclass constructor parameters are appended to the list of 
super-class constructor parameters.</p></div>
             </div>
             <!-- /// Content End -->
           </div>

Modified: websites/production/tapestry/content/developer-information.html
==============================================================================
--- websites/production/tapestry/content/developer-information.html (original)
+++ websites/production/tapestry/content/developer-information.html Sat Nov 26 
13:17:27 2022
@@ -32,10 +32,10 @@
   <link rel="apple-touch-icon-precomposed" 
href="/images/apache-tapestry-icon-57.png">
   <link rel="shortcut icon" href="/images/apache-tapestry-icon-32.png">
 
-  <link rel="stylesheet" 
href="https://fonts.googleapis.com/css2?family=Sarabun:ital,wght@0,400;0,700;1,400;1,700&display=swap";>
 
-  <link rel="stylesheet" 
href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css"; 
integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh"
 crossorigin="anonymous">
+  <link rel="stylesheet" href="/resources/bootstrap/bootstrap.min.css">
   <link rel="stylesheet" 
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.13.0/css/all.min.css";>
   <link rel="stylesheet" 
href="https://cdnjs.cloudflare.com/ajax/libs/prism/1.20.0/themes/prism.min.css";>
+  <link rel="stylesheet" href="/resources/fonts/fonts.css">
   <link rel="stylesheet" href="/styles/main.css">
 
   <script type="text/javascript">
@@ -46,7 +46,7 @@
 
   <script src="https://code.jquery.com/jquery-3.4.1.slim.min.js"; 
integrity="sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n"
 crossorigin="anonymous" defer></script>
   <script 
src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js"; 
integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo"
 crossorigin="anonymous" defer></script>
-  <script 
src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js"; 
integrity="sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6"
 crossorigin="anonymous" defer></script>
+  <script src="stylesheet" href="/resources/bootstrap/bootstrap.min.js">
   <script 
src="https://cdnjs.cloudflare.com/ajax/libs/prism/1.20.0/prism.min.js"; 
defer></script>
        <script 
src="https://cdnjs.cloudflare.com/ajax/libs/prism/1.20.0/plugins/autoloader/prism-autoloader.min.js";
 defer></script>
 

Modified: websites/production/tapestry/content/development-dashboard.html
==============================================================================
--- websites/production/tapestry/content/development-dashboard.html (original)
+++ websites/production/tapestry/content/development-dashboard.html Sat Nov 26 
13:17:27 2022
@@ -32,10 +32,10 @@
   <link rel="apple-touch-icon-precomposed" 
href="/images/apache-tapestry-icon-57.png">
   <link rel="shortcut icon" href="/images/apache-tapestry-icon-32.png">
 
-  <link rel="stylesheet" 
href="https://fonts.googleapis.com/css2?family=Sarabun:ital,wght@0,400;0,700;1,400;1,700&display=swap";>
 
-  <link rel="stylesheet" 
href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css"; 
integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh"
 crossorigin="anonymous">
+  <link rel="stylesheet" href="/resources/bootstrap/bootstrap.min.css">
   <link rel="stylesheet" 
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.13.0/css/all.min.css";>
   <link rel="stylesheet" 
href="https://cdnjs.cloudflare.com/ajax/libs/prism/1.20.0/themes/prism.min.css";>
+  <link rel="stylesheet" href="/resources/fonts/fonts.css">
   <link rel="stylesheet" href="/styles/main.css">
 
   <script type="text/javascript">
@@ -46,7 +46,7 @@
 
   <script src="https://code.jquery.com/jquery-3.4.1.slim.min.js"; 
integrity="sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n"
 crossorigin="anonymous" defer></script>
   <script 
src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js"; 
integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo"
 crossorigin="anonymous" defer></script>
-  <script 
src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js"; 
integrity="sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6"
 crossorigin="anonymous" defer></script>
+  <script src="stylesheet" href="/resources/bootstrap/bootstrap.min.js">
   <script 
src="https://cdnjs.cloudflare.com/ajax/libs/prism/1.20.0/prism.min.js"; 
defer></script>
        <script 
src="https://cdnjs.cloudflare.com/ajax/libs/prism/1.20.0/plugins/autoloader/prism-autoloader.min.js";
 defer></script>
 
@@ -142,7 +142,7 @@
             
             <!-- /// Content Start -->
             <div id="content">
-                            <div id="ConfluenceContent"><p>The 
<strong>development dashboard</strong> is a built-in Tapestry page that can 
help identify and resolve problems in your application.</p><p>The dashboard is 
typically only available to requests from localhost (the page is whitelist 
access only, see <a href="security.html">Security</a>).</p><p><span>Some 
features of the dashboard are only available in development 
mode.</span></p><p>The dashboard is available via the URI "core/t5dashboard", 
or can be accessed by the <a class="external-link" 
href="http://tapestry.apache.org/5.4/apidocs/org/apache/tapestry5/corelib/components/DevTool.html";>DevTool</a>
 component's dropdown menu.</p><p><span>&#160;<span 
class="confluence-embedded-file-wrapper image-center-wrapper 
confluence-embedded-manual-size"><img class="confluence-embedded-image 
image-center" width="500" 
src="development-dashboard.data/Tapestry_5_Dashboard_-_pages.png"></span></span></p><p>By
 default, there are three tabs (t
 his is extensible).</p><h2 id="DevelopmentDashboard-Pages">Pages</h2><p>The 
pages tab shows what pages are currently loaded into the application. Tapestry 
only loads a page when it is first needed.</p><p>It is possible to clear out 
Tapestry's caches, forcing a reload. You can also run a garbage collection 
(GC).</p><p>It is possible to load any individual page, or attempt to load all 
pages. This can be a good way to see if all pages (and templates) are error 
free ... loading all will catch quite a few potential errors.</p><h2 
id="DevelopmentDashboard-Services">Services</h2><p>When using Tapestry there 
will often be a large number of services defined in the registry; a mix of the 
built-in services provided by the framework and your own.</p><p>Services are 
usually only instantiated once they are needed.</p><p><span 
class="confluence-embedded-file-wrapper image-center-wrapper 
confluence-embedded-manual-size"><img class="confluence-embedded-image 
image-center" width="500" src="developmen
 t-dashboard.data/Tapestry_5_Dashboard.png"></span></p><p>Services may be 
builtin, defined, virtual or real.</p><p><strong>Builtin</strong> only applies 
to a few special services that are part of Tapestry 
IoC.</p><p><strong>Defined</strong> services are defined in some module, but 
have not yet been referenced in any way.</p><p><strong>Virtual</strong> 
services have been referenced and have gotten as far as creating a service 
proxy.</p><p><strong>Real</strong> services have had methods invoked, this 
forces the <em>realization</em> of the service which includes instantiating the 
service, injecting dependencies, and decorating with any applicable 
interceptors.</p><h2 id="DevelopmentDashboard-ComponentLibraries">Component 
Libraries</h2><p><span class="confluence-embedded-file-wrapper 
image-center-wrapper confluence-embedded-manual-size"><img 
class="confluence-embedded-image image-center" width="500" 
src="development-dashboard.data/Tapestry_5_Dashboard_-_libs.png"></span></p><p>This
 page 
 gives a summary of all component libraries used in the current 
application.</p></div>
+                            <div id="ConfluenceContent"><p>The 
<strong>development dashboard</strong> is a built-in Tapestry page that can 
help identify and resolve problems in your application.</p><p>The dashboard is 
typically only available to requests from localhost (the page is whitelist 
access only, see <a href="security.html">Security</a>).</p><p><span>Some 
features of the dashboard are only available in development 
mode.</span></p><p>The dashboard is available via the URI "core/t5dashboard", 
or can be accessed by the <a class="external-link" 
href="http://tapestry.apache.org/5.4/apidocs/org/apache/tapestry5/corelib/components/DevTool.html";>DevTool</a>
 component's dropdown menu.</p><p><span>&#160;<span 
class="confluence-embedded-file-wrapper image-center-wrapper 
confluence-embedded-manual-size"><img class="confluence-embedded-image 
image-center" draggable="false" width="500" 
src="development-dashboard.data/Tapestry_5_Dashboard_-_pages.png"></span></span></p><p>By
 default, there
  are three tabs (this is extensible).</p><h2 
id="DevelopmentDashboard-Pages">Pages</h2><p>The pages tab shows what pages are 
currently loaded into the application. Tapestry only loads a page when it is 
first needed.</p><p>It is possible to clear out Tapestry's caches, forcing a 
reload. You can also run a garbage collection (GC).</p><p>It is possible to 
load any individual page, or attempt to load all pages. This can be a good way 
to see if all pages (and templates) are error free ... loading all will catch 
quite a few potential errors.</p><h2 
id="DevelopmentDashboard-Services">Services</h2><p>When using Tapestry there 
will often be a large number of services defined in the registry; a mix of the 
built-in services provided by the framework and your own.</p><p>Services are 
usually only instantiated once they are needed.</p><p><span 
class="confluence-embedded-file-wrapper image-center-wrapper 
confluence-embedded-manual-size"><img class="confluence-embedded-image 
image-center" draggable
 ="false" width="500" 
src="development-dashboard.data/Tapestry_5_Dashboard.png"></span></p><p>Services
 may be builtin, defined, virtual or real.</p><p><strong>Builtin</strong> only 
applies to a few special services that are part of Tapestry 
IoC.</p><p><strong>Defined</strong> services are defined in some module, but 
have not yet been referenced in any way.</p><p><strong>Virtual</strong> 
services have been referenced and have gotten as far as creating a service 
proxy.</p><p><strong>Real</strong> services have had methods invoked, this 
forces the <em>realization</em> of the service which includes instantiating the 
service, injecting dependencies, and decorating with any applicable 
interceptors.</p><h2 id="DevelopmentDashboard-ComponentLibraries">Component 
Libraries</h2><p><span class="confluence-embedded-file-wrapper 
image-center-wrapper confluence-embedded-manual-size"><img 
class="confluence-embedded-image image-center" draggable="false" width="500" 
src="development-dashboard.data/Tap
 estry_5_Dashboard_-_libs.png"></span></p><p>This page gives a summary of all 
component libraries used in the current application.</p></div>
             </div>
             <!-- /// Content End -->
           </div>

Modified: 
websites/production/tapestry/content/documentation-improvement-tasks.html
==============================================================================
--- websites/production/tapestry/content/documentation-improvement-tasks.html 
(original)
+++ websites/production/tapestry/content/documentation-improvement-tasks.html 
Sat Nov 26 13:17:27 2022
@@ -32,10 +32,10 @@
   <link rel="apple-touch-icon-precomposed" 
href="/images/apache-tapestry-icon-57.png">
   <link rel="shortcut icon" href="/images/apache-tapestry-icon-32.png">
 
-  <link rel="stylesheet" 
href="https://fonts.googleapis.com/css2?family=Sarabun:ital,wght@0,400;0,700;1,400;1,700&display=swap";>
 
-  <link rel="stylesheet" 
href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css"; 
integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh"
 crossorigin="anonymous">
+  <link rel="stylesheet" href="/resources/bootstrap/bootstrap.min.css">
   <link rel="stylesheet" 
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.13.0/css/all.min.css";>
   <link rel="stylesheet" 
href="https://cdnjs.cloudflare.com/ajax/libs/prism/1.20.0/themes/prism.min.css";>
+  <link rel="stylesheet" href="/resources/fonts/fonts.css">
   <link rel="stylesheet" href="/styles/main.css">
 
   <script type="text/javascript">
@@ -46,7 +46,7 @@
 
   <script src="https://code.jquery.com/jquery-3.4.1.slim.min.js"; 
integrity="sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n"
 crossorigin="anonymous" defer></script>
   <script 
src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js"; 
integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo"
 crossorigin="anonymous" defer></script>
-  <script 
src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js"; 
integrity="sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6"
 crossorigin="anonymous" defer></script>
+  <script src="stylesheet" href="/resources/bootstrap/bootstrap.min.js">
   <script 
src="https://cdnjs.cloudflare.com/ajax/libs/prism/1.20.0/prism.min.js"; 
defer></script>
        <script 
src="https://cdnjs.cloudflare.com/ajax/libs/prism/1.20.0/plugins/autoloader/prism-autoloader.min.js";
 defer></script>
 

Modified: websites/production/tapestry/content/documentation.html
==============================================================================
--- websites/production/tapestry/content/documentation.html (original)
+++ websites/production/tapestry/content/documentation.html Sat Nov 26 13:17:27 
2022
@@ -32,10 +32,10 @@
   <link rel="apple-touch-icon-precomposed" 
href="/images/apache-tapestry-icon-57.png">
   <link rel="shortcut icon" href="/images/apache-tapestry-icon-32.png">
 
-  <link rel="stylesheet" 
href="https://fonts.googleapis.com/css2?family=Sarabun:ital,wght@0,400;0,700;1,400;1,700&display=swap";>
 
-  <link rel="stylesheet" 
href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css"; 
integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh"
 crossorigin="anonymous">
+  <link rel="stylesheet" href="/resources/bootstrap/bootstrap.min.css">
   <link rel="stylesheet" 
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.13.0/css/all.min.css";>
   <link rel="stylesheet" 
href="https://cdnjs.cloudflare.com/ajax/libs/prism/1.20.0/themes/prism.min.css";>
+  <link rel="stylesheet" href="/resources/fonts/fonts.css">
   <link rel="stylesheet" href="/styles/main.css">
 
   <script type="text/javascript">
@@ -46,7 +46,7 @@
 
   <script src="https://code.jquery.com/jquery-3.4.1.slim.min.js"; 
integrity="sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n"
 crossorigin="anonymous" defer></script>
   <script 
src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js"; 
integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo"
 crossorigin="anonymous" defer></script>
-  <script 
src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js"; 
integrity="sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6"
 crossorigin="anonymous" defer></script>
+  <script src="stylesheet" href="/resources/bootstrap/bootstrap.min.js">
   <script 
src="https://cdnjs.cloudflare.com/ajax/libs/prism/1.20.0/prism.min.js"; 
defer></script>
        <script 
src="https://cdnjs.cloudflare.com/ajax/libs/prism/1.20.0/plugins/autoloader/prism-autoloader.min.js";
 defer></script>
 

Modified: websites/production/tapestry/content/dom.html
==============================================================================
--- websites/production/tapestry/content/dom.html (original)
+++ websites/production/tapestry/content/dom.html Sat Nov 26 13:17:27 2022
@@ -32,10 +32,10 @@
   <link rel="apple-touch-icon-precomposed" 
href="/images/apache-tapestry-icon-57.png">
   <link rel="shortcut icon" href="/images/apache-tapestry-icon-32.png">
 
-  <link rel="stylesheet" 
href="https://fonts.googleapis.com/css2?family=Sarabun:ital,wght@0,400;0,700;1,400;1,700&display=swap";>
 
-  <link rel="stylesheet" 
href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css"; 
integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh"
 crossorigin="anonymous">
+  <link rel="stylesheet" href="/resources/bootstrap/bootstrap.min.css">
   <link rel="stylesheet" 
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.13.0/css/all.min.css";>
   <link rel="stylesheet" 
href="https://cdnjs.cloudflare.com/ajax/libs/prism/1.20.0/themes/prism.min.css";>
+  <link rel="stylesheet" href="/resources/fonts/fonts.css">
   <link rel="stylesheet" href="/styles/main.css">
 
   <script type="text/javascript">
@@ -46,7 +46,7 @@
 
   <script src="https://code.jquery.com/jquery-3.4.1.slim.min.js"; 
integrity="sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n"
 crossorigin="anonymous" defer></script>
   <script 
src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js"; 
integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo"
 crossorigin="anonymous" defer></script>
-  <script 
src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js"; 
integrity="sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6"
 crossorigin="anonymous" defer></script>
+  <script src="stylesheet" href="/resources/bootstrap/bootstrap.min.js">
   <script 
src="https://cdnjs.cloudflare.com/ajax/libs/prism/1.20.0/prism.min.js"; 
defer></script>
        <script 
src="https://cdnjs.cloudflare.com/ajax/libs/prism/1.20.0/plugins/autoloader/prism-autoloader.min.js";
 defer></script>
 

Modified: websites/production/tapestry/content/download.html
==============================================================================
--- websites/production/tapestry/content/download.html (original)
+++ websites/production/tapestry/content/download.html Sat Nov 26 13:17:27 2022
@@ -32,10 +32,10 @@
   <link rel="apple-touch-icon-precomposed" 
href="/images/apache-tapestry-icon-57.png">
   <link rel="shortcut icon" href="/images/apache-tapestry-icon-32.png">
 
-  <link rel="stylesheet" 
href="https://fonts.googleapis.com/css2?family=Sarabun:ital,wght@0,400;0,700;1,400;1,700&display=swap";>
 
-  <link rel="stylesheet" 
href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css"; 
integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh"
 crossorigin="anonymous">
+  <link rel="stylesheet" href="/resources/bootstrap/bootstrap.min.css">
   <link rel="stylesheet" 
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.13.0/css/all.min.css";>
   <link rel="stylesheet" 
href="https://cdnjs.cloudflare.com/ajax/libs/prism/1.20.0/themes/prism.min.css";>
+  <link rel="stylesheet" href="/resources/fonts/fonts.css">
   <link rel="stylesheet" href="/styles/main.css">
 
   <script type="text/javascript">
@@ -46,7 +46,7 @@
 
   <script src="https://code.jquery.com/jquery-3.4.1.slim.min.js"; 
integrity="sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n"
 crossorigin="anonymous" defer></script>
   <script 
src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js"; 
integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo"
 crossorigin="anonymous" defer></script>
-  <script 
src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js"; 
integrity="sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6"
 crossorigin="anonymous" defer></script>
+  <script src="stylesheet" href="/resources/bootstrap/bootstrap.min.js">
   <script 
src="https://cdnjs.cloudflare.com/ajax/libs/prism/1.20.0/prism.min.js"; 
defer></script>
        <script 
src="https://cdnjs.cloudflare.com/ajax/libs/prism/1.20.0/plugins/autoloader/prism-autoloader.min.js";
 defer></script>
 

Modified: websites/production/tapestry/content/downloadboxes-v2.html
==============================================================================
--- websites/production/tapestry/content/downloadboxes-v2.html (original)
+++ websites/production/tapestry/content/downloadboxes-v2.html Sat Nov 26 
13:17:27 2022
@@ -32,10 +32,10 @@
   <link rel="apple-touch-icon-precomposed" 
href="/images/apache-tapestry-icon-57.png">
   <link rel="shortcut icon" href="/images/apache-tapestry-icon-32.png">
 
-  <link rel="stylesheet" 
href="https://fonts.googleapis.com/css2?family=Sarabun:ital,wght@0,400;0,700;1,400;1,700&display=swap";>
 
-  <link rel="stylesheet" 
href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css"; 
integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh"
 crossorigin="anonymous">
+  <link rel="stylesheet" href="/resources/bootstrap/bootstrap.min.css">
   <link rel="stylesheet" 
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.13.0/css/all.min.css";>
   <link rel="stylesheet" 
href="https://cdnjs.cloudflare.com/ajax/libs/prism/1.20.0/themes/prism.min.css";>
+  <link rel="stylesheet" href="/resources/fonts/fonts.css">
   <link rel="stylesheet" href="/styles/main.css">
 
   <script type="text/javascript">
@@ -46,7 +46,7 @@
 
   <script src="https://code.jquery.com/jquery-3.4.1.slim.min.js"; 
integrity="sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n"
 crossorigin="anonymous" defer></script>
   <script 
src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js"; 
integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo"
 crossorigin="anonymous" defer></script>
-  <script 
src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js"; 
integrity="sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6"
 crossorigin="anonymous" defer></script>
+  <script src="stylesheet" href="/resources/bootstrap/bootstrap.min.js">
   <script 
src="https://cdnjs.cloudflare.com/ajax/libs/prism/1.20.0/prism.min.js"; 
defer></script>
        <script 
src="https://cdnjs.cloudflare.com/ajax/libs/prism/1.20.0/plugins/autoloader/prism-autoloader.min.js";
 defer></script>
 

Modified: websites/production/tapestry/content/enum-parameter-recipe.html
==============================================================================
--- websites/production/tapestry/content/enum-parameter-recipe.html (original)
+++ websites/production/tapestry/content/enum-parameter-recipe.html Sat Nov 26 
13:17:27 2022
@@ -32,10 +32,10 @@
   <link rel="apple-touch-icon-precomposed" 
href="/images/apache-tapestry-icon-57.png">
   <link rel="shortcut icon" href="/images/apache-tapestry-icon-32.png">
 
-  <link rel="stylesheet" 
href="https://fonts.googleapis.com/css2?family=Sarabun:ital,wght@0,400;0,700;1,400;1,700&display=swap";>
 
-  <link rel="stylesheet" 
href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css"; 
integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh"
 crossorigin="anonymous">
+  <link rel="stylesheet" href="/resources/bootstrap/bootstrap.min.css">
   <link rel="stylesheet" 
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.13.0/css/all.min.css";>
   <link rel="stylesheet" 
href="https://cdnjs.cloudflare.com/ajax/libs/prism/1.20.0/themes/prism.min.css";>
+  <link rel="stylesheet" href="/resources/fonts/fonts.css">
   <link rel="stylesheet" href="/styles/main.css">
 
   <script type="text/javascript">
@@ -46,7 +46,7 @@
 
   <script src="https://code.jquery.com/jquery-3.4.1.slim.min.js"; 
integrity="sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n"
 crossorigin="anonymous" defer></script>
   <script 
src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js"; 
integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo"
 crossorigin="anonymous" defer></script>
-  <script 
src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js"; 
integrity="sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6"
 crossorigin="anonymous" defer></script>
+  <script src="stylesheet" href="/resources/bootstrap/bootstrap.min.js">
   <script 
src="https://cdnjs.cloudflare.com/ajax/libs/prism/1.20.0/prism.min.js"; 
defer></script>
        <script 
src="https://cdnjs.cloudflare.com/ajax/libs/prism/1.20.0/plugins/autoloader/prism-autoloader.min.js";
 defer></script>
 

Modified: websites/production/tapestry/content/environmental-services.html
==============================================================================
--- websites/production/tapestry/content/environmental-services.html (original)
+++ websites/production/tapestry/content/environmental-services.html Sat Nov 26 
13:17:27 2022
@@ -32,10 +32,10 @@
   <link rel="apple-touch-icon-precomposed" 
href="/images/apache-tapestry-icon-57.png">
   <link rel="shortcut icon" href="/images/apache-tapestry-icon-32.png">
 
-  <link rel="stylesheet" 
href="https://fonts.googleapis.com/css2?family=Sarabun:ital,wght@0,400;0,700;1,400;1,700&display=swap";>
 
-  <link rel="stylesheet" 
href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css"; 
integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh"
 crossorigin="anonymous">
+  <link rel="stylesheet" href="/resources/bootstrap/bootstrap.min.css">
   <link rel="stylesheet" 
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.13.0/css/all.min.css";>
   <link rel="stylesheet" 
href="https://cdnjs.cloudflare.com/ajax/libs/prism/1.20.0/themes/prism.min.css";>
+  <link rel="stylesheet" href="/resources/fonts/fonts.css">
   <link rel="stylesheet" href="/styles/main.css">
 
   <script type="text/javascript">
@@ -46,7 +46,7 @@
 
   <script src="https://code.jquery.com/jquery-3.4.1.slim.min.js"; 
integrity="sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n"
 crossorigin="anonymous" defer></script>
   <script 
src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js"; 
integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo"
 crossorigin="anonymous" defer></script>
-  <script 
src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js"; 
integrity="sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6"
 crossorigin="anonymous" defer></script>
+  <script src="stylesheet" href="/resources/bootstrap/bootstrap.min.js">
   <script 
src="https://cdnjs.cloudflare.com/ajax/libs/prism/1.20.0/prism.min.js"; 
defer></script>
        <script 
src="https://cdnjs.cloudflare.com/ajax/libs/prism/1.20.0/plugins/autoloader/prism-autoloader.min.js";
 defer></script>
 

Modified: websites/production/tapestry/content/error-page-recipe.html
==============================================================================
--- websites/production/tapestry/content/error-page-recipe.html (original)
+++ websites/production/tapestry/content/error-page-recipe.html Sat Nov 26 
13:17:27 2022
@@ -32,10 +32,10 @@
   <link rel="apple-touch-icon-precomposed" 
href="/images/apache-tapestry-icon-57.png">
   <link rel="shortcut icon" href="/images/apache-tapestry-icon-32.png">
 
-  <link rel="stylesheet" 
href="https://fonts.googleapis.com/css2?family=Sarabun:ital,wght@0,400;0,700;1,400;1,700&display=swap";>
 
-  <link rel="stylesheet" 
href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css"; 
integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh"
 crossorigin="anonymous">
+  <link rel="stylesheet" href="/resources/bootstrap/bootstrap.min.css">
   <link rel="stylesheet" 
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.13.0/css/all.min.css";>
   <link rel="stylesheet" 
href="https://cdnjs.cloudflare.com/ajax/libs/prism/1.20.0/themes/prism.min.css";>
+  <link rel="stylesheet" href="/resources/fonts/fonts.css">
   <link rel="stylesheet" href="/styles/main.css">
 
   <script type="text/javascript">
@@ -46,7 +46,7 @@
 
   <script src="https://code.jquery.com/jquery-3.4.1.slim.min.js"; 
integrity="sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n"
 crossorigin="anonymous" defer></script>
   <script 
src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js"; 
integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo"
 crossorigin="anonymous" defer></script>
-  <script 
src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js"; 
integrity="sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6"
 crossorigin="anonymous" defer></script>
+  <script src="stylesheet" href="/resources/bootstrap/bootstrap.min.js">
   <script 
src="https://cdnjs.cloudflare.com/ajax/libs/prism/1.20.0/prism.min.js"; 
defer></script>
        <script 
src="https://cdnjs.cloudflare.com/ajax/libs/prism/1.20.0/plugins/autoloader/prism-autoloader.min.js";
 defer></script>
 
@@ -270,7 +270,7 @@ public class Error404
 
 
 </code></pre>
-</div></div><p>The end-result, in when <em>not</em> in production mode, looks 
like this:</p><p></p><p><span class="confluence-embedded-file-wrapper 
image-center-wrapper confluence-embedded-manual-size"><img 
class="confluence-embedded-image confluence-content-image-border image-center" 
width="500" 
src="error-page-recipe.data/Resource_not_found_.png"></span></p><div 
class="confluence-information-macro 
confluence-information-macro-information"><span class="aui-icon aui-icon-small 
aui-iconfont-info confluence-information-macro-icon"></span><div 
class="confluence-information-macro-body"><p>An issue with an application that 
has a root Index page is that any invalid path, which would normally generate a 
404 error, is instead routed to the Index page (because the invalid path looks 
like page's activation context). See <a class="external-link" 
href="https://issues.apache.org/jira/browse/TAP5-2070";>Issue 
TAP5-2070</a>.</p></div></div></div>
+</div></div><p>The end-result, in when <em>not</em> in production mode, looks 
like this:</p><p></p><p><span class="confluence-embedded-file-wrapper 
image-center-wrapper confluence-embedded-manual-size"><img 
class="confluence-embedded-image confluence-content-image-border image-center" 
draggable="false" width="500" 
src="error-page-recipe.data/Resource_not_found_.png"></span></p><div 
class="confluence-information-macro 
confluence-information-macro-information"><span class="aui-icon aui-icon-small 
aui-iconfont-info confluence-information-macro-icon"></span><div 
class="confluence-information-macro-body"><p>An issue with an application that 
has a root Index page is that any invalid path, which would normally generate a 
404 error, is instead routed to the Index page (because the invalid path looks 
like page's activation context). See <a class="external-link" 
href="https://issues.apache.org/jira/browse/TAP5-2070";>Issue 
TAP5-2070</a>.</p></div></div></div>
             </div>
             <!-- /// Content End -->
           </div>

Modified: websites/production/tapestry/content/exploring-the-project.html
==============================================================================
--- websites/production/tapestry/content/exploring-the-project.html (original)
+++ websites/production/tapestry/content/exploring-the-project.html Sat Nov 26 
13:17:27 2022
@@ -32,10 +32,10 @@
   <link rel="apple-touch-icon-precomposed" 
href="/images/apache-tapestry-icon-57.png">
   <link rel="shortcut icon" href="/images/apache-tapestry-icon-32.png">
 
-  <link rel="stylesheet" 
href="https://fonts.googleapis.com/css2?family=Sarabun:ital,wght@0,400;0,700;1,400;1,700&display=swap";>
 
-  <link rel="stylesheet" 
href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css"; 
integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh"
 crossorigin="anonymous">
+  <link rel="stylesheet" href="/resources/bootstrap/bootstrap.min.css">
   <link rel="stylesheet" 
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.13.0/css/all.min.css";>
   <link rel="stylesheet" 
href="https://cdnjs.cloudflare.com/ajax/libs/prism/1.20.0/themes/prism.min.css";>
+  <link rel="stylesheet" href="/resources/fonts/fonts.css">
   <link rel="stylesheet" href="/styles/main.css">
 
   <script type="text/javascript">
@@ -46,7 +46,7 @@
 
   <script src="https://code.jquery.com/jquery-3.4.1.slim.min.js"; 
integrity="sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n"
 crossorigin="anonymous" defer></script>
   <script 
src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js"; 
integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo"
 crossorigin="anonymous" defer></script>
-  <script 
src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js"; 
integrity="sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6"
 crossorigin="anonymous" defer></script>
+  <script src="stylesheet" href="/resources/bootstrap/bootstrap.min.js">
   <script 
src="https://cdnjs.cloudflare.com/ajax/libs/prism/1.20.0/prism.min.js"; 
defer></script>
        <script 
src="https://cdnjs.cloudflare.com/ajax/libs/prism/1.20.0/plugins/autoloader/prism-autoloader.min.js";
 defer></script>
 
@@ -327,16 +327,15 @@ public class Index
 
 
 
-<span class="gliffy-container" id="gliffy-container-24346949-7738" 
data-fullwidth="913" data-ceoid="24188263" 
data-edit="${diagramEditLink.getLinkUrl()}" 
data-full="${diagramZoomLink.getLinkUrl()}" data-filename="Templates and 
Parameters">
+<span class="gliffy-container" id="gliffy-container-24346949-2995" 
data-fullwidth="913" data-size="S" data-ceoid="24188263" 
data-edit="${diagramEditLink.getLinkUrl()}" 
data-full="${diagramZoomLink.getLinkUrl()}" data-filename="Templates and 
Parameters">
 
-    <map id="gliffy-map-24346949-7601" name="gliffy-map-24346949-7601"></map>
+    <map id="gliffy-map-24346949-8954" name="gliffy-map-24346949-8954"></map>
 
-    <img class="gliffy-image gliffy-image-border" 
id="gliffy-image-24346949-7738" width="304" height="300" data-full-width="913" 
data-full-height="901" 
src="https://cwiki.apache.org/confluence/download/attachments/24188263/Templates%20and%20Parameters.png?version=2&amp;modificationDate=1371888025000&amp;api=v2";
 alt="Templates and Parameters" usemap="#gliffy-map-24346949-7601">
+    <img class="gliffy-image gliffy-image-border" 
id="gliffy-image-24346949-2995" width="304" height="300" data-full-width="913" 
data-full-height="901" 
src="https://cwiki.apache.org/confluence/download/attachments/24188263/Templates%20and%20Parameters.png?version=2&amp;modificationDate=1371888025000&amp;api=v2";
 alt="Templates and Parameters" usemap="#gliffy-map-24346949-8954">
 
-    <map class="gliffy-dynamic" id="gliffy-dynamic-map-24346949-7738" 
name="gliffy-dynamic-map-24346949-7738"></map>
+    <map class="gliffy-dynamic" id="gliffy-dynamic-map-24346949-2995" 
name="gliffy-dynamic-map-24346949-2995"></map>
 </span>
 
-
 </p><p>The interesting point here (and this is an advanced concept in 
Tapestry, one we'll return to later) is that we can pass a chunk of the 
Index.tml template to the Layout component as the <code>sidebar</code> 
parameter. That's what the tapestry:parameter namespace (the "p:" prefix) is 
for; the element name is matched against a parameter of the component and the 
entire block of the template is passed into the Layout component ... which 
decides where, inside <em>its</em> template, that block gets rendered.</p><div 
class="code panel pdl" style="border-width: 1px;"><div class="codeContent 
panelContent pdl">
 <pre><code class="language-xml">&lt;t:eventlink event="complete" class="btn 
btn-default"&gt;Complete&amp;raquo;&lt;/t:eventlink&gt;
 </code></pre>
@@ -346,7 +345,7 @@ public class Index
     return "A great day to learn Tapestry";
   }
 </code></pre>
-</div></div><p>Make sure you save changes; then click the refresh link in the 
web browser:</p><p><span class="confluence-embedded-file-wrapper 
confluence-embedded-manual-size"><img class="confluence-embedded-image" 
width="700" 
src="exploring-the-project.data/app-live-reload.png"></span></p><p>This is one 
of Tapestry's early <em>wow factor</em> features: changes to your component 
classes are picked up immediately (a feature we call Live Class Reloading). No 
restart. No re-deploy. Make the changes and see them <em>now</em>. Nothing 
should slow you down or get in the way of you getting your job done.</p><div 
class="confluence-information-macro 
confluence-information-macro-information"><span class="aui-icon aui-icon-small 
aui-iconfont-info confluence-information-macro-icon"></span><div 
class="confluence-information-macro-body"><p>If Live Class Reloading isn't 
working for you, check the Troubleshooting section at <a 
href="class-reloading.html">Class Reloading</a>.</p></div></div><p>But .
 .. what if you make a mistake? What if you got the name in the template wrong. 
Give it a try; in the template, change ${currentTime} to, say, ${currenTime}, 
and see what you get:</p><p><span class="confluence-embedded-file-wrapper 
confluence-embedded-manual-size"><img class="confluence-embedded-image" 
width="700" src="exploring-the-project.data/app-error-1.png"></span></p><p>This 
is Tapestry's exception report page. It's quite detailed. It clearly identifies 
what Tapestry was doing, and relates the problem to a specific line in the 
template, which is shown in context. Tapestry always expands out the entire 
stack of exceptions, because it is so common for exceptions to be thrown, 
caught, and re-thrown inside other exceptions. In fact, if we scroll down just 
a little bit, we see more detail about this exception, plus a little bit of 
help:</p><p><span class="confluence-embedded-file-wrapper 
confluence-embedded-manual-size"><img class="confluence-embedded-image" 
width="700" src="explori
 ng-the-project.data/app-error-2.png"></span></p><p>This is part of Tapestry's 
way: it not only spells out exactly what it was doing and what went wrong, but 
it even helps you find a solution; here it tells you the names of properties 
you could have used.</p><div class="confluence-information-macro 
confluence-information-macro-information"><span class="aui-icon aui-icon-small 
aui-iconfont-info confluence-information-macro-icon"></span><div 
class="confluence-information-macro-body"><p>This level of detail reflects that 
the application has been configured to run in <em>development mode</em> instead 
of <em>production mode</em>. In production mode, the exception report would 
simply be the top level exception message. However, most production 
applications go further and customize how Tapestry handles and reports 
exceptions.</p></div></div><p>Tapestry displays the stack trace of the deepest 
exception, along with lots of details about the run-time environment: details 
about the current requ
 est, the HttpSession (if one exists), and even a detailed list of all JVM 
system properties. Scroll down to see all this information.</p><p>Next: <a 
href="implementing-the-hi-lo-guessing-game.html">Implementing the Hi-Lo 
Guessing Game</a></p></div>
+</div></div><p>Make sure you save changes; then click the refresh link in the 
web browser:</p><p><span class="confluence-embedded-file-wrapper 
confluence-embedded-manual-size"><img class="confluence-embedded-image" 
draggable="false" width="700" 
src="exploring-the-project.data/app-live-reload.png"></span></p><p>This is one 
of Tapestry's early <em>wow factor</em> features: changes to your component 
classes are picked up immediately (a feature we call Live Class Reloading). No 
restart. No re-deploy. Make the changes and see them <em>now</em>. Nothing 
should slow you down or get in the way of you getting your job done.</p><div 
class="confluence-information-macro 
confluence-information-macro-information"><span class="aui-icon aui-icon-small 
aui-iconfont-info confluence-information-macro-icon"></span><div 
class="confluence-information-macro-body"><p>If Live Class Reloading isn't 
working for you, check the Troubleshooting section at <a 
href="class-reloading.html">Class Reloading</a>.</p></
 div></div><p>But ... what if you make a mistake? What if you got the name in 
the template wrong. Give it a try; in the template, change ${currentTime} to, 
say, ${currenTime}, and see what you get:</p><p><span 
class="confluence-embedded-file-wrapper confluence-embedded-manual-size"><img 
class="confluence-embedded-image" draggable="false" width="700" 
src="exploring-the-project.data/app-error-1.png"></span></p><p>This is 
Tapestry's exception report page. It's quite detailed. It clearly identifies 
what Tapestry was doing, and relates the problem to a specific line in the 
template, which is shown in context. Tapestry always expands out the entire 
stack of exceptions, because it is so common for exceptions to be thrown, 
caught, and re-thrown inside other exceptions. In fact, if we scroll down just 
a little bit, we see more detail about this exception, plus a little bit of 
help:</p><p><span class="confluence-embedded-file-wrapper 
confluence-embedded-manual-size"><img class="confluence-embe
 dded-image" draggable="false" width="700" 
src="exploring-the-project.data/app-error-2.png"></span></p><p>This is part of 
Tapestry's way: it not only spells out exactly what it was doing and what went 
wrong, but it even helps you find a solution; here it tells you the names of 
properties you could have used.</p><div class="confluence-information-macro 
confluence-information-macro-information"><span class="aui-icon aui-icon-small 
aui-iconfont-info confluence-information-macro-icon"></span><div 
class="confluence-information-macro-body"><p>This level of detail reflects that 
the application has been configured to run in <em>development mode</em> instead 
of <em>production mode</em>. In production mode, the exception report would 
simply be the top level exception message. However, most production 
applications go further and customize how Tapestry handles and reports 
exceptions.</p></div></div><p>Tapestry displays the stack trace of the deepest 
exception, along with lots of details about th
 e run-time environment: details about the current request, the HttpSession (if 
one exists), and even a detailed list of all JVM system properties. Scroll down 
to see all this information.</p><p>Next: <a 
href="implementing-the-hi-lo-guessing-game.html">Implementing the Hi-Lo 
Guessing Game</a></p></div>
             </div>
             <!-- /// Content End -->
           </div>

Modified: websites/production/tapestry/content/extending-the-if-component.html
==============================================================================
--- websites/production/tapestry/content/extending-the-if-component.html 
(original)
+++ websites/production/tapestry/content/extending-the-if-component.html Sat 
Nov 26 13:17:27 2022
@@ -32,10 +32,10 @@
   <link rel="apple-touch-icon-precomposed" 
href="/images/apache-tapestry-icon-57.png">
   <link rel="shortcut icon" href="/images/apache-tapestry-icon-32.png">
 
-  <link rel="stylesheet" 
href="https://fonts.googleapis.com/css2?family=Sarabun:ital,wght@0,400;0,700;1,400;1,700&display=swap";>
 
-  <link rel="stylesheet" 
href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css"; 
integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh"
 crossorigin="anonymous">
+  <link rel="stylesheet" href="/resources/bootstrap/bootstrap.min.css">
   <link rel="stylesheet" 
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.13.0/css/all.min.css";>
   <link rel="stylesheet" 
href="https://cdnjs.cloudflare.com/ajax/libs/prism/1.20.0/themes/prism.min.css";>
+  <link rel="stylesheet" href="/resources/fonts/fonts.css">
   <link rel="stylesheet" href="/styles/main.css">
 
   <script type="text/javascript">
@@ -46,7 +46,7 @@
 
   <script src="https://code.jquery.com/jquery-3.4.1.slim.min.js"; 
integrity="sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n"
 crossorigin="anonymous" defer></script>
   <script 
src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js"; 
integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo"
 crossorigin="anonymous" defer></script>
-  <script 
src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js"; 
integrity="sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6"
 crossorigin="anonymous" defer></script>
+  <script src="stylesheet" href="/resources/bootstrap/bootstrap.min.js">
   <script 
src="https://cdnjs.cloudflare.com/ajax/libs/prism/1.20.0/prism.min.js"; 
defer></script>
        <script 
src="https://cdnjs.cloudflare.com/ajax/libs/prism/1.20.0/plugins/autoloader/prism-autoloader.min.js";
 defer></script>
 

Modified: websites/production/tapestry/content/first.html
==============================================================================
--- websites/production/tapestry/content/first.html (original)
+++ websites/production/tapestry/content/first.html Sat Nov 26 13:17:27 2022
@@ -32,10 +32,10 @@
   <link rel="apple-touch-icon-precomposed" 
href="/images/apache-tapestry-icon-57.png">
   <link rel="shortcut icon" href="/images/apache-tapestry-icon-32.png">
 
-  <link rel="stylesheet" 
href="https://fonts.googleapis.com/css2?family=Sarabun:ital,wght@0,400;0,700;1,400;1,700&display=swap";>
 
-  <link rel="stylesheet" 
href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css"; 
integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh"
 crossorigin="anonymous">
+  <link rel="stylesheet" href="/resources/bootstrap/bootstrap.min.css">
   <link rel="stylesheet" 
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.13.0/css/all.min.css";>
   <link rel="stylesheet" 
href="https://cdnjs.cloudflare.com/ajax/libs/prism/1.20.0/themes/prism.min.css";>
+  <link rel="stylesheet" href="/resources/fonts/fonts.css">
   <link rel="stylesheet" href="/styles/main.css">
 
   <script type="text/javascript">
@@ -46,7 +46,7 @@
 
   <script src="https://code.jquery.com/jquery-3.4.1.slim.min.js"; 
integrity="sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n"
 crossorigin="anonymous" defer></script>
   <script 
src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js"; 
integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo"
 crossorigin="anonymous" defer></script>
-  <script 
src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js"; 
integrity="sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6"
 crossorigin="anonymous" defer></script>
+  <script src="stylesheet" href="/resources/bootstrap/bootstrap.min.js">
   <script 
src="https://cdnjs.cloudflare.com/ajax/libs/prism/1.20.0/prism.min.js"; 
defer></script>
        <script 
src="https://cdnjs.cloudflare.com/ajax/libs/prism/1.20.0/plugins/autoloader/prism-autoloader.min.js";
 defer></script>
 

Modified: websites/production/tapestry/content/footer.html
==============================================================================
--- websites/production/tapestry/content/footer.html (original)
+++ websites/production/tapestry/content/footer.html Sat Nov 26 13:17:27 2022
@@ -32,10 +32,10 @@
   <link rel="apple-touch-icon-precomposed" 
href="/images/apache-tapestry-icon-57.png">
   <link rel="shortcut icon" href="/images/apache-tapestry-icon-32.png">
 
-  <link rel="stylesheet" 
href="https://fonts.googleapis.com/css2?family=Sarabun:ital,wght@0,400;0,700;1,400;1,700&display=swap";>
 
-  <link rel="stylesheet" 
href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css"; 
integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh"
 crossorigin="anonymous">
+  <link rel="stylesheet" href="/resources/bootstrap/bootstrap.min.css">
   <link rel="stylesheet" 
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.13.0/css/all.min.css";>
   <link rel="stylesheet" 
href="https://cdnjs.cloudflare.com/ajax/libs/prism/1.20.0/themes/prism.min.css";>
+  <link rel="stylesheet" href="/resources/fonts/fonts.css">
   <link rel="stylesheet" href="/styles/main.css">
 
   <script type="text/javascript">
@@ -46,7 +46,7 @@
 
   <script src="https://code.jquery.com/jquery-3.4.1.slim.min.js"; 
integrity="sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n"
 crossorigin="anonymous" defer></script>
   <script 
src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js"; 
integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo"
 crossorigin="anonymous" defer></script>
-  <script 
src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js"; 
integrity="sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6"
 crossorigin="anonymous" defer></script>
+  <script src="stylesheet" href="/resources/bootstrap/bootstrap.min.js">
   <script 
src="https://cdnjs.cloudflare.com/ajax/libs/prism/1.20.0/prism.min.js"; 
defer></script>
        <script 
src="https://cdnjs.cloudflare.com/ajax/libs/prism/1.20.0/plugins/autoloader/prism-autoloader.min.js";
 defer></script>
 

Modified: websites/production/tapestry/content/footerv2.html
==============================================================================
--- websites/production/tapestry/content/footerv2.html (original)
+++ websites/production/tapestry/content/footerv2.html Sat Nov 26 13:17:27 2022
@@ -32,10 +32,10 @@
   <link rel="apple-touch-icon-precomposed" 
href="/images/apache-tapestry-icon-57.png">
   <link rel="shortcut icon" href="/images/apache-tapestry-icon-32.png">
 
-  <link rel="stylesheet" 
href="https://fonts.googleapis.com/css2?family=Sarabun:ital,wght@0,400;0,700;1,400;1,700&display=swap";>
 
-  <link rel="stylesheet" 
href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css"; 
integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh"
 crossorigin="anonymous">
+  <link rel="stylesheet" href="/resources/bootstrap/bootstrap.min.css">
   <link rel="stylesheet" 
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.13.0/css/all.min.css";>
   <link rel="stylesheet" 
href="https://cdnjs.cloudflare.com/ajax/libs/prism/1.20.0/themes/prism.min.css";>
+  <link rel="stylesheet" href="/resources/fonts/fonts.css">
   <link rel="stylesheet" href="/styles/main.css">
 
   <script type="text/javascript">
@@ -46,7 +46,7 @@
 
   <script src="https://code.jquery.com/jquery-3.4.1.slim.min.js"; 
integrity="sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n"
 crossorigin="anonymous" defer></script>
   <script 
src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js"; 
integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo"
 crossorigin="anonymous" defer></script>
-  <script 
src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js"; 
integrity="sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6"
 crossorigin="anonymous" defer></script>
+  <script src="stylesheet" href="/resources/bootstrap/bootstrap.min.js">
   <script 
src="https://cdnjs.cloudflare.com/ajax/libs/prism/1.20.0/prism.min.js"; 
defer></script>
        <script 
src="https://cdnjs.cloudflare.com/ajax/libs/prism/1.20.0/plugins/autoloader/prism-autoloader.min.js";
 defer></script>
 


Reply via email to