buildAirportDB.jsbuildConfigIcons.jsbuildIndexIcons.jscheckMdLinks.jsgenerateFavicon.jsgenerateIcon.jsgenerateSplash.jsmdToc.jsmdToHtml.jsmdToIndex.jsnasrCycle.jsppdigCompare.jsptableCatalog.jsselfTestRun.jstmlLint.jsThe app and documentation build process relies on several custom scripts written in various languages. The NodeJS scripts rely on the following npm packages, also recorded in the package.json in the project root:
Install them as follows:
npm install commander path png-to-ico puppeteer sharp xml2js
These packages may have other dependencies that depend on your operating system. Please see the package documentation.
The generateFavicon.js, generateIcon.js, and generateSplash.js scripts are intended to generate the icons, favicons, and splash screens for POH Performance app with very little effort. ALl the tweaking of each icon and splash screen layout is avoided. The scripts all use puppeteer to build a web page for the requested image and snapshot the result to create the requested image file. The image is programmatically adjusted to meet padding or other formatting constraints. The technique will allow other programmatic tweaking in the future.
buildAirportDB.jsBuilds the airport database for an app. See the Airport Database Reference. If no options are specified then all runway surfaces except water are included.
-D or --data <dir> (optional)NFDC/APT_BASE.csv, NFDC/APT_RWY.csv, NFDC/APT_RWY_END.csvEFF_DATE column.ourairportscom/airports.csvourairportscom/runways.csv./source/airportData is used.-d or --dirt (optional)-h or --hard (optional)-L or --log <file> (optional)<file. If omitted, log output is sent to the standard error output.-l <len> or --length <len> (optional)-o or --output <file><file. If omitted, the database is sent to the standard output.-t or --turf (optional)-v or --verbose (optional)-w or --water (optional)An airport database file in JSON format. See the Airport Database Reference.
buildConfigIcons.jsnode buildConfigIcons.js <configFile>
This script automatically builds the icons and splash screens used by the specified Cordova config.xml file. It expects XML comments of the form <!-- iconArgs="<args>" ---> or <!-- splashArgs="<args>" --->on the same line following any <icon> or <splash> elements defining an icon or splash screen in the config.xml file. It will record the src file name in the element and the args string in the comment and call generateIcon.js or generateSplash.js with the src filename and specified args string to generate the output.
The script also detects XML comments of the form <!-- globalIconArgs="<args>" ---> or <!-- globalSplashArgs="<args>" --->. These will add the specified argument string to any iconArgs or splashArgs comments associated with individual <icon> or <splash> elements. Here's an example of the icon and splash screen portion of a config.xml file:
<!-- globalIconArgs="-t1 C182 -t2 Performance" -->
<!-- globalSplashArgs="-t1 C182 -t2 Performance -i logoImage.png" -->
<!-- android properties -->
<platform name="android">
<icon src="res/icon/android/ldpi.png" density="ldpi" /> <!-- iconArgs="-s 36" -->
<icon src="res/icon/android/hdpi.png" density="hdpi" /> <!-- iconArgs="-s 72" -->
<splash src="res/screen/android/port-ldpi.png" density="port-ldpi" /> <!-- splashArgs="-w 200 -h 320 -p 28" -->
<splash src="res/screen/android/port-hdpi.png" density="port-hdpi" /> <!-- splashArgs="-w 480 -h 800 -p 28" -->
</platform>
<!-- IOS properties -->
<platform name="ios">
<icon src="res/icon/ios/icon-60.png" width="60" height="60" /> <!-- iconArgs="-s 60" -->
<icon src="res/icon/ios/icon-167.png" width="167" height="167" /> <!-- iconArgs="-s 167" -->
<!-- storyboard splash screens -->
<splash src="res/screen/ios/Default@2x~iphone~anyany.png" /> <!-- splashArgs="-w 1334 -h 1334 -p 28" -->
<splash src="res/screen/ios/Default@2x~ipad~anyany.png" /> <!-- splashArgs="-w 2732 -h 2732 -p 28" -->
</platform>
Calling generateIcon.js with this file will generate the following icons and splash screens:
res/icon/android/ldpi.png: A 36x36 iconres/icon/android/hdpi.png: A 72x72 iconres/screen/android/port-ldpi.png: A 200x320 splash screenres/screen/android/hdpi-ldpi.png: A 480x800 splash screenres/icon/android/icon-60: A 60x60 iconres/icon/android/icon-167: A 167x167 iconres/screen/android/Default@2x~iphone~anyany.png: A 1334x1334 splash screenres/screen/android/Default@2x~ipad~anyany.png: A 2732x27320 splash screenlogoImage.png image underneath. The words and image will be automatically scaled to maintain the specified padding area (28% of width or height). The image will be scaled to have the same width as the words.<configFile>config.xml file.buildIndexIcons.jsnode buildIndexIcons.js <indexFile>
This script automatically builds the icons and favicons used by the specified index.html file and any associated PWA manifest.json file. In the index.html file, it expects HTML comments of the form <!-- iconArgs="<args>" ---> or <!-- faviconArgs="<args>" ---> on the same line following any <link> elements with rel="icon" or rel="apple-touch-icon" in the index.html file. It will record the href file name in the element and the args string in the comment and call generateIcon.js or generateFavicon.js with the href filename and specified args string to generate the output.
The script also detects HTML comments of the form <!-- globalIconArgs="<args>" --->, which will add the specified argument string to any iconArgs or faviconArgs comments associated with individual <link> elements. Here's an example of the icon portion of an index.html file:
<!-- globalIconArgs="-t1 C182 -t2 Performance" -->
<!-- faviconGlobalArgs="-t1 C182 -t2 Performance" -->
<link rel="icon" href="buildStamp/image/favicon.ico" /> <!-- faviconArgs="" -->
<link rel="apple-touch-icon" href="buildStamp/image/icon-192.png" /> <!-- iconArgs="-s 192" -->
Calling generateIcon.js with this file will generate the following icons and splash screens:
buildStamp/image/favicon.ico: A favicon with the default sizesbuildStamp/image/icon-192.png: A 192x191 iconfavicon.ico will have the default sizes of 16, 32, 48, 64, 128, and 256.<indexFile>index.html file.checkMdLinks.jsnode checkMdLinks.js <mdFile>
This script checks that the links within the <mdFile> Markdown file point to valid target files and anchors. Links with a URL scheme, such as https: or mailto:, are external and are not checked. The script exits with status 1 if it reports any broken link or anchor.
<mdFile>generateFavicon.jsnode generateFavicon.js -o <file> -t1 <text1> [options]
This script generates an ICO favicon file containing multiple icon images of different sizes. The icon images can have one or two lines of text and a specified background color. The text will be automatically scaled so that the icon box has a specified padding. The default padding is 10% of the width. Each image is equal in width and height and may have rounded corners.
The default icon sizes are 16, 32, 48, 64, 128, and 256 pixels. For better readability, icons less than 64 pixels will only contain the first line.
-o <file> or --output <file> (required)-c <color> or --color <color> (optional)<color> string may be any CSS color string or a color range separated by a ':'. If omitted, the default string is "rgb(0,50,255):rgb(0,0,127)".-ff <string> or --fontFamily <string> (optional)-fr <number> or --fontRatio <number> (optional)-fw <string> or --fontFamily <string> (optional)-p <number> or --padding <number> (optional)-r <number> or --radius <number> (optional)-s <sizes> or --sizes <sizes> (optional)"16,32,48,64,128,256".-t1 <string> or --text1 <string> (required)-t2 <string> or --text2 <string> (optional)generateIcon.jsnode generateIcon.js -o <file> -t1 <text1> [options]
This script generates a PNG icon file. The icon can have one or two lines of text and a specified background color. The text will be automatically scaled so the icon box has a specified padding. The default padding is 10% of the width. Each image is equal in width and height and may have rounded corners.
-c <color> or --color <color> (optional)<color> string may be any CSS color string or a color range separated by a ':'. If omitted, the default string is "rgb(0,50,255):rgb(0,0,127)".-ff <string> or --fontFamily <string> (optional)-fr <number> or --fontRatio <number> (optional)-fw <string> or --fontFamily <string> (optional)-o <file> or --output <file> (required)-p <number> or --padding <number> (optional)-r <number> or --radius <number> (optional)-s <number> or --size <number> (optional)-t1 <string> or --text1 <string> (required)-t2 <string> or --text2 <string> (optional)generateSplash.jsnode generateSplash.js -o <file> -t1 <text1> -w <width> -h <height> [options]
This script generates a PNG splash screen file of the specified width and height in pixels. The icon can have one or two lines of text, an optional image, and a specified background color.
The text and image will be automatically scaled so the icon box has a specified padding. The image will have the same width as the largest line of text and both will be scaled to fit the area inside the padding.
-o <file> or --output <file> (required)-c <color> or --color <color> (optional)<color> string may be any CSS color string or a color range separated by a ':'. If omitted, the default string is "rgb(0,50,255):rgb(0,0,127)".-ff <string> or --fontFamily <string> (optional)-fr <number> or --fontRatio <number> (optional)-fw <string> or --fontFamily <string> (optional)-h <number> or --height <number> (required)-i <file> or --image <file> (optional)-p <number> or --padding <number> (optional)-t1 <string> or --text1 <string> (required)-t2 <string> or --text2 <string> (optional)-w <number> or --width <number> (required)mdToc.jsnode mdToc.js <mdFile>
This script generates a Table of Contents in the <mdFile> Markdown file. The script looks for the following marker comments to delineate where to insert the Table of Contents:
<!-- toc start -->: Marks the start of the insertion area<!-- toc end -->: Marks the end of the insertion areaThe first time the script is run, it inserts the generated TOC between the markers. When the file is updated and the script is re-run, it deletes the content between the markers before generating and inserting a new TOC.
By default, the script will index all headers including the heading for the Table of Contents. You can prevent indexing by adding `` at the end of the line containing a heading that should not be indexed. The script will also look for a comment of the form <!-- toc opts:[string] -->. The [string] contains a comma-separated list of heading levels to index. All other heading levels will be omitted from the TOC. For example, a line containing <!-- toc opts:h2,h3 --> will restrict indexing to only heading levels 2 and 3.
The index is a simple list containing a link to the specified section that contains the section name. Here's an example from this page:
<!-- toc opts:h2,h3 -->
# Scripts Reference <!-- index="Documents --><!-- omit from toc" -->
## Related documents
* [Development, Debugging, and Troubleshooting](development.md)
## Table of contents
<!-- toc start -->
<!-- toc end -->
---
## Introduction
...
<mdFile>mdToHtml.jsnode mdToHtml.js -i <inputMdFile> -o <outputHtmlFile> [options]
node mdToHtml.js [options] < <inputMdFile> > <outputMdFile>
This script converts a Markdown file to an HTML file. The input Markdown can use GFM format. The input Markdown file can be on stdin or it can be specified using -i <inputMdFile>. Similarly the output file can be sent to stdout or it can be specified using -o <outputMdFile>. If a -c <cssFile> argument is provided, then the specified CSS file will be linked in the output HTML.
-c <cssFile> (optional)-i <inputMdFile> (optional)stdin is used.-o <outputHtmlFile> (optional)stdout is used.mdToIndex.jsnode mdToIndex.js [options]
This script generates an alphabetic or category index of Markdown files in a specified directory to stdout. It searches all files with a .md extension in the directory. The -a option specifies that an alphabetic index is to be generated. Otherwise, a category and sub-category index is generated.
The alphabetic index is a simple list with links to the indexed files and anchors. The category and sub-category index is an index of ### (h3) elements with the category name and #### (h4) subcategories, which contain a list of all the indexed items underneath. The categories, subcategories, and indexed lists are sorted alphabetically.
The script searches each Markdown file for comments of the form:
# <headingText> `<!-- index="<category>:<subcategory>" -->`
The heading can be at any level, but the comment must follow on the same line. This will generate a list item with a link containing the <headingText> with the file and heading as the target and anchor. The list item will be sorted into the alphabetic list when requested or placed in the correct sub-category list when a categorized list is requested.
The script also searches each Markdown file for comments of the form:
<!-- target="<targetText>" index="<category>:<subcategory>" -->
This will create a link to this file using <targetText> for the link text. This will add the link to both the alphabetical and category indexes. The latter will be under the requested <category> and <subcategory>.
The script is intended to be used by a build environment to create a Markdown file containing an index of the indexed Markdown targets in a directory. The build environment must create the surrounding elements and then use this script to generate the index contents where desired.
-a (optional)-d <directory> or --directory <directory> (optional)-i <directory> or --index-directory <directory> (optional)-v or --verbose (optional)nasrCycle.jsnode tools/nasrCycle.js [<effDate>]
With no argument, this script prints the effective dates of the current and next 28 day NASR subscription cycles, e.g. 03_Sep_2026 01_Oct_2026. This DD_Mon_YYYY form is the one used in the NFDC subscription file names. The cycles are computed from a known cycle effective date, 03 Sep 2026.
With an <effDate> argument, it prints just that date in the DD_Mon_YYYY form. make db uses this to check that a downloaded zip's EFF_DATE is the requested cycle.
<effDate> (optional)EFF_DATE form, YYYY/MM/DD. Any other form is an error and exits with status 1.ppdigCompare.jsnode tools/ppdigCompare.js <appId> <modelId> <file.ppdig> [options]
node tools/ppdigCompare.js <appId> <modelId> --list [--sn <serial>] [--options <a,b>]
node tools/ppdigCompare.js <appId> <modelId> --dump <out.json> [--sn <serial>] [--options <a,b>]
This script compares a Digitizer project with a model's Ptables. It exports each of the project's graphs and tables with the ppdig command (see Extracting POH Data with an AI Agent), loads the app in headless Chrome, and sets the model up with acType.setAcData(). Then it interpolates every exported row in the Ptable named by the item's Data path, and lists the rows where the model's value differs from the project's. Values are compared in the project's units, the POH's, converting to and from the app's default units as the model does.
With --list, it instead lists the model's Ptables, each with its data path, title, inputs and output, to choose the data path for a project's items. See Choosing what to digitize.
With --dump, it instead writes the model's Ptables with their data as JSON: each data path with its title, its inputs' keys, units, limits and interpolation, its output's key, units and rounding, and its rows as [input, ..., output] in the table's own units. ppdig seed fills a project's items from it; see Re-verifying a model's data.
The script tests the built web image, so run make <appId>.web first. The make <appId>.ppdigCompare model=<modelId> file=<ppdig> args="<options>", make <appId>.ptables model=<modelId> args="<options>" and make <appId>.modelDump model=<modelId> out=<json> args="<options>" targets do both steps.
The script exits with status 0 when every row matches, and 1 when any row differs or fails, or an item can't be compared.
<appId>C310.<modelId>CT310R, with --sn, or an internal id, such as CT310R#76, which is set up at its first serial number.<file.ppdig>--name <item>--group <acData path>Ptable.--path <acData path>Ptable to compare with, such as tko.obstacleTbl, instead of the item's Data path.--sn <serial>--options <a,b>--set <key=value>Ptable input the item doesn't supply, in the app's default units, such as --set flaps=up. Repeat it for more inputs. An item's fixed inputs take its place.--tol <n>--max <n>--listPtables instead of comparing a project. A table is marked unread when build/tableCoverage/<appId>.json, from the last make <appId>.tableCoverage, says no calculation reads it.--dump <out.json>Ptables with their data to this file instead of comparing a project.PPDIG_COMPARE_PORT (optional)PUPPETEER_EXECUTABLE_PATH (optional)ptableCatalog.jsnode tools/ptableCatalog.js <outDir> <appId>...
This script writes the catalog of models and Ptables that the Digitizer offers as reference models. It loads each app in headless Chrome and, for every model as the app sets it up without options, lists each Ptable with its data path, title, input and output keys, units, limits and output rounding. An input matched by name, such as flaps, lists the names it takes. The catalog holds no table values: a reference model's numbers come from another POH.
It writes <outDir>/<appId>.json for each app and <outDir>/index.json, which lists the apps. The script reads the built web images, so run make <appId>.web first. make digCatalog does both steps for every aircraft app, writing to tools/digitizer/public/catalog, where the Digitizer's development server serves it; make pubDig makes it and publishes it with the Digitizer. The generated files aren't committed.
<outDir><appId>...C310 Baron.PTABLE_CATALOG_PORT (optional)PUPPETEER_EXECUTABLE_PATH (optional)selfTestRun.jsnode tools/selfTestRun.js <appId>
This script runs an app's built-in unit tests in headless Chrome and reports the results. It serves build/web on a local port, loads the app, opens the Test page with nav.popupPage('test') as the Settings page does (so the page renders and the Page views test can mount pages in it), and waits up to two minutes for the suite to finish. It then prints a JSON summary of the failing groups and any app assert() failures, followed by <appId>: PASS or <appId>: FAIL.
The script tests the built web image, so run make <appId>.web first. The make test and make <appId>.test targets do both steps.
The script exits with status 0 when every group passes, or when the app has no Test page. It exits with status 1 on any failing group, any assert() failure, a timeout, or a runner error.
<appId>C172. Defaults to C172.SELFTEST_PORT (optional)PUPPETEER_EXECUTABLE_PATH (optional)tmlLint.jsnode tools/tmlLint.js [--verbose] [--unused] [<appId> ...]
This script checks that every state variable a tml template references is one the app defines. A template names a state variable with {{id}}, {{id@}}, {{id prop=...}}, hasChanged=a,b or hasValue=a, and a reference to an undefined one only fails when the template renders, which the unit tests never do for a card behind an option or model gate. make lint runs this script for every app after eslint.
For each app the script follows the static imports from source/app/<appId>/buildStamp/app.js, collects the ids declared in every stateVarInfo array it can see, and checks the references in every template. Declared ids come from {id:'x'} object literals, SV.infoBasedOn('x', base), {...base, id:'x'}, arrays built with spreads, .concat(), .flat(), .reduce(), arrayFlatten(), arrayGenerate() and .map() over a literal array, functions such as stateVarInfo(pageId) with their call sites, and new UseValue(() => ...). An id with a units object also declares its unit siblings (id_lb, id_kg, ...) and a selector declares id_options. A declaration the script cannot expand is reported as unexpandable so the evaluator can be taught; it is never matched loosely.
A literal reference must be declared; the error lists the nearest declared ids. A reference with an unresolvable part, such as wb_${tankId}Fuel, must match a declared id as a pattern in at least one of the apps being linted, since a common template may be dead in an app that has no such page. A reference that is nothing but an expression, {{${sVarId}}}, cannot be checked and is only counted.
The script exits with status 0 when every reference resolves, and 1 otherwise.
<appId> ...Baron TBM. Defaults to every app with an app.js. Lint all apps together when checking a common file: a pattern reference is judged across the apps in the run.--verbose--unusedsv.<id> access or string literal refers to.