Skip to content

Commit 6acd4d3

Browse files
authored
Merge pull request #14 from AegisJSProject/release/0.1.0
Rename to `@aegisjsproject/markdown`
2 parents c2e039f + 31f03f8 commit 6acd4d3

File tree

9 files changed

+289
-160
lines changed

9 files changed

+289
-160
lines changed

.npmignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
node_modules/
2+
test/
23
.github/
34
.editorconfig
45
.eslintignore

CHANGELOG.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,17 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
66

77
## [Unreleased]
88

9+
## [v0.1.0] - 2024-02-28
10+
11+
### Added
12+
- Add functions to load `highlight.js` stylesheets and fetch & parse markdown
13+
14+
### Fixed
15+
- Do not publish `test/` directory
16+
17+
### Changed
18+
- Renamed to `@aegisjsproject/markdown`
19+
920
## [v0.0.3] - 2024-02-26
1021

1122
### Added

README.md

Lines changed: 97 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,25 @@
1-
# `@shgysk8zer0/aegis-markdown`
1+
# `@aegisjsproject/markdown`
22

3-
Markdown parser for [`@shgysk8zer0/aegis`](https://github.com/shgysk8zer0/aegis)
3+
Markdown parser for [`@aegisjsproject/core`](https://github.com/AegisJSProject/core)
44

5-
[![CodeQL](https://github.com/shgysk8zer0/aegis-markdown/actions/workflows/codeql-analysis.yml/badge.svg)](https://github.com/shgysk8zer0/aegis-markdown/actions/workflows/codeql-analysis.yml)
6-
![Node CI](https://github.com/shgysk8zer0/aegis-markdown/workflows/Node%20CI/badge.svg)
7-
![Lint Code Base](https://github.com/shgysk8zer0/aegis-markdown/workflows/Lint%20Code%20Base/badge.svg)
5+
[![CodeQL](https://github.com/AegisJSProject/markdown/actions/workflows/codeql-analysis.yml/badge.svg)](https://github.com/AegisJSProject/markdown/actions/workflows/codeql-analysis.yml)
6+
![Node CI](https://github.com/AegisJSProject/markdown/workflows/Node%20CI/badge.svg)
7+
![Lint Code Base](https://github.com/AegisJSProject/markdown/workflows/Lint%20Code%20Base/badge.svg)
88

9-
[![GitHub license](https://img.shields.io/github/license/shgysk8zer0/aegis-markdown.svg)](https://github.com/shgysk8zer0/aegis-markdown/blob/master/LICENSE)
10-
[![GitHub last commit](https://img.shields.io/github/last-commit/shgysk8zer0/aegis-markdown.svg)](https://github.com/shgysk8zer0/aegis-markdown/commits/master)
11-
[![GitHub release](https://img.shields.io/github/release/shgysk8zer0/aegis-markdown?logo=github)](https://github.com/shgysk8zer0/aegis-markdown/releases)
9+
[![GitHub license](https://img.shields.io/github/license/AegisJSProject/markdown.svg)](https://github.com/AegisJSProject/markdown/blob/master/LICENSE)
10+
[![GitHub last commit](https://img.shields.io/github/last-commit/AegisJSProject/markdown.svg)](https://github.com/AegisJSProject/markdown/commits/master)
11+
[![GitHub release](https://img.shields.io/github/release/AegisJSProject/markdown?logo=github)](https://github.com/AegisJSProject/markdown/releases)
1212
[![GitHub Sponsors](https://img.shields.io/github/sponsors/shgysk8zer0?logo=github)](https://github.com/sponsors/shgysk8zer0)
1313

14-
[![npm](https://img.shields.io/npm/v/@shgysk8zer0/aegis-markdown)](https://www.npmjs.com/package/@shgysk8zer0/aegis-markdown)
15-
![node-current](https://img.shields.io/node/v/@shgysk8zer0/aegis-markdown)
16-
![NPM Unpacked Size](https://img.shields.io/npm/unpacked-size/%40shgysk8zer0%2Faegis-markdown)
14+
[![npm](https://img.shields.io/npm/v/@aegisjsproject/markdown)](https://www.npmjs.com/package/@aegisjsproject/markdown)
15+
![node-current](https://img.shields.io/node/v/@aegisjsproject/markdown)
16+
![NPM Unpacked Size](https://img.shields.io/npm/unpacked-size/%40shgysk8zer0%2Fmarkdown)
1717

18-
[![npm](https://img.shields.io/npm/dw/@shgysk8zer0/aegis-markdown?logo=npm)](https://www.npmjs.com/package/@shgysk8zer0/aegis-markdown)
18+
[![npm](https://img.shields.io/npm/dw/@aegisjsproject/markdown?logo=npm)](https://www.npmjs.com/package/@aegisjsproject/markdown)
1919

20-
[![GitHub followers](https://img.shields.io/github/followers/shgysk8zer0.svg?style=social)](https://github.com/shgysk8zer0)
21-
![GitHub forks](https://img.shields.io/github/forks/shgysk8zer0/aegis-markdown.svg?style=social)
22-
![GitHub stars](https://img.shields.io/github/stars/shgysk8zer0/aegis-markdown.svg?style=social)
20+
[![GitHub followers](https://img.shields.io/github/followers/AegisJSProject.svg?style=social)](https://github.com/AegisJSProject)
21+
![GitHub forks](https://img.shields.io/github/forks/AegisJSProject/markdown.svg?style=social)
22+
![GitHub stars](https://img.shields.io/github/stars/AegisJSProject/markdown.svg?style=social)
2323
[![Twitter Follow](https://img.shields.io/twitter/follow/shgysk8zer0.svg?style=social)](https://twitter.com/shgysk8zer0)
2424

2525
[![Donate using Liberapay](https://img.shields.io/liberapay/receives/shgysk8zer0.svg?logo=liberapay)](https://liberapay.com/shgysk8zer0/donate "Donate using Liberapay")
@@ -32,7 +32,87 @@ Markdown parser for [`@shgysk8zer0/aegis`](https://github.com/shgysk8zer0/aegis)
3232
## Example
3333

3434
```js
35-
import { md } from '@shgysk8zer0/aegis-markdown';
35+
import { md, createStyleSheet, getMarkdown } from '@aegisjsproject/markdown';
3636

37-
document.body.append(md`# Hello, World!`);
37+
document.head.append(
38+
createStyleSheet('github', { media: '(prefers-color-scheme: light)' }),
39+
createStyleSheet('github-dark', { media: '(prefers-color-scheme: dark)' }),
40+
);
41+
42+
document.getElementById('header').append(md`
43+
# Hello, World!
44+
45+
## It is currently ${new Date().toLocaleString()}.
46+
`);
47+
48+
customElements.define('md-preview', class HTMLMDPreviewElement extends HTMLElement {
49+
#shadow;
50+
51+
constructor() {
52+
super();
53+
54+
this.#shadow = this.attachShadow({ mode: 'closed' });
55+
const container = document.createElement('div');
56+
container.id = 'container';
57+
container.part.add('container');
58+
59+
this.#shadow.append(
60+
createStyleSheet('github', { media: '(prefers-color-scheme: light)' }),
61+
createStyleSheet('github-dark', { media: '(prefers-color-scheme: dark)' }),
62+
container,
63+
);
64+
}
65+
66+
async attributeChangedCallback(name, oldVal, newVal) {
67+
switch(name) {
68+
case 'src':
69+
if (typeof newVal === 'string') {
70+
this.#shadow.getElementById('container').replaceChildren(await getMarkdown(this.src));
71+
} else {
72+
this.#shadow.getElementById('container').replaceChildren();
73+
}
74+
break;
75+
76+
default:
77+
throw new Error(`Unhandled attribute change: ${name}.`);
78+
}
79+
}
80+
81+
set content(val) {
82+
if (typeof val === 'string' && val.length !== 0) {
83+
this.#shadow.getElementById('container').replaceChildren(md`${val}`);
84+
this.scrollIntoView({ behavior: 'smooth', block: 'start' });
85+
} else {
86+
this.#shadow.getElementById('container').replaceChildren();
87+
}
88+
}
89+
90+
get src() {
91+
return this.getAttribute('src');
92+
}
93+
94+
set src(val) {
95+
if (typeof val === 'string' || val instanceof URL) {
96+
this.setAttribute('src', val);
97+
} else {
98+
this.removeAttribute('src');
99+
}
100+
}
101+
102+
clear() {
103+
this.content = null;
104+
}
105+
106+
static get observedAttributes() {
107+
return ['src'];
108+
}
109+
});
110+
111+
document.forms.test.addEventListener('submit', event => {
112+
event.preventDefault();
113+
const data = new FormData(event.target);
114+
document.getElementById('preview').content = data.get('md');
115+
});
116+
117+
document.forms.test.addEventListener('reset', () => document.getElementById('preview').clear());
38118
```

markdown.js

Lines changed: 43 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,25 @@
11
import { Marked } from 'marked';
22
import { markedHighlight } from 'marked-highlight';
33
import hljs from 'highlight.js';
4-
import { sanitizeString } from '@shgysk8zer0/aegis';
4+
import { sanitizeString } from '@aegisjsproject/core/core.js';
5+
6+
export const hljsURL = new URL(`https://unpkg.com/@highlightjs/cdn-assets@${hljs.versionString}/`);
7+
8+
export function createStyleSheet(path, { media, base = hljsURL } = {}) {
9+
const link = document.createElement('link');
10+
link.relList.add('stylesheet');
11+
link.crossOrigin = 'anonymous';
12+
link.referrerPolicy = 'no-referrer';
13+
14+
if (typeof media === 'string') {
15+
link.media = media;
16+
} else if (media instanceof MediaQueryList) {
17+
link.media = media.media;
18+
}
19+
20+
link.href = new URL(`./styles/${path}.min.css`, base);
21+
return link;
22+
}
523

624
export function createMDParser({
725
gfm = true,
@@ -36,3 +54,27 @@ export function createMDParser({
3654
}
3755

3856
export const md = createMDParser({});
57+
58+
export async function getMarkdown(url, {
59+
mode = 'cors',
60+
referrerPolicy = 'no-referrer',
61+
parser = md,
62+
headers = new Headers({ Accept: 'text/markdown' }),
63+
...rest
64+
} = {}) {
65+
if (typeof headers === 'object' && ! (headers instanceof Headers)) {
66+
return await getMarkdown(url, { mode, referrerPolicy, parser, headers: new Headers(headers), ...rest });
67+
} else if (! headers.has('Accept')) {
68+
headers.set('Accept', 'text/markdown');
69+
}
70+
71+
const resp = await fetch(url, { mode, referrerPolicy, headers, ...rest });
72+
73+
if (! resp.ok) {
74+
throw new Error(`${resp.url} [${resp.status} ${resp.statusText}]`);
75+
} else if (! resp.headers.get('Content-Type').startsWith('text/markdown')) {
76+
throw new TypeError(`Invalid Content-Type: ${resp.headers.get('Content-Type')}.`);
77+
} else {
78+
return parser`${await resp.text()}`;
79+
}
80+
}

0 commit comments

Comments
 (0)