Introduction
Aqua acts as a preprocessor for Web Components and markdown parsers, mainly built to be compatible with Svelte, but it could also work in browsers natively as a callable API.
This parses markdown/markups and returns a styled HTMLElement
block that could be injected to any DOM or directly replace the processed Node
if used natively in a browser.
It only utilizes prism, everything else is built from the ground up using native Web APIs and modern CSS layouts, preprocessed to be compatible with both modern and old browsers.
Quick Start
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@ignatiusmb/aqua@20.3.0/lib/aqua.min.css" />
<script defer src="https://cdn.jsdelivr.net/npm/@ignatiusmb/aqua@20.3.0/lib/aqua.cbs.js"></script>
Use as highlighter functionimport Aqua from '@ignatiusmb/aqua';
const options = {
highlight: (str, language) => Aqua.code.highlight(str, { language });
}
// Use it like so as 'markdown-it' options
const markIt = require('markdown-it')(options);
The output from the parsed block of code should then look like the code block above. There’s also a couple more examples below in the Modules / API section. This documentation is also built with Aqua.
You should be able to use highlight
API from code
with any markdown parser that allows you to handle the syntax highlighting yourself. This is basically the custom highlight function replacement, and it respects the DOM hierarchy by starting with the <pre>
tag so there won’t be any unnecessary nesting happening.
Getting Started
Use in Node.js
via npmnpm install @ignatiusmb/aqua
Use in Browser
Direct Include --> jsDelivr CDN<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@ignatiusmb/aqua@20.3.0/lib/aqua.min.css" />
<script defer src="https://cdn.jsdelivr.net/npm/@ignatiusmb/aqua@20.3.0/lib/aqua.min.js"></script>
Direct Include --> UNPKG CDN<link rel="stylesheet" href="https://unpkg.com/@ignatiusmb/aqua@20.3.0/lib/aqua.min.css" />
<script defer src="https://unpkg.com/@ignatiusmb/aqua@20.3.0/lib/aqua.min.js"></script>
Included Font Vars
:root {
--aqua-default: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Rubik', 'Ubuntu', 'Roboto', sans-serif;
--aqua-heading: 'Karla', sans-serif;
--aqua-monospace: 'Fira Code', 'Inconsolata', 'Consolas', monospace;
}
/* Example */
body {
font-family: var(--aqua-default);
}
header {
font-family: var(--aqua-heading);
}
footer {
font-family: var(--aqua-monospace);
}
Use your own binaries or through CDN<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Rubik&display=swap">
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Ubuntu&display=swap">
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Karla&display=swap">
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Fira+Code&display=swap">
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Inconsolata&display=swap">
Important Note
Aqua provides stylesheets and script files, linking or including the stylesheet is mandatory to display the elements properly. A custom reset is included as well so it makes quick prototyping a breeze, everything should display properly, and it works without any additional configuration.
1.0 - without bundler<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@ignatiusmb/aqua@20.3.0/lib/aqua.min.css" />
2.0 - with a bundlerimport '@ignatiusmb/aqua/lib/aqua.min.css';
On the other hand, there’s a couple of ways to use the script files. You can use and import the entire module through the CDN if you’re using it in the client-side. But, if you use the parser from the server-side, you can just bundle the callback script file with your website or include it in the head.
1.0 - Parsing in client-side<script defer src="https://cdn.jsdelivr.net/npm/@ignatiusmb/aqua@20.3.0/lib/aqua.min.js"></script>
2.0 - Parsing from server-side | With bundlerimport '@ignatiusmb/aqua/lib/aqua.cbs';
2.1 - Parsing from server-side | No bundler<script defer src="https://cdn.jsdelivr.net/npm/@ignatiusmb/aqua@20.3.0/lib/aqua.cbs.js"></script>
Modules / API
Aqua doesn’t have any named export by default, but it provides many props that has it, all available and listed below. First, import the entire module through its default export with the name Aqua
.
import Aqua from '@ignatiusmb/aqua';
Code.js
const { cbs, highlight, highlightAll, init } = Aqua.code;
Aqua.code
provides 4 public methods
init
- method used for client-side parsingcbs
- all the needed callbacks for toolbar onclick eventshighlight
- the highlighter function to parse code blockshighlightAll
- wrapper to call Prism highlightAll function
Client-side usage<body>
<pre class="aqua code-block" data-language="" data-title="">
<!-- text to be preformatted -->
</pre>
<div id="root" class="container">
<pre class="aqua code-block" data-language="" data-title="">
<!-- text to be preformatted -->
</pre>
</div>
</body>
<script>
// Defaults to document.body if no argument is passed
// This will parse and highlight all <pre> tags
// with class of 'aqua code-block' inside <body>
Aqua.code.init();
// Select tag with class of 'container' and id 'root'
// as the starting element and will only parse
// all <pre> tags inside tags with this class and id
Aqua.code.init(document.querySelector('.container#root'));
</script>
Server-side usage | Simpleconst markIt = require('markdown-it')({ highlight: (str, language) => Aqua.code.highlight(str, { language }) });
Server-side usage | With title parsingconst options = {
highlight: (str, language) => {
const strList = str.split('\n');
const dataset = { language };
// If the first line has a prefix of '~'
// It will use the first line as the title
if (strList[0][0] === '~') {
dataset['title'] = strList[0].slice(1);
}
// Check if title exist and remove it from string to be parsed
const content = strList.slice(dataset['title'] ? 1 : 0).join('\n');
return Aqua.code.highlight(content, dataset);
},
}
Server-side usage | With title and lineStart parsingimport Aqua from '@ignatiusmb/aqua';
const options = {
highlight: (str, language) => {
const strList = str.split('\n');
const dataset = { language };
if (strList[0][0] === '~') {
const [title, lineNumber] = strList[0].split('#');
dataset['title'] = title.slice(1);
// Check if there's a hash '#' in the title and use it as start line number
if (lineNumber) dataset['lineStart'] = parseInt(lineNumber);
}
const content = strList.slice(dataset['title'] ? 1 : 0).join('\n');
return Aqua.code.highlight(content, dataset);
},
}