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

bdemers pushed a commit to branch related-links
in repository https://gitbox.apache.org/repos/asf/shiro-site.git

commit e1c65b5d3b99060e9744a3dea1768c042e160c44
Author: Brian Demers <[email protected]>
AuthorDate: Wed Oct 20 17:26:01 2021 -0400

    Add related links to page template.
    
    If a `related` tag exists in page's front mater the related links 
navigation will be added to the page.
    
    NOTE: any linked pages should have a `description` tag.
---
 jbake/assets/css/base.css                          |  20 ++
 jbake/content/10-minute-tutorial.adoc              |   1 +
 jbake/content/get-started.md                       |   1 +
 jbake/content/issues.adoc                          |   1 +
 permissions.md => jbake/content/permissions.adoc   | 214 ++++++++++++---------
 .../content/securitymanager.adoc                   |  85 ++++----
 jbake/templates/page.ftl                           |  25 +++
 7 files changed, 210 insertions(+), 137 deletions(-)

diff --git a/jbake/assets/css/base.css b/jbake/assets/css/base.css
index 1b470f7..ba2f896 100644
--- a/jbake/assets/css/base.css
+++ b/jbake/assets/css/base.css
@@ -192,4 +192,24 @@ ul.pagination {
 
 .news-title, .popular-guides {
   font-size: 1em;
+}
+
+div.related-content {
+  border-style: solid;
+  border-width: 2px;
+  border-color: navy;
+  padding: 5px;
+  margin-left: 20px;
+  margin-bottom: 20px;
+  width: 275px;
+  float: right;
+  clear: both;
+}
+
+.related-content h2 {
+  font-size: 34px;
+}
+
+.related-content .read-more {
+  font-size: 11px;
 }
\ No newline at end of file
diff --git a/jbake/content/10-minute-tutorial.adoc 
b/jbake/content/10-minute-tutorial.adoc
index c116dcf..a23a44c 100644
--- a/jbake/content/10-minute-tutorial.adoc
+++ b/jbake/content/10-minute-tutorial.adoc
@@ -4,6 +4,7 @@ Brian Demers
 :jbake-type: page
 :jbake-status: published
 :jbake-tags: documentation, manual
+:jbake-description: Try Apache Shiro for yourself in under 10 minutes.
 :idprefix:
 
 == Introduction
diff --git a/jbake/content/get-started.md b/jbake/content/get-started.md
index 6eb0b63..ff4ccc0 100644
--- a/jbake/content/get-started.md
+++ b/jbake/content/get-started.md
@@ -4,6 +4,7 @@ author=Les Hazelwood
 type=page
 tags=documentation, manual
 status=published
+description=Resources, guides and tutorials for new Shiro users.
 ~~~~~~
 
 Apache Shiro focuses on ease-of-use, so you can rely on secure, stable 
authentication, authorization, cryptography, and session management. With 
Shiro’s easy-to-understand API, you can quickly and easily secure any 
application. Get started!
diff --git a/jbake/content/issues.adoc b/jbake/content/issues.adoc
index 5b3badd..ed3d64a 100644
--- a/jbake/content/issues.adoc
+++ b/jbake/content/issues.adoc
@@ -4,6 +4,7 @@
 :jbake-tags: documentation, support, community, issues, bugs
 :idprefix:
 :icons: font
+:jbake-description: some sort of description
 
 Apache Shiro uses Atlassian Jira for tracking tasks, feature requests, bugs, 
and other issues related to the project development.
 
diff --git a/permissions.md b/jbake/content/permissions.adoc
similarity index 79%
rename from permissions.md
rename to jbake/content/permissions.adoc
index ed8071c..cda97cd 100644
--- a/permissions.md
+++ b/jbake/content/permissions.adoc
@@ -1,15 +1,22 @@
-# <a 
name="Permissions-UnderstandingPermissionsinApacheShiro"></a>Understanding 
Permissions in Apache Shiro
-
+= Understanding Permissions in Apache Shiro
+:jbake-type: page
+:jbake-status: published
+:jbake-tags: permissions, authorization
+:jbake-related: { "links": ["java-authorization-guide.html", 
"webapp-tutorial.html", "get-started.html", "10-minute-tutorial.html"] }
+:idprefix:
+~~~~~~
+
+[#Permissions-UnderstandingPermissionsinApacheShiro]
 Shiro defines a Permission as a statement that defines an explicit behavior or 
action. It is a statement of raw functionality in an application and nothing 
more. Permissions are the lowest-level constructs in security polices, and they 
explicitly define only "what" the application can do.
 
 They do _not_ at all describe "who" is able to perform the action(s).
 
 Some examples of permissions:
 
-*   Open a file
-*   View the '/user/list' web page
-*   Print documents
-*   Delete the 'jsmith' user
+* Open a file
+* View the '/user/list' web page
+* Print documents
+* Delete the 'jsmith' user
 
 Defining "who" (users) is allowed to do "what" (permissions) is an exercise of 
assigning permissions to users in some way. This is always done by the 
application's data model and can vary greatly across applications.
 
@@ -17,214 +24,230 @@ For example, permissions can be grouped in a Role and 
that Role could be associa
 
 There are many variations for how permissions could be granted to users - the 
application determines how to model this based on the application requirements.
 
-<a name="Permissions-WildcardPermissions"></a>
-##Wildcard Permissions
+== Wildcard Permissions
 
 The above examples of permissions, "Open a file", "View the 'user/list' web 
page", etc are all valid permission statements. However, it would be very 
difficult computationally to interpret those natural language strings and 
determine if a user is allowed to perform that behavior or not.
 
 So to enable easy-to-process yet still readable permission statements, Shiro 
provides powerful and intuitive permission syntax we refer to as the 
WildcardPermission.
 
-<a name="Permissions-SimpleUsage"></a>
-###Simple Usage
+=== Simple Usage
 
 Let's say you want to protect access to your company's printers such that some 
people can print to particular printers, while others can query what jobs are 
currently in the queue.
 
 An extremely simple approach would be to grant the user a "queryPrinter" 
permission. Then you could check to see if the user has the queryPrinter 
permission by calling:
 
-``` java
+[source,java]
+----
 subject.isPermitted("queryPrinter")
-```
+
+----
 
 This is (mostly) equivalent to
 
-``` java
+[source,java]
+----
 subject.isPermitted( new WildcardPermission("queryPrinter") )
-```
+
+----
 
 but more on that later.
 
-The simple permission string may work for simple applications, but it requires 
you to have permissions like "printPrinter", "queryPrinter", "managePrinter", 
etc. You can also grant a user "*" permissions using the wildcard character 
(giving this permission construct its name), which means they have **_all_** 
permissions across _the entire application_.
+The simple permission string may work for simple applications, but it requires 
you to have permissions like "printPrinter", "queryPrinter", "managePrinter", 
etc. You can also grant a user &quot;*&quot; permissions using the wildcard 
character (giving this permission construct its name), which means they have 
*_all_* permissions across _the entire application_.
 
 But using this approach there's no way to just say a user has "all printer 
permissions". For this reason, Wildcard Permissions supports multiple _levels_ 
of permissioning.
 
-<a name="Permissions-MultipleParts"></a>
-###Multiple Parts
+=== Multiple Parts
 
 Wildcard Permissions support the concept of multiple _levels_ or _parts_. For 
example, you could restructure the previous simple example by granting a user 
the permission
 
-``` ini
+[source,ini]
+----
 printer:query
-```
+----
 
 The colon in this example is a special character used to delimit the next part 
in the permission string.
 
 In this example, the first part is the domain that is being operated on 
(`printer`) and the second part is the action (`query`) being performed. The 
other above examples would be changed to:
 
-``` ini
+[source,ini]
+----
 printer:print
 printer:manage
-```
+----
 
 There is no limit to the number of parts that can be used, so it is up to your 
imagination in terms of ways that this could be used in your application.
 
-<a name="Permissions-MultipleValues"></a>
-####Multiple Values
+==== Multiple Values
 
 Each part can contain multiple values. So instead of granting the user both 
the "printer:print" and "printer:query" permissions, you could simply grant 
them one:
 
-``` ini
+[source,ini]
+----
 printer:print,query
-```
+----
 
 which gives them the ability to `print` and `query` printers. And since they 
are granted both those actions, you could check to see if the user has the 
ability to query printers by calling:
 
-``` java
+[source,java]
+----
 subject.isPermitted("printer:query")
-```
+----
 
 which would return `true`
 
-<a name="Permissions-AllValues"></a>
-####All Values
+==== All Values
 
 What if you wanted to grant a user _all_ values in a particular part? It would 
be more convenient to do this than to have to manually list every value. Again, 
based on the wildcard character, we can do this. If the `printer` domain had 3 
possible actions (`query`, `print`, and `manage`), this:
 
-``` ini
+[source,ini]
+----
 printer:query,print,manage
-```
+----
 
 simply becomes this:
 
-``` ini
+[source,ini]
+----
 printer:*
-```
+----
 
 Then, _any_ permission check for "printer:XXX" will return `true`. Using the 
wildcard in this way scales better than explicitly listing actions since, if 
you added a new action to the application later, you don't need to update the 
permissions that use the wildcard character in that part.
 
 Finally, it is also possible to use the wildcard token in any part of a 
wildcard permission string. For example, if you wanted to grant a user the 
"view" action across _all_ domains (not just printers), you could grant this:
 
-``` ini
+[source,ini]
+----
 *:view
-```
+----
 
 Then any permission check for "foo:view" would return `true`
 
-<a name="Permissions-InstanceLevelAccessControl"></a>
-###Instance-Level Access Control
+=== Instance-Level Access Control
 
 Another common usage of wildcard permissions is to model instance-level Access 
Control Lists. In this scenario you use three parts - the first is the 
_domain_, the second is the _action_(s), and the third is the instance(s) being 
acted upon.
 
 So for example you could have
 
-``` ini
+[source,ini]
+----
 printer:query:lp7200
 printer:print:epsoncolor
-```
+----
 
 The first defines the behavior to `query` the `printer` with the ID `lp7200`. 
The second permission defines the behavior to `print` to the `printer` with ID 
`epsoncolor`. If you grant these permissions to users, then they can perform 
specific behavior on _specific instances_. Then you can do a check in code:
 
-``` java
+[source,java]
+----
 if ( SecurityUtils.getSubject().isPermitted("printer:query:lp7200") {
     // Return the current jobs on printer lp7200 }
 }
-```
+----
 
 This is an extremely powerful way to express permissions. But again, having to 
define multiple instance IDs for all printers does not scale well, particularly 
when new printers are added to the system. You can instead use a wildcard:
 
-``` ini
+[source,ini]
+----
 printer:print:*
-```
+----
 
 This does scale, because it covers any new printers as well. You could even 
allow access to all actions on all printers:
 
-``` ini
+[source,ini]
+----
 printer:*:*
-```
+----
 
 or all actions on a single printer:
 
-``` ini
+[source,ini]
+----
 printer:*:lp7200
-```
+----
 
 or even specific actions:
 
-``` ini
+[source,ini]
+----
 printer:query,print:lp7200
-```
+----
 
 The '*' wildcard and ',' sub-part separator can be used in any part of the 
permission.
 
-<a name="Permissions-MissingParts"></a>
-####Missing Parts
+==== Missing Parts
 
 One final thing to note about permission assignments: missing parts imply that 
the user has access to all values corresponding to that part. In other words,
 
-``` ini
+[source,ini]
+----
 printer:print
-```
+----
 
 is equivalent to
 
-``` ini
+[source,ini]
+----
 printer:print:*
-```
+----
 
 and
 
-``` ini
+[source,ini]
+----
 printer
-```
+----
 
 is equivalent to
 
-``` ini
+[source,ini]
+----
 printer:*:*
-```
+----
 
 However, you can only leave off parts from the _end_ of the string, so this:
 
-``` ini
+[source,ini]
+----
 printer:lp7200
-```
+----
 
-is **_not_** equivalent to
+is *_not_* equivalent to
 
-``` ini
+[source,ini]
+----
 printer:*:lp7200
-```
+----
 
-<a name="Permissions-CheckingPermissions"></a>
-##Checking Permissions
+== Checking Permissions
 
-While permission assignments use the wildcard construct quite a bit 
("printer:print:*" = print to any printer) for convenience and scalability, 
permission **checks** at runtime should _always_ be based on the most specific 
permission string possible.
+While permission assignments use the wildcard construct quite a bit 
("printer:print:*" = print to any printer) for convenience and scalability, 
permission *checks* at runtime should _always_ be based on the most specific 
permission string possible.
 
-For example, if the user had a UI and they wanted to print a document to the 
`lp7200` printer, you **should** check if the user is permitted to do so by 
executing this code:
+For example, if the user had a UI and they wanted to print a document to the 
`lp7200` printer, you *should* check if the user is permitted to do so by 
executing this code:
 
-``` java
+[source,java]
+----
 if ( SecurityUtils.getSubject().isPermitted("printer:print:lp7200") ) {
     //print the document to the lp7200 printer }
 }
-```
+----
 
 That check is very specific and explicitly reflects what the user is 
attempting to do at that moment in time.
 
 The following however is much less ideal for a runtime check:
 
-```java
+[source,java]
+----
 if ( SecurityUtils.getSubject().isPermitted("printer:print") ) {
     //print the document }
 }
-```
+----
 
-Why? Because the second example says "You must be able to print to **any** 
printer for the following code block to execute". But remember that 
"printer:print" is equivalent to "printer:print:*"!
+Why? Because the second example says "You must be able to print to *any* 
printer for the following code block to execute". But remember that 
"printer:print" is equivalent to "printer:print:*"!
 
-Therefore, this is an incorrect check. What if the current user does not have 
the ability to print to any printer, but they **do** have the ability to print 
to say, the `lp7200` and `epsoncolor` printers. Then the 2nd example above 
would never allow them to print to the `lp7200` printer even though they have 
been granted that ability!
+Therefore, this is an incorrect check. What if the current user does not have 
the ability to print to any printer, but they *do* have the ability to print to 
say, the `lp7200` and `epsoncolor` printers. Then the 2nd example above would 
never allow them to print to the `lp7200` printer even though they have been 
granted that ability!
 
 So the rule of thumb is to use the most specific permission string possible 
when performing permission checks. Of course, the 2nd block above might be a 
valid check somewhere else in the application if you really did only want to 
execute the code block if the user was allowed to print to any printer 
(suspect, but possible). Your application will determine what checks make 
sense, but in general, the more specific, the better.
 
-<a name="Permissions-Implication%2CnotEquality"></a>
-##Implication, not Equality
+== Implication, not Equality
 
 Why is it that runtime permission checks should be as specific as possible, 
but permission assignments can be a little more generic? It is because the 
permission checks are evaluated by _implication_ logic - not equality checks.
 
@@ -232,51 +255,52 @@ That is, if a user is assigned the `user:*` permission, 
this _implies_ that the
 
 To support implication rules, all permissions are translated in to object 
instances that implement the `org.apache.shiro.authz.Permission` interface. 
This is so that implication logic can be executed at runtime and that 
implication logic is often more complex than a simple string equality check. 
All of the wildcard behavior described in this document is actually made 
possible by the `org.apache.shiro.authz.permission.WildcardPermission` class 
implementation. Here are some more wildcard p [...]
 
-``` ini
+[source,ini]
+----
 user:*
-```
+----
 
 _implies_ the ability to also delete a user:
 
-``` ini
+[source,ini]
+----
 user:delete
-```
+----
 
 Similarly,
 
-``` ini
+[source,ini]
+----
 user:*:12345
-```
+----
 
 _implies_ the ability to also update user account with ID 12345:
 
-``` ini
+[source,ini]
+----
 user:update:12345
-```
+----
 
 and
 
-``` ini
+[source,ini]
+----
 printer
-```
+----
 
 _implies_ the ability to print to any printer
 
-``` ini
+[source,ini]
+----
 printer:print
-```
+----
 
-<a name="Permissions-PerformanceConsiderations"></a>
-##Performance Considerations
+== Performance Considerations
 
 Permission checks are more complex than a simple equals comparison, so runtime 
implication logic must execute for each assigned Permission. When using 
permission strings like the ones shown above, you're implicitly using Shiro's 
default `WildcardPermission` which executes the necessary implication logic.
 
 Shiro's default behavior for Realm implementations is that, for every 
permission check (for example, a call to `subject.isPermitted`), _all_ of the 
permissions assigned to that user (in their Groups, Roles, or directly assigned 
to them) need to be checked individually for implication. Shiro 'short 
circuits' this process by returning immediately after the first successful 
check occurs to increase performance, but it is not a silver bullet.
 
-This is usually extremely fast when users, roles and permissions are cached in 
memory when using a proper [CacheManager](cachemanager.html "CacheManager"), 
which Shiro does support for Realm implementations. Just know that with this 
default behavior, as the number of permissions assigned to a user or their 
roles or groups increase, the time to perform the check will necessarily 
increase.
+This is usually extremely fast when users, roles and permissions are cached in 
memory when using a proper link:cachemanager.html[CacheManager], which Shiro 
does support for Realm implementations. Just know that with this default 
behavior, as the number of permissions assigned to a user or their roles or 
groups increase, the time to perform the check will necessarily increase.
 
 If a Realm implementor has a more efficient way of checking permissions and 
performing this implication logic, especially if based on the applicaton's data 
model, they should implement that as part of their Realm isPermitted* method 
implementations. The default Realm/WildcardPermission support exists to cover 
80-90% of most use cases, but it might not be the best solution for 
applications that have massive amounts of permissions to store and/or check at 
runtime.
-
-#lendAHandDoc()
-
-<input type="hidden" id="ghEditPage" value="permissions.md"></input>
diff --git a/securitymanager.md.vtl b/jbake/content/securitymanager.adoc
similarity index 53%
rename from securitymanager.md.vtl
rename to jbake/content/securitymanager.adoc
index f898df8..193d97b 100644
--- a/securitymanager.md.vtl
+++ b/jbake/content/securitymanager.adoc
@@ -1,63 +1,68 @@
-#parse("templates/includes.vtl")
+= Understanding the SecurityManager in Apache Shiro
+:jbake-type: page
+:jbake-status: published
+:jbake-tags: permissions, authorization, authentication, securitymanager
+:idprefix:
 
-<a name="SecurityManager-UnderstandingtheSecurityManagerinApacheShiro"></a>
-Understanding the SecurityManager in Apache Shiro
-=================================================
-
-The 
[SecurityManager](static/current/apidocs/org/apache/shiro/mgt/SecurityManager.html)
 lies at the heart of Shiro's architecture. While the [Subject](subject.html 
"Subject") represents security functionality and state for a _single_ 
application user, the `SecurityManager` performs security operations and 
manages state for _all_ application users.
+[#SecurityManager-UnderstandingtheSecurityManagerinApacheShiro]
+The 
link:static/current/apidocs/org/apache/shiro/mgt/SecurityManager.html[SecurityManager]
 lies at the heart of Shiro's architecture. While the 
link:subject.html[Subject] represents security functionality and state for a 
_single_ application user, the `SecurityManager` performs security operations 
and manages state for _all_ application users.
 
 Because Shiro's API encourages a `Subject`-centric programming approach, most 
application developers will rarely, if ever, interact with the 
`SecurityManager` directly (framework developers however might sometimes find 
it useful). Even so, it is still important to know how the `SecurityManager` 
functions, especially when configuring one for an application.
 
-<a name="SecurityManager-Design"></a>
-Design
-------
+[#SecurityManager-Design]
+== Design
 
 As stated previously, the application's `SecurityManager` performs security 
operations and manages state for _all_ application users. In Shiro's default 
`SecurityManager` implementations, this includes:
 
-*   Authentication
-*   Authorization
-*   Session Management
-*   Cache Management
-*   [Realm](realm.html "Realm") coordination
-*   Event propagation
-*   "Remember Me" Services
-*   Subject creation
-*   Logout
-and more.
+* Authentication
+* Authorization
+* Session Management
+* Cache Management
+* link:realm.html[Realm] coordination
+* Event propagation
+* "Remember Me" Services
+* Subject creation
+* Logout
+* and more!
 
 But this is a lot of functionality to try to manage in a single component. 
And, making these things flexible and customizable would be very difficult if 
everything were lumped into a single implementation class.
 
 To simplify configuration and enable flexible configuration/pluggability, 
Shiro's implementations are all highly modular in design - so modular in fact, 
that the SecurityManager implementation (and its class-hierarchy) does not do 
much at all. Instead, the `SecurityManager` implementations mostly act as a 
lightweight 'container' component, delegating almost all behavior to 
nested/wrapped components.
 
-<a name="SecurityManager-Modularity"></a>
-#[[###Modularity]]#
+[#SecurityManager-Modularity]
+### Modularity
 
 To simplify the `SecurityManager` implementation complexity and allow for 
pluggable behavior, the Shiro `SecurityManager` implementations delegate almost 
all logic to a nested set of modular components that actually perform the 
necessary functionality. While the components actually execute the logic, the 
`SecurityManager` implementation knows how and when to coordinate the 
components for the correct behavior.
 
 The nested components that the `SecurityManager` coordinates and delegates to 
are:
 
-*   Authenticator (`org.apache.shiro.authc.Authenticator`)
-*   Authorizer (`org.apache.shiro.authz.Authorizer`)
-*   SessionManager (`org.apache.shiro.session.mgt.SessionManager`)
-*   [CacheManager](cachemanager.html "CacheManager") 
(`org.apache.shiro.cache.CacheManager`)
-*   RememberMeManager (`org.apache.shiro.mgt.RememberMeManager`)
-*   SubjectFactory(`org.apache.shiro.mgt.SubjectFactory`)
+* Authenticator (`org.apache.shiro.authc.Authenticator`)
+* Authorizer (`org.apache.shiro.authz.Authorizer`)
+* SessionManager (`org.apache.shiro.session.mgt.SessionManager`)
+* link:cachemanager.html[CacheManager] (`org.apache.shiro.cache.CacheManager`)
+* RememberMeManager (`org.apache.shiro.mgt.RememberMeManager`)
+* SubjectFactory(`org.apache.shiro.mgt.SubjectFactory`)
 
 The `SecurityManager` implementations and are also JavaBeans compatible, which 
allows you (or a configuration mechanism) to easily customize the pluggable 
components via standard JavaBeans accessor/mutator methods (get*/set*). This 
means the Shiro's architectural modularity can translate into very easy 
configuration for custom behavior.
 
-#tip('Easy Configuration', 'Because of JavaBeans compatibility, it is very 
easy to configure the <code>SecurityManager</code> with custom components via 
any mechanism that supports JavaBeans-style configuration, such as <a 
href="spring.html" title="Spring">Spring</a>, Guice, JBoss, etc.')
+[TIP]
+.Easy Configuration
+====
+Because of JavaBeans compatibility, it is very easy to configure the 
`SecurityManager` with custom components via any mechanism that supports 
JavaBeans-style configuration, such as link:spring.html[Spring], Guice, JBoss, 
etc.
+====
 
-<a name="SecurityManager-ProgrammaticConfiguration"></a>
-#[[###Programmatic Configuration]]#
+[#SecurityManager-ProgrammaticConfiguration]
+### Programmatic Configuration
 
 The absolute simplest way to create a SecurityManager and make it available to 
the application is to create a `org.apache.shiro.mgt.DefaultSecurityManager` 
and wire it up in code:
 
-``` java
+[source,java]
+----
 Realm realm = //instantiate or acquire a Realm instance.  We'll discuss Realms 
later. 
 SecurityManager securityManager = new DefaultSecurityManager(realm);
 //Make the SecurityManager instance available to the entire application: 
 SecurityUtils.setSecurityManager(securityManager);
-```
+----
 
 Surprisingly, after only 3 lines of code, you now have a fully functional 
Shiro environment suitable for most applications. How easy was that!?
 
@@ -65,17 +70,13 @@ You could additionally call any of the `SecurityManager` 
instance's setter metho
 
 But, as simple as programmatic customization is, these 3 lines of code do not 
represent the ideal configuration for most real world applications. There are a 
few reasons why programmatic configuration may not be suitable for your 
application:
 
-1.  It requires you to know about and instantiate a direct implementation. It 
would be nicer if you didn't have to know about concrete implementations and 
where to find them.
-2.  The `SecurityUtils.setSecurityManager` method call makes the instantiated 
`SecurityManager` instance a VM static singleton, which, while fine for many 
applications, would cause problems if more than one Shiro-enabled application 
was running on the same JVM. It could be better if the instance was an 
application singleton, but not a static memory reference.
-3.  It requires you to recompile your application every time you want to make 
a Shiro configuration change.
+. It requires you to know about and instantiate a direct implementation. It 
would be nicer if you didn't have to know about concrete implementations and 
where to find them.
+. The `SecurityUtils.setSecurityManager` method call makes the instantiated 
`SecurityManager` instance a VM static singleton, which, while fine for many 
applications, would cause problems if more than one Shiro-enabled application 
was running on the same JVM. It could be better if the instance was an 
application singleton, but not a static memory reference.
+. It requires you to recompile your application every time you want to make a 
Shiro configuration change.
 
 Most applications instead benefit from text-based configuration that could be 
modified independently of source code and even make things easier to understand 
for those not intimately familiar with Shiro's APIs.
 
-<a name="SecurityManager-TextConfiguration"></a>
-#[[###Text Configuration]]#
-
-Shiro provides a simple INI-based [configuration](configuration.html 
"Configuration") that can be used out of the box, but any other 
JavaBeans-compatible mechanism can be used as well. For example, Shiro has 
excellent [Spring support](spring.html "Spring") too. Other similar frameworks 
(Guice, JBoss, etc) could also be used.
-
-#lendAHandDoc()
+[#SecurityManager-TextConfiguration]
+=== Text Configuration
 
-<input type="hidden" id="ghEditPage" value="securitymanager.md.vtl"></input>
+Shiro provides a simple INI-based link:configuration.html[configuration] that 
can be used out of the box, but any other JavaBeans-compatible mechanism can be 
used as well. For example, Shiro has excellent link:spring.html[Spring support] 
too. Other similar frameworks (Guice, JBoss, etc) could also be used.
diff --git a/jbake/templates/page.ftl b/jbake/templates/page.ftl
index 3b683f9..868fabc 100644
--- a/jbake/templates/page.ftl
+++ b/jbake/templates/page.ftl
@@ -6,6 +6,31 @@
        </div>
        <#else></#if>
 
+       <#if (content.related)??>
+               <div class="related-content">
+                       <h2>Related Content</h2>
+                       <#list content.related.links>
+                               <#items as link>
+                                       <#list db.getDocumentByUri(link)>
+                                               <#items as linkedDoc>
+                                                       <#if 
(linkedDoc.title)??>
+                                                               <h3 
class="title"><a href="${link}">${linkedDoc.title}</a></h3>
+                                                               <p 
class="description">
+                                                               <#if 
(linkedDoc.description)??>
+                                                                       
${linkedDoc.description}
+                                                               </#if>
+                                                               </p>
+                                                               <p>
+                                                                       <span 
class="read-more"><a href="${link}">Read More &gt;&gt;</a></span>
+                                                               </p>
+                                                       </#if>
+                                               </#items>
+                                       </#list>
+                               </#items>
+                       </#list>
+               </div>
+       </#if>
+
        <@content.body?interpret />
 
        <hr />

Reply via email to