Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 6 additions & 4 deletions src/render.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { dirname } from "path";
import path from "path";
import { fileURLToPath } from "url";

import nunjucks from "nunjucks";
Expand All @@ -7,13 +7,15 @@ import showdown from "showdown";
import { removeExtraEmptyLines } from "./text.js";

// load converters & template engines
const srcDir = dirname(fileURLToPath(import.meta.url));
const srcDir = path.dirname(fileURLToPath(import.meta.url));
const templateDir = path.join(srcDir, "templates");
const sd = new showdown.Converter();
const env = new nunjucks.Environment(new nunjucks.FileSystemLoader(srcDir));
const loader = new nunjucks.FileSystemLoader(templateDir);
const env = new nunjucks.Environment(loader);
env.addFilter("parseJson", JSON.parse);

/// basic convertion functions
const toMarkDown = (schema) => env.render("template.md", schema);
const toMarkDown = (schema) => env.render("base.md", schema);
const toHtml = (schema) => sd.makeHtml(toMarkDown(schema));

// helpers for the engine function below
Expand Down
31 changes: 0 additions & 31 deletions src/template.md

This file was deleted.

13 changes: 13 additions & 0 deletions src/templates/base.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{% import "macros.md" as macros %}

# {{ title }}

**(`{{ type }}`)**

{{ description|safe }}

{% for _, property in properties %}

{{ macros.instance(property, title=2) }}

{% endfor %}
66 changes: 66 additions & 0 deletions src/templates/macros.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
{% macro instance(property, level=2) %}

{{ "#".repeat(level) }} {{ property.title }}

{% if property.type %}**(`{{ property.type }}`)**{% endif %}{% if property.default %} Defaults to _{{ property.default }}_.{% endif %}

{% if property.description %}
{{ property.description }}
{% endif %}

{% if property.context %}
{{ property.context|safe }}
{% endif %}

{% if property.oneOf or property.anyOf or property.allOf or property.not %}
{{ "#".repeat(level + 1) }} Validation

{% if property.oneOf %}
{{ "#".repeat(level + 2) }} It must satisfy one of these conditions

{% for item in property.oneOf %}
{{ instance(item, level + 3) }}
{% endfor %}
{% endif %}

{% if property.anyOf %}
{{ "#".repeat(level + 2) }} It must satisfy at least one of these conditions

{% for item in property.anyOf %}
{{ instance(item, level + 3) }}
{% endfor %}
{% endif %}

{% if property.allOf %}
{{ "#".repeat(level + 2) }} It must satisfy all one of these conditions

{% for item in property.allOf %}
{{ instance(item, level + 3) }}
{% endfor %}
{% endif %}

{% if property.not %}
{{ "#".repeat(level + 2) }} It cannot satisfy any of these conditions

{% for item in property.not %}
{{ instance(item, level + 3) }}
{% endfor %}
{% endif %}

{% endif %}

{% if property.examples %}
{% if property.examples.length > 1 %}
{% set example_section_title = "Examples" %}
{% else %}
{% set example_section_title = "Example" %}
{% endif %}
{{ "#".repeat(level + 1) }} {{ example_section_title }}

{% for example in property.examples %}

- `{{ example|parseJson|dump|safe }}`
{% endfor %}

{% endif %}
{% endmacro %}
18 changes: 14 additions & 4 deletions src/text.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,18 @@
function removeExtraEmptyLines(text) {
let cleaned = text.trim();
cleaned = cleaned.replace(/\n{3,}/gm, "\n\n"); // remove extra empty lines
cleaned += "\n"; // add new line at end of string
return cleaned;
const lines = text.split("\n");
const cleaned = [];

for (let idx = 0; idx < lines.length; idx++) {
let line = lines[idx].trim();
let previous = cleaned[cleaned.length - 1] || "";

if (line == "" && previous == "") {
continue; // skip duplicate empty lines
}
cleaned.push(line);
}

return cleaned.join("\n").trim() + "\n";
}

export { removeExtraEmptyLines };
44 changes: 31 additions & 13 deletions test/fixtures/data-resource.html
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ <h3 id="examples">Examples</h3>
<li><p><code>{"profile":"http://example.com/my-profiles-json-schema.json"}</code></p></li>
</ul>
<h2 id="name">Name</h2>
<p><strong>(<code>string</code>)</strong> </p>
<p><strong>(<code>string</code>)</strong></p>
<p>An identifier string. Lower case characters with <code>.</code>, <code>_</code>, <code>-</code> and <code>/</code> are allowed.</p>
<p>This is ideally a url-usable and human-readable name. Name <code>SHOULD</code> be invariant, meaning it <code>SHOULD NOT</code> change when its parent descriptor is updated.</p>
<h3 id="example">Example</h3>
Expand All @@ -21,7 +21,25 @@ <h3 id="example">Example</h3>
<h2 id="path">Path</h2>
<p>A reference to the data for this resource, as either a path as a string, or an array of paths as strings. of valid URIs.</p>
<p>The dereferenced value of each referenced data source in <code>path</code> <code>MUST</code> be commensurate with a native, dereferenced representation of the data the resource describes. For example, in a <em>Tabular</em> Data Resource, this means that the dereferenced value of <code>path</code> <code>MUST</code> be an array.</p>
<h3 id="examples-1">Examples</h3>
<h3 id="validation">Validation</h3>
<h4 id="itmustsatisfyoneoftheseconditions">It must satisfy one of these conditions</h4>
<h5 id="path-1">Path</h5>
<p><strong>(<code>string</code>)</strong></p>
<p>A fully qualified URL, or a POSIX file path..</p>
<p>Implementations need to negotiate the type of path provided, and dereference the data accordingly.</p>
<h6 id="examples-1">Examples</h6>
<ul>
<li><p><code>{"path":"file.csv"}</code></p></li>
<li><p><code>{"path":"http://example.com/file.csv"}</code></p></li>
</ul>
<h5 id=""> </h5>
<p><strong>(<code>array</code>)</strong></p>
<h6 id="examples-2">Examples</h6>
<ul>
<li><p><code>["file.csv"]</code></p></li>
<li><p><code>["http://example.com/file.csv"]</code></p></li>
</ul>
<h3 id="examples-3">Examples</h3>
<ul>
<li><p><code>{"path":["file.csv","file2.csv"]}</code></p></li>
<li><p><code>{"path":["http://example.com/file.csv","http://example.com/file2.csv"]}</code></p></li>
Expand All @@ -30,54 +48,54 @@ <h3 id="examples-1">Examples</h3>
<h2 id="data">Data</h2>
<p>Inline data for this resource.</p>
<h2 id="schema">Schema</h2>
<p><strong>(<code>object</code>)</strong> </p>
<p><strong>(<code>object</code>)</strong></p>
<p>A schema for this resource.</p>
<h2 id="title">Title</h2>
<p><strong>(<code>string</code>)</strong> </p>
<p><strong>(<code>string</code>)</strong></p>
<p>A human-readable title.</p>
<h3 id="example-1">Example</h3>
<ul>
<li><code>{"title":"My Package Title"}</code></li>
</ul>
<h2 id="description">Description</h2>
<p><strong>(<code>string</code>)</strong> </p>
<p><strong>(<code>string</code>)</strong></p>
<p>A text description. Markdown is encouraged.</p>
<h3 id="example-2">Example</h3>
<ul>
<li><code>{"description":"# My Package description\nAll about my package."}</code></li>
</ul>
<h2 id="homepage">Home Page</h2>
<p><strong>(<code>string</code>)</strong> </p>
<p><strong>(<code>string</code>)</strong></p>
<p>The home on the web that is related to this data package.</p>
<h3 id="example-3">Example</h3>
<ul>
<li><code>{"homepage":"http://example.com/"}</code></li>
</ul>
<h2 id="sources">Sources</h2>
<p><strong>(<code>array</code>)</strong> </p>
<p><strong>(<code>array</code>)</strong></p>
<p>The raw sources for this resource.</p>
<h3 id="example-4">Example</h3>
<ul>
<li><code>{"sources":[{"title":"World Bank and OECD","path":"http://data.worldbank.org/indicator/NY.GDP.MKTP.CD"}]}</code></li>
</ul>
<h2 id="licenses">Licenses</h2>
<p><strong>(<code>array</code>)</strong> </p>
<p><strong>(<code>array</code>)</strong></p>
<p>The license(s) under which the resource is published.</p>
<p>This property is not legally binding and does not guarantee that the package is licensed under the terms defined herein.</p>
<h3 id="example-5">Example</h3>
<ul>
<li><code>{"licenses":[{"name":"odc-pddl-1.0","path":"http://opendatacommons.org/licenses/pddl/","title":"Open Data Commons Public Domain Dedication and License v1.0"}]}</code></li>
</ul>
<h2 id="format">Format</h2>
<p><strong>(<code>string</code>)</strong> </p>
<p><strong>(<code>string</code>)</strong></p>
<p>The file format of this resource.</p>
<p><code>csv</code>, <code>xls</code>, <code>json</code> are examples of common formats.</p>
<h3 id="example-6">Example</h3>
<ul>
<li><code>{"format":"xls"}</code></li>
</ul>
<h2 id="mediatype">Media Type</h2>
<p><strong>(<code>string</code>)</strong> </p>
<p><strong>(<code>string</code>)</strong></p>
<p>The media type of this resource. Can be any valid media type listed with <a href="https://www.iana.org/assignments/media-types/media-types.xhtml">IANA</a>.</p>
<h3 id="example-7">Example</h3>
<ul>
Expand All @@ -91,16 +109,16 @@ <h3 id="example-8">Example</h3>
<li><code>{"encoding":"utf-8"}</code></li>
</ul>
<h2 id="bytes">Bytes</h2>
<p><strong>(<code>integer</code>)</strong> </p>
<p><strong>(<code>integer</code>)</strong></p>
<p>The size of this resource in bytes.</p>
<h3 id="example-9">Example</h3>
<ul>
<li><code>{"bytes":2082}</code></li>
</ul>
<h2 id="hash">Hash</h2>
<p><strong>(<code>string</code>)</strong> </p>
<p><strong>(<code>string</code>)</strong></p>
<p>The MD5 hash of this resource. Indicate other hashing algorithms with the {algorithm}:{hash} format.</p>
<h3 id="examples-2">Examples</h3>
<h3 id="examples-4">Examples</h3>
<ul>
<li><p><code>{"hash":"d25c9c77f588f5dc32059d2da1136c02"}</code></p></li>
<li><p><code>{"hash":"SHA256:5262f12512590031bbcc9a430452bfd75c2791ad6771320bb4b5728bfb78c4d0"}</code></p></li>
Expand Down
Loading