FAQ — Actual Information for Code Modules

Code Modules depends upon BBEdit’s include and variable syntax. There may be a way to replicate that functionality in another text editor, but I haven’t discovered it.
Modules have a number of advantages. They can return markup with data — like a list. Modules can use variables. Modules can return different markup for different pages using the same data.
This is what the templates/ subfolder of Markup modules is for. Different templates represent different uses of the module. Each template can call a different list, if a different subset or order of the items are required. Each template can determine the Type file that each item calls by overwriting variables used later in the chain. The different type files can return different markup using the same data contained in the item files.
BBEdit organizes projects using a Project file. Each Project file has a “Site Settings” pane where you can specify where BBEdit looks for includes and templates. My convention, which you are free to ignore, is to put mine in an /app/modules/ folder and to put the public files in /public/ (or in /dist/ if the public files are built).

Simple includes just pull in the contents of the child file. If that child file calls another include, then that is processed first. If variables have already been defined higher up in the chain, then they are passed down unaltered. But a simple include can’t define or overwrite variables on its own. If the simple include is in the top level HTML page file, then it will be replaced by the child file. Simple includes aren’t often used in top level HTML pages for this reason. Simple includes are not replaced when they do not appear in the top level HTML page. An example of a simple include is:

#bbinclude 'header.shtml'

Persistent includes are wrapped in HTML comment tags. They can define or overwrite variables. And they will not be replaced in a top level HTML page file. Instead, the content of the include will be placed between the two parts of an persistent include, each of which are wrapped in an HTML comment. The boilerplate #bbincludeoptions# variable just prevents a blank line from being inserted. An example of a persistent include is:

<!-- #bbinclude '/markup/faq/entry.shtml'
#bbincludeoptions#="inline=true"
#INDENT#	= "			"
-->
<!-- end bbinclude -->

Sometimes a whole module is overkill. If you want to replicate the simplicity of a traditional include, explore the high level Elements module. This one module can contain many traditional includes. One added benefit is that these includes can use the global variables or variables defined in the calling chain. The Elements module is a great place to tuck away a large hunk of markup, e.g. a form. By putting it in its own include, the calling file’s markup is made more readable.
The Blank module is a subfolder of the high level Markup module. Duplicate the Blank module and rename it appropriately: i.e. faq. Then go into the root entry.shtml file and change the #MODULE# variable value to the same value as the name of the module: i.e. faq. Now you have the skeleton of a Faq module, ready to alter to make it work for your purpose. By copying and renaming the Blank module, you’ve reduced the repetitive boilerplate that is an undeniable downside to the Code Modules system.
Each item is a persistent include that contains a number of variables. In the case of the Faq markup module responsible for this web page section, there’s a Question, an Answer, and an ID variable. Here, an optional comment variable is used; I use these comments to provide instructions to those who are filling in the values of the variables. The blank.shtml file — which you customize and update as you create and modify the module — contains this starting framework for new items. The blank.shtml file for the Faq module on this sample site is:

<!-- #bbinclude "/markup/#MODULE#/types/default.shtml"
#bbincludeoptions#="inline=true"
#QUESTION#		= ''
#ANSWER#		= ''
#ID#			= ''
#COMMENT#		= 'The ID must be unique from the IDs of the other Faq items.'
-->
<!-- end bbinclude -->

This is a no-op text file containing general notes relevant to the module. I record information about the “promises” of the module here by copying all the different calls (persistent includes, usually) to the module. The _notes.txt file for the Faq module on this sample site is:

Calls to the module go here.

<!-- #bbinclude "/markup/faq/entry.shtml"
#bbincludeoptions#="inline=true"
#INDENT#	= "			"
-->
<!-- end bbinclude -->

A more complex example is the _notes.txt file for the Nav module:

The Nav module returns the main navigation for each page header — template: default. 

It also can return an unordered ul list of links with sub sections for each dropdown (for 404) — template: div-links.

It can also return a div with a flat set of links (for sidebar; since only for sidebar, this one has an active class on the sidebar link) — template: ul-links.

TERTIARY-NAV-TYPE variable defines the form of the markup which comes from the Blog module when getting individual blog posts.

SIMPLE-TYPE is for simple nav links that aren't dropdown items.


<!-- #bbinclude "/nav/entry.shtml"
#bbincludeoptions#="inline=true"
#SIMPLE-TYPE#		= 'simple'
#TERTIARY-NAV-TYPE#	= 'dropdown-item'
#TEMPLATE#		= 'default'
#INDENT#		= '		'
-->
<!-- end bbinclude -->


<!-- #bbinclude "/nav/entry.shtml"
#bbincludeoptions#="inline=true"
#TEMPLATE#	= 'div-links'
#INDENT#	= '					'
-->
<!-- end bbinclude -->


<!-- #bbinclude "/nav/entry.shtml"
#bbincludeoptions#="inline=true"
#TEMPLATE#		= 'ul-links'
#SIMPLE-TYPE#		= 'dropdown-item-ul'
#TERTIARY-NAV-TYPE#	= 'dropdown-item-ul'
#INDENT#		= '				'
-->
<!-- end bbinclude -->



<!-- #bbinclude "/nav/entry.shtml"
#bbincludeoptions#="inline=true"
#TEMPLATE#	= 'dropdown-single'
#TYPE#		= '#SIMPLE-TYPE#'
#TEXT#		= '#NAV-NAME#'
#URL#		= '#URL#'
-->
<!-- end bbinclude -->


<!-- #bbinclude "/nav/entry.shtml"
#bbincludeoptions#="inline=true"
#TEMPLATE#		= 'div-links'
#SIMPLE-TYPE#		= 'simple-bare'
#TERTIARY-NAV-TYPE#	= 'simple-bare'
#INDENT#		= '					'
-->
<!-- end bbinclude -->

When you’re creating a module, the test is the correctness of the markup that it outputs.

  • If the top or bottom of the markup is wrong, you look in templates/.
  • If the order of the items is wrong, you look in lists/.
  • If the individual items themselves are wrong, you look in items/.
  • If the markup of each item is malformed, then you look in the types/.
  • If a variable name (e.g. #URL#) slips its way into the final markup, then it hasn’t been defined and you fix that.

More interesting is how you refactor a module while retaining confidence that you haven’t broken it. For this, I copy the final page into a new file. Then I use BBEdit’s command ”Seach ⟶ Find Differences ⟶ Compare Two Front Windows” to compare the new module output to the old. If the new output is identical to the old, or only different in desired ways, then it isn’t broken. Since each module is encapsulated, so long as the module’s “promises” are kept and the markup doesn’t change, the refactor has been successful.