Having already created implementations of our object-based and folder-based maps, it should be fairly quick work to create a map implementation of our function representation.
Wrap a function with a Map #
To create a function-based map, we’ll need two things: 1) a function that can produce a value for a given key, and 2) an array of keys defining a representative domain over which the function is valid.
/* src/map/FunctionMap.js */
export default class FunctionMap extends Map {
constructor(fn, domain) {
super();
this.fn = fn;
this.domain = domain;
}
get(key) {
return this.fn(key);
}
*keys() {
yield* this.domain;
}
}
We can use this FunctionMap class as follows:
/* src/map/fn.js */
import FunctionMap from "./FunctionMap.js";
// Function to generate markdown for a key of the format "post<n>.md"
function fn(key) {
const match = /.+(?<number>\d+)\.md/.exec(key);
if (match) {
return `This is **post ${match.groups.number}**.`;
}
}
// Representative domain of the function
const domain = ["post1.md", "post2.md", "post3.md"];
export default new FunctionMap(fn, domain);
The earlier object-based and files-based maps are “real” in that the data is stored persistently in the real world. But the function-based map above is virtual from the start — the complete data is not stored persistently, and is only available when code is running.
Note that a map’s keys method doesn’t have to return every key the map can actually handle. The map above defines three representative keys, but the get method will actually accept any key ending in .md. If we ask for post4.md, we will get back This is **post 4**. That flexibility can be useful. (If that’s not desired, the get method can reject requests for keys outside the stated domain.)
Verify the function map #
From inside the src/map directory, run the unit tests for the function-based map. These are the same tests as for the object and folder maps.
$ node fn.test.js
▶ FunctionMap
✔ get (0.755042ms)
✔ keys (0.346042ms)
✔ FunctionMap (1.489167ms)
ℹ tests 2
ℹ suites 1
ℹ pass 2
ℹ fail 0
…
Use our json utility to display this function-based map:
$ node json fn.js
{
"post1.md": "This is **post 1**.",
"post2.md": "This is **post 2**.",
"post3.md": "This is **post 3**."
}
You can think of a FunctionMap as a function that can tell you what its domain is.
We can apply our markdown-to-HTML transformation to this function-backed map to create a new map of HTML.
/* src/map/htmlFn.js */
import fnMap from "./fn.js";
import HtmlMap from "./HtmlMap.js";
export default new HtmlMap(fnMap);
View the HTML translation of the markdown files in the virtual map implied by the function.
$ node json htmlFn.js
{
"post1.html": "<p>This is <strong>post 1</strong>.</p>\n",
"post2.html": "<p>This is <strong>post 2</strong>.</p>\n",
"post3.html": "<p>This is <strong>post 3</strong>.</p>\n"
}
We have now implemented four different ways to construct a map based on: 1) an object, 2) a folder, 3) a function, 4) another map.
In a bit, we’ll see how they can be used together to create interesting combinations and be used for practical purposes like making a site. Before doing that, however, let’s make our code a little more general-purpose and flexible.
Next: Full compatibility »