Compare commits
15 Commits
v1.0.0-alp
...
cd335a366e
| Author | SHA1 | Date | |
|---|---|---|---|
|
cd335a366e
|
|||
|
b307d4de03
|
|||
|
91eff4ad07
|
|||
|
994053e080
|
|||
|
bc37756097
|
|||
|
3a5733eeee
|
|||
|
7c2549cbfe
|
|||
|
e3bd385c96
|
|||
|
038ce15908
|
|||
|
7aebcfc43f
|
|||
|
b7eccde9d0
|
|||
|
9305e9f718
|
|||
|
b907cc2f65
|
|||
|
29e2fca2a5
|
|||
|
d3e908b2b0
|
1
.gitignore
vendored
1
.gitignore
vendored
@@ -1,3 +1,4 @@
|
|||||||
.env
|
.env
|
||||||
users.yaml
|
users.yaml
|
||||||
build/
|
build/
|
||||||
|
coverage/
|
||||||
|
|||||||
@@ -45,6 +45,11 @@ pre code {
|
|||||||
padding: 0.6rem 1rem;
|
padding: 0.6rem 1rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.highlight pre {
|
||||||
|
font-size: 0.9em;
|
||||||
|
padding: 0.6rem 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
img {
|
img {
|
||||||
max-width: 100%;
|
max-width: 100%;
|
||||||
}
|
}
|
||||||
|
|||||||
140
assets/css/prism.css
Normal file
140
assets/css/prism.css
Normal file
@@ -0,0 +1,140 @@
|
|||||||
|
/**
|
||||||
|
* prism.js default theme for JavaScript, CSS and HTML
|
||||||
|
* Based on dabblet (http://dabblet.com)
|
||||||
|
* @author Lea Verou
|
||||||
|
*/
|
||||||
|
|
||||||
|
code[class*="language-"],
|
||||||
|
pre[class*="language-"] {
|
||||||
|
color: black;
|
||||||
|
background: none;
|
||||||
|
text-shadow: 0 1px white;
|
||||||
|
font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace;
|
||||||
|
font-size: 1em;
|
||||||
|
text-align: left;
|
||||||
|
white-space: pre;
|
||||||
|
word-spacing: normal;
|
||||||
|
word-break: normal;
|
||||||
|
word-wrap: normal;
|
||||||
|
line-height: 1.5;
|
||||||
|
|
||||||
|
-moz-tab-size: 4;
|
||||||
|
-o-tab-size: 4;
|
||||||
|
tab-size: 4;
|
||||||
|
|
||||||
|
-webkit-hyphens: none;
|
||||||
|
-moz-hyphens: none;
|
||||||
|
-ms-hyphens: none;
|
||||||
|
hyphens: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
pre[class*="language-"]::-moz-selection, pre[class*="language-"] ::-moz-selection,
|
||||||
|
code[class*="language-"]::-moz-selection, code[class*="language-"] ::-moz-selection {
|
||||||
|
text-shadow: none;
|
||||||
|
background: #b3d4fc;
|
||||||
|
}
|
||||||
|
|
||||||
|
pre[class*="language-"]::selection, pre[class*="language-"] ::selection,
|
||||||
|
code[class*="language-"]::selection, code[class*="language-"] ::selection {
|
||||||
|
text-shadow: none;
|
||||||
|
background: #b3d4fc;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media print {
|
||||||
|
code[class*="language-"],
|
||||||
|
pre[class*="language-"] {
|
||||||
|
text-shadow: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Code blocks */
|
||||||
|
pre[class*="language-"] {
|
||||||
|
padding: 1em;
|
||||||
|
margin: .5em 0;
|
||||||
|
overflow: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
:not(pre) > code[class*="language-"],
|
||||||
|
pre[class*="language-"] {
|
||||||
|
background: #f5f2f0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Inline code */
|
||||||
|
:not(pre) > code[class*="language-"] {
|
||||||
|
padding: .1em;
|
||||||
|
border-radius: .3em;
|
||||||
|
white-space: normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
.token.comment,
|
||||||
|
.token.prolog,
|
||||||
|
.token.doctype,
|
||||||
|
.token.cdata {
|
||||||
|
color: slategray;
|
||||||
|
}
|
||||||
|
|
||||||
|
.token.punctuation {
|
||||||
|
color: #999;
|
||||||
|
}
|
||||||
|
|
||||||
|
.token.namespace {
|
||||||
|
opacity: .7;
|
||||||
|
}
|
||||||
|
|
||||||
|
.token.property,
|
||||||
|
.token.tag,
|
||||||
|
.token.boolean,
|
||||||
|
.token.number,
|
||||||
|
.token.constant,
|
||||||
|
.token.symbol,
|
||||||
|
.token.deleted {
|
||||||
|
color: #905;
|
||||||
|
}
|
||||||
|
|
||||||
|
.token.selector,
|
||||||
|
.token.attr-name,
|
||||||
|
.token.string,
|
||||||
|
.token.char,
|
||||||
|
.token.builtin,
|
||||||
|
.token.inserted {
|
||||||
|
color: #690;
|
||||||
|
}
|
||||||
|
|
||||||
|
.token.operator,
|
||||||
|
.token.entity,
|
||||||
|
.token.url,
|
||||||
|
.language-css .token.string,
|
||||||
|
.style .token.string {
|
||||||
|
color: #9a6e3a;
|
||||||
|
/* This background color was intended by the author of this theme. */
|
||||||
|
background: hsla(0, 0%, 100%, .5);
|
||||||
|
}
|
||||||
|
|
||||||
|
.token.atrule,
|
||||||
|
.token.attr-value,
|
||||||
|
.token.keyword {
|
||||||
|
color: #07a;
|
||||||
|
}
|
||||||
|
|
||||||
|
.token.function,
|
||||||
|
.token.class-name {
|
||||||
|
color: #DD4A68;
|
||||||
|
}
|
||||||
|
|
||||||
|
.token.regex,
|
||||||
|
.token.important,
|
||||||
|
.token.variable {
|
||||||
|
color: #e90;
|
||||||
|
}
|
||||||
|
|
||||||
|
.token.important,
|
||||||
|
.token.bold {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
.token.italic {
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
|
||||||
|
.token.entity {
|
||||||
|
cursor: help;
|
||||||
|
}
|
||||||
@@ -47,6 +47,13 @@ pre code {
|
|||||||
color: var(--text-color-dark-bg);
|
color: var(--text-color-dark-bg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.highlight pre,
|
||||||
|
.highlight code {
|
||||||
|
background-color: var(--background-color-body);
|
||||||
|
border: 2px solid #e8e3da;
|
||||||
|
color: var(--text-color-body);
|
||||||
|
}
|
||||||
|
|
||||||
dl dt {
|
dl dt {
|
||||||
color: var(--text-color-discreet);
|
color: var(--text-color-discreet);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -52,6 +52,15 @@ const config = {
|
|||||||
},
|
},
|
||||||
query_timeout: parseInt(Deno.env.get("RELAY_TIMEOUT_MS") || "5000"),
|
query_timeout: parseInt(Deno.env.get("RELAY_TIMEOUT_MS") || "5000"),
|
||||||
njump_url: Deno.env.get("NJUMP_URL") || "https://njump.me",
|
njump_url: Deno.env.get("NJUMP_URL") || "https://njump.me",
|
||||||
|
prism: {
|
||||||
|
// TODO make configurable via ENV
|
||||||
|
// Supported languages: https://app.unpkg.com/prismjs@1.29.0/files/components
|
||||||
|
extraLanguages: [
|
||||||
|
"bash",
|
||||||
|
"markdown",
|
||||||
|
"typescript"
|
||||||
|
]
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const staticUsersConfigured = Object.keys(staticUsers).length > 0;
|
const staticUsersConfigured = Object.keys(staticUsers).length > 0;
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
"tasks": {
|
"tasks": {
|
||||||
"dev": "deno run --allow-all --watch server.ts",
|
"dev": "deno run --allow-all --watch server.ts",
|
||||||
"server": "deno run --allow-all server.ts",
|
"server": "deno run --allow-all server.ts",
|
||||||
"compile": "deno compile --allow-all --include ./assets/ --output ./build/substr_x86_64-unknown-linux-gnu server.ts",
|
"compile": "deno compile --allow-all --include ./assets/ --exclude ./tests/ --output ./build/substr_x86_64-unknown-linux-gnu server.ts",
|
||||||
"test": "DENO_ENV=test deno test --allow-read --allow-env"
|
"test": "DENO_ENV=test deno test --allow-read --allow-env"
|
||||||
},
|
},
|
||||||
"imports": {
|
"imports": {
|
||||||
|
|||||||
3
deno.lock
generated
3
deno.lock
generated
@@ -54,6 +54,7 @@
|
|||||||
"npm:nostr-tools@^2.7.0": "2.10.4",
|
"npm:nostr-tools@^2.7.0": "2.10.4",
|
||||||
"npm:nostr-wasm@0.1.0": "0.1.0",
|
"npm:nostr-wasm@0.1.0": "0.1.0",
|
||||||
"npm:path-to-regexp@6.2.1": "6.2.1",
|
"npm:path-to-regexp@6.2.1": "6.2.1",
|
||||||
|
"npm:prismjs@1.29.0": "1.29.0",
|
||||||
"npm:prismjs@^1.29.0": "1.29.0",
|
"npm:prismjs@^1.29.0": "1.29.0",
|
||||||
"npm:sanitize-html@^2.13.0": "2.13.1",
|
"npm:sanitize-html@^2.13.0": "2.13.1",
|
||||||
"npm:websocket-ts@^2.1.5": "2.1.5",
|
"npm:websocket-ts@^2.1.5": "2.1.5",
|
||||||
@@ -71,7 +72,7 @@
|
|||||||
"npm:marked-alert",
|
"npm:marked-alert",
|
||||||
"npm:marked-footnote",
|
"npm:marked-footnote",
|
||||||
"npm:marked-gfm-heading-id",
|
"npm:marked-gfm-heading-id",
|
||||||
"npm:prismjs",
|
"npm:prismjs@^1.29.0",
|
||||||
"npm:sanitize-html"
|
"npm:sanitize-html"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|||||||
10
feeds.ts
10
feeds.ts
@@ -20,6 +20,8 @@ export async function profileAtomFeed(
|
|||||||
<id>${articleId}</id>
|
<id>${articleId}</id>
|
||||||
<title>${article.title}</title>
|
<title>${article.title}</title>
|
||||||
<link href="${article.url}" />
|
<link href="${article.url}" />
|
||||||
|
<link rel="alternate" type="text/html" href="${article.url}" />
|
||||||
|
<link rel="alternate" type="application/nostr+json" href="nostr:${article.naddr}" />
|
||||||
<updated>${isoDate(article.updatedAt)}</updated>
|
<updated>${isoDate(article.updatedAt)}</updated>
|
||||||
<published>${isoDate(article.publishedAt)}</published>
|
<published>${isoDate(article.publishedAt)}</published>
|
||||||
<summary>${article.summary}</summary>
|
<summary>${article.summary}</summary>
|
||||||
@@ -32,13 +34,17 @@ export async function profileAtomFeed(
|
|||||||
|
|
||||||
return `
|
return `
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<feed xmlns="http://www.w3.org/2005/Atom">
|
<feed xmlns="http://www.w3.org/2005/Atom" xmlns:nostr="urn:nostr:protocol">
|
||||||
<title>${profile.name} on Nostr (Articles)</title>
|
<title>${profile.name} on Nostr (Articles)</title>
|
||||||
|
<link rel="alternate" type="text/html" href="${profile.profileUrl}" />
|
||||||
|
<link rel="alternate" type="application/nostr+json" href="nostr:${profile.npub}" />
|
||||||
<id>${feedId}</id>
|
<id>${feedId}</id>
|
||||||
<updated>${isoDate(lastUpdate)}</updated>
|
<updated>${isoDate(lastUpdate)}</updated>
|
||||||
<icon>${profile.avatarImageUrl}</icon>
|
<icon>${profile.avatarImageUrl}</icon>
|
||||||
<author>
|
<author>
|
||||||
<name>${name}</name>
|
<name>${profile.name}</name>
|
||||||
|
<uri>${profile.profileUrl}</uri>
|
||||||
|
<nostr:uri>nostr:${profile.nprofile}</nostr:uri>
|
||||||
</author>
|
</author>
|
||||||
${articlesXml}
|
${articlesXml}
|
||||||
</feed>
|
</feed>
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import { fetchArticlesByAuthor, fetchProfileEvent } from "../nostr.ts";
|
|||||||
import { profileAtomFeed } from "../feeds.ts";
|
import { profileAtomFeed } from "../feeds.ts";
|
||||||
import Profile from "../models/profile.ts";
|
import Profile from "../models/profile.ts";
|
||||||
import { notFoundHandler } from "../handlers/errors.ts";
|
import { notFoundHandler } from "../handlers/errors.ts";
|
||||||
|
import { generateOgProfileImage } from "../magick.ts";
|
||||||
|
|
||||||
const userAtomFeedHandler = async function (ctx: Context) {
|
const userAtomFeedHandler = async function (ctx: Context) {
|
||||||
const username = ctx.state.username;
|
const username = ctx.state.username;
|
||||||
@@ -20,6 +21,7 @@ const userAtomFeedHandler = async function (ctx: Context) {
|
|||||||
const profile = new Profile(profileEvent, username);
|
const profile = new Profile(profileEvent, username);
|
||||||
|
|
||||||
if (profile.nip05) {
|
if (profile.nip05) {
|
||||||
|
await generateOgProfileImage(profile);
|
||||||
const articles = await fetchArticlesByAuthor(pubkey, 10);
|
const articles = await fetchArticlesByAuthor(pubkey, 10);
|
||||||
const atom = await profileAtomFeed(profile, articles);
|
const atom = await profileAtomFeed(profile, articles);
|
||||||
|
|
||||||
|
|||||||
9
html.ts
9
html.ts
@@ -19,6 +19,7 @@ function htmlLayout({ title, body, metaHtml }: HtmlLayoutOptions): string {
|
|||||||
<title>${title}</title>
|
<title>${title}</title>
|
||||||
${metaHtml || ""}
|
${metaHtml || ""}
|
||||||
<link rel="stylesheet" type="text/css" href="/assets/css/layout.css" />
|
<link rel="stylesheet" type="text/css" href="/assets/css/layout.css" />
|
||||||
|
<link rel="stylesheet" type="text/css" href="/assets/css/prism.css" />
|
||||||
<link rel="stylesheet" type="text/css" href="/assets/css/themes/default-light.css" />
|
<link rel="stylesheet" type="text/css" href="/assets/css/themes/default-light.css" />
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
@@ -113,9 +114,6 @@ export function articleListHtml(articles: Article[]): string {
|
|||||||
function userAddressHtml(profile: Profile) {
|
function userAddressHtml(profile: Profile) {
|
||||||
let html = "";
|
let html = "";
|
||||||
|
|
||||||
if (profile.nip05) {
|
|
||||||
html += `<dt>Nostr address</dt><dd>${profile.nip05}</dd>\n`;
|
|
||||||
}
|
|
||||||
if (profile.lud16) {
|
if (profile.lud16) {
|
||||||
html += `<dt>Lightning address</dt><dd>${profile.lud16}</dd>\n`;
|
html += `<dt>Lightning address</dt><dd>${profile.lud16}</dd>\n`;
|
||||||
}
|
}
|
||||||
@@ -212,7 +210,8 @@ function feedLinksHtml(profile: Profile) {
|
|||||||
function profileMetaHtml(profile: Profile) {
|
function profileMetaHtml(profile: Profile) {
|
||||||
return `
|
return `
|
||||||
<link rel="icon" href="${profile.avatarImageUrl}" type="image/png">
|
<link rel="icon" href="${profile.avatarImageUrl}" type="image/png">
|
||||||
<link rel="alternate" type="application/nostr+json" href="nostr:${profile.npub}" title="${profile.name} on Nostr">
|
<link rel="me" type="application/nostr+json" href="nostr:${profile.nprofile}" title="${profile.name}">
|
||||||
|
<link rel="alternate" type="application/nostr+json" href="nostr:${profile.nprofile}" title="${profile.name} on Nostr">
|
||||||
<meta property="og:url" content="${profile.profileUrl}">
|
<meta property="og:url" content="${profile.profileUrl}">
|
||||||
<meta property="og:type" content="website">
|
<meta property="og:type" content="website">
|
||||||
<meta property="og:title" content="${profile.name} on Nostr">
|
<meta property="og:title" content="${profile.name} on Nostr">
|
||||||
@@ -233,6 +232,8 @@ function articleMetaHtml(article: Article, profile: Profile) {
|
|||||||
return `
|
return `
|
||||||
<link rel="icon" href="${profile.avatarImageUrl}" type="image/png">
|
<link rel="icon" href="${profile.avatarImageUrl}" type="image/png">
|
||||||
<link rel="alternate" type="application/nostr+json" href="nostr:${article.naddr}" title="This article on Nostr">
|
<link rel="alternate" type="application/nostr+json" href="nostr:${article.naddr}" title="This article on Nostr">
|
||||||
|
<link rel="author" type="text/html" href="${profile.profileUrl}" title="${profile.name}">
|
||||||
|
<link rel="author" type="application/nostr+json" href="nostr:${profile.nprofile}" title="${profile.name}">
|
||||||
<meta property="og:url" content="${article.url}">
|
<meta property="og:url" content="${article.url}">
|
||||||
<meta property="og:type" content="website">
|
<meta property="og:type" content="website">
|
||||||
<meta property="og:title" content="${article.title}">
|
<meta property="og:title" content="${article.title}">
|
||||||
|
|||||||
2
ldap.ts
2
ldap.ts
@@ -49,6 +49,8 @@ export async function lookupUsernameByPubkey(pubkey: string): Promise<string | u
|
|||||||
if (searchEntries.length > 0) {
|
if (searchEntries.length > 0) {
|
||||||
username = searchEntries[0].cn.toString();
|
username = searchEntries[0].cn.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
await client.unbind();
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
await client.unbind();
|
await client.unbind();
|
||||||
throw e;
|
throw e;
|
||||||
|
|||||||
@@ -4,6 +4,10 @@ import { NostrEvent as NEvent } from "@nostrify/nostrify";
|
|||||||
import { replaceNostrUris } from "../nostr/links.ts";
|
import { replaceNostrUris } from "../nostr/links.ts";
|
||||||
import config from "../config.ts";
|
import config from "../config.ts";
|
||||||
|
|
||||||
|
for (const language of config.prism.extraLanguages) {
|
||||||
|
await import(`npm:prismjs@1.29.0/components/prism-${language}.js`);
|
||||||
|
}
|
||||||
|
|
||||||
export default class Article {
|
export default class Article {
|
||||||
event: NEvent;
|
event: NEvent;
|
||||||
|
|
||||||
|
|||||||
@@ -59,6 +59,13 @@ export default class Profile {
|
|||||||
return nip19.npubEncode(this.pubkey);
|
return nip19.npubEncode(this.pubkey);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get nprofile(): string {
|
||||||
|
return nip19.nprofileEncode({
|
||||||
|
pubkey: this.pubkey,
|
||||||
|
relays: [config.relay_urls[0]],
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
get profileUrl(): string {
|
get profileUrl(): string {
|
||||||
return `${config.base_url}/@${this.username}`;
|
return `${config.base_url}/@${this.username}`;
|
||||||
}
|
}
|
||||||
|
|||||||
140
prism.css
Normal file
140
prism.css
Normal file
@@ -0,0 +1,140 @@
|
|||||||
|
/**
|
||||||
|
* prism.js default theme for JavaScript, CSS and HTML
|
||||||
|
* Based on dabblet (http://dabblet.com)
|
||||||
|
* @author Lea Verou
|
||||||
|
*/
|
||||||
|
|
||||||
|
code[class*="language-"],
|
||||||
|
pre[class*="language-"] {
|
||||||
|
color: black;
|
||||||
|
background: none;
|
||||||
|
text-shadow: 0 1px white;
|
||||||
|
font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace;
|
||||||
|
font-size: 1em;
|
||||||
|
text-align: left;
|
||||||
|
white-space: pre;
|
||||||
|
word-spacing: normal;
|
||||||
|
word-break: normal;
|
||||||
|
word-wrap: normal;
|
||||||
|
line-height: 1.5;
|
||||||
|
|
||||||
|
-moz-tab-size: 4;
|
||||||
|
-o-tab-size: 4;
|
||||||
|
tab-size: 4;
|
||||||
|
|
||||||
|
-webkit-hyphens: none;
|
||||||
|
-moz-hyphens: none;
|
||||||
|
-ms-hyphens: none;
|
||||||
|
hyphens: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
pre[class*="language-"]::-moz-selection, pre[class*="language-"] ::-moz-selection,
|
||||||
|
code[class*="language-"]::-moz-selection, code[class*="language-"] ::-moz-selection {
|
||||||
|
text-shadow: none;
|
||||||
|
background: #b3d4fc;
|
||||||
|
}
|
||||||
|
|
||||||
|
pre[class*="language-"]::selection, pre[class*="language-"] ::selection,
|
||||||
|
code[class*="language-"]::selection, code[class*="language-"] ::selection {
|
||||||
|
text-shadow: none;
|
||||||
|
background: #b3d4fc;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media print {
|
||||||
|
code[class*="language-"],
|
||||||
|
pre[class*="language-"] {
|
||||||
|
text-shadow: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Code blocks */
|
||||||
|
pre[class*="language-"] {
|
||||||
|
padding: 1em;
|
||||||
|
margin: .5em 0;
|
||||||
|
overflow: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
:not(pre) > code[class*="language-"],
|
||||||
|
pre[class*="language-"] {
|
||||||
|
background: #f5f2f0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Inline code */
|
||||||
|
:not(pre) > code[class*="language-"] {
|
||||||
|
padding: .1em;
|
||||||
|
border-radius: .3em;
|
||||||
|
white-space: normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
.token.comment,
|
||||||
|
.token.prolog,
|
||||||
|
.token.doctype,
|
||||||
|
.token.cdata {
|
||||||
|
color: slategray;
|
||||||
|
}
|
||||||
|
|
||||||
|
.token.punctuation {
|
||||||
|
color: #999;
|
||||||
|
}
|
||||||
|
|
||||||
|
.token.namespace {
|
||||||
|
opacity: .7;
|
||||||
|
}
|
||||||
|
|
||||||
|
.token.property,
|
||||||
|
.token.tag,
|
||||||
|
.token.boolean,
|
||||||
|
.token.number,
|
||||||
|
.token.constant,
|
||||||
|
.token.symbol,
|
||||||
|
.token.deleted {
|
||||||
|
color: #905;
|
||||||
|
}
|
||||||
|
|
||||||
|
.token.selector,
|
||||||
|
.token.attr-name,
|
||||||
|
.token.string,
|
||||||
|
.token.char,
|
||||||
|
.token.builtin,
|
||||||
|
.token.inserted {
|
||||||
|
color: #690;
|
||||||
|
}
|
||||||
|
|
||||||
|
.token.operator,
|
||||||
|
.token.entity,
|
||||||
|
.token.url,
|
||||||
|
.language-css .token.string,
|
||||||
|
.style .token.string {
|
||||||
|
color: #9a6e3a;
|
||||||
|
/* This background color was intended by the author of this theme. */
|
||||||
|
background: hsla(0, 0%, 100%, .5);
|
||||||
|
}
|
||||||
|
|
||||||
|
.token.atrule,
|
||||||
|
.token.attr-value,
|
||||||
|
.token.keyword {
|
||||||
|
color: #07a;
|
||||||
|
}
|
||||||
|
|
||||||
|
.token.function,
|
||||||
|
.token.class-name {
|
||||||
|
color: #DD4A68;
|
||||||
|
}
|
||||||
|
|
||||||
|
.token.regex,
|
||||||
|
.token.important,
|
||||||
|
.token.variable {
|
||||||
|
color: #e90;
|
||||||
|
}
|
||||||
|
|
||||||
|
.token.important,
|
||||||
|
.token.bold {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
.token.italic {
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
|
||||||
|
.token.entity {
|
||||||
|
cursor: help;
|
||||||
|
}
|
||||||
@@ -69,7 +69,7 @@ describe("Article", () => {
|
|||||||
describe("#naddr", () => {
|
describe("#naddr", () => {
|
||||||
it("returns a bech32 addressable event ID", () => {
|
it("returns a bech32 addressable event ID", () => {
|
||||||
expect(article.naddr).toMatch(
|
expect(article.naddr).toMatch(
|
||||||
/naddr1qvzqqqr4gupzq8meqkx80g3yuklzymy0qf/,
|
/^naddr1qvzqqqr4gupzq8meqkx80g3yuklzymy0qf/,
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -40,4 +40,12 @@ describe("Profile", () => {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe("#nprofile", () => {
|
||||||
|
it("returns a bech32 profile ID", () => {
|
||||||
|
expect(profile.nprofile).toMatch(
|
||||||
|
/^nprofile1qyt8wumn8ghj7mn0wd68ytntdaek6mmn9ehhyecqyq0hjpvvw73zfed7yf/,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user