Codebook
Codebook allows you to execute code that is also shown to the user embedded in an HTML page.
Codebook allows you to execute code that is also shown to the user embedded in an HTML page.
Codebook needs two parts to work: the code on the page that should be run, and the JavaScript to run it (see Methods).
The code on the page comes in blocks, which should have a class of js-codebook__block
. These blocks can belong to sets, which can be run independently.
On this page, code blocks are marked by a 📖.
By default, a block belongs to a special set with the name "default". However, it can be added to a specific set by specifying a set name via a data-codebook-set
attribute in one of two places:
js-codebook__set
If a set is specified in both of those places, the set specified on the block itself will take precedence. Code blocks can only belong to a single set.
Code blocks in a set have two helper methods exposed that allow them to print output to the page:
log(...output: any[])
If a code block has a log output element, specified via a data-codebook-log
attribute with a value matching the id
attribute of the log output element, the log
method will print output to that element when called.
Multiple values can be logged, with each value appended to the log after the last. A block's log is cleared before each time its set is run.
On this page, Codebook logs are marked by a 📝.
It will attempt to convert Date
and Object
to strings intelligently, otherwise it will attempt to coerce each value to a string.
html(output: string)
If a code block has an HTML output element, specified via a data-codebook-html
attribute with a value matching the id
attribute of the log output element, the html
method will overwrite that element's inner HTML with whatever custom HTML is passed in as the output
argument.
Particularly because the log
and html
methods take on different values at different times, any asynchronous code that runs within a Codebook block should finish before the main thread of the code block is finished.
This can be accomplished either by using the await
keyword whenever calling asynchronous code, or by keeping track of all asynchronous code and using await Promise.all(promises);
at the end of a block to wait for all asynchronous code to complete.
Codebook wraps each block in an async
function, so await
can be used. As a result, the methods used to run code sets each return a Promise
, which resolves when all specified sets have finished running.
codebook.run(args?: Record<string, any>): Promise<void>;
The run
method runs all sets of code on a page, in which they appear on the page.
Code blocks within a set will run in the order in which they appear in the markup, unless they have a data-codebook-index
attribute. This attribute should be a number, and code with a lower number here will run first.
Code blocks with an index will always run before code blocks without an index, and if code blocks have the same index then they will run in the order in which they appear in the markup.
run
takes a single optional argument, which is an Object
containing named arguments to be passed to your code. This can be used to expose objects that don't exist on the global scope, such as packages that have been imported into a module.
codebook.run({
testArg: 'test',
});
Codebook uses some variables to ensure the `log` and `html` methods are available, so these argument names are reserved and cannot be used:
'_log'
'_$log'
'log'
'_html'
'_$html'
'html'
codebook.runSet(setName: string, args?: Record<string, any>): Promise<void>;
codebook.runSet(args?: Record<string, any>): Promise<void>;
The runSet
method allows you to run a specific set of code, instead of all of them. The setName
argument should be a string matching the name of the set, or can be left blank to call the "default" set.
codebook.runSet('test', { testArg: 'test2' });
codebook.tidy(): void;
The tidy
method looks for all Codebook code blocks and analyses their shared indentation based on how much the first line of code is indented, expecting indentation to be done with tabs. Then it strips all lines in that block by the same amount of indentation, so code appearing on the page using CSS rules like white-space: pre;
won't appear hugely indented, but the source HTML code can still be tidily indented.
As well as code blocks, the tidy
method will also tidy "inert" blocks by looking for elements with a class of js-codebook__inert
. These blocks are otherwise ignored by Codebook, and it won't try to run any code they contain.