mirror of
https://github.com/notion-enhancer/notion-enhancer.git
synced 2025-04-06 21:49:03 +00:00
add mod pages to menu: options & docs (README.md rendered)
This commit is contained in:
parent
5fe31ac703
commit
a5c4d47a6d
3
extension/dep/markdown-it.min.js
vendored
Normal file
3
extension/dep/markdown-it.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
@ -5,6 +5,9 @@
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
import './dep/markdown-it.min.js';
|
||||
|
||||
export const ERROR = Symbol();
|
||||
|
||||
export const env = {};
|
||||
@ -42,7 +45,12 @@ web.whenReady = (selectors = [], callback = () => {}) => {
|
||||
*/
|
||||
web.createElement = (html) => {
|
||||
const template = document.createElement('template');
|
||||
template.innerHTML = html.trim();
|
||||
template.innerHTML = html.includes('<pre')
|
||||
? html.trim()
|
||||
: html
|
||||
.split(/\n/)
|
||||
.map((line) => line.trim())
|
||||
.join('');
|
||||
return template.content.firstElementChild;
|
||||
};
|
||||
|
||||
@ -95,7 +103,7 @@ fs.getText = (path) => fetch(chrome.runtime.getURL(path)).then((res) => res.text
|
||||
|
||||
fs.isFile = async (path) => {
|
||||
try {
|
||||
await fetch(chrome.runtime.getURL(`repo/${path}`));
|
||||
await fetch(chrome.runtime.getURL(path));
|
||||
return true;
|
||||
} catch {
|
||||
return false;
|
||||
@ -137,79 +145,88 @@ export const regexers = {
|
||||
|
||||
export const registry = {};
|
||||
|
||||
registry.validate = async (mod, err, check) =>
|
||||
Promise.all(
|
||||
[
|
||||
check('name', mod.name, typeof mod.name === 'string'),
|
||||
check('id', mod.id, typeof mod.id === 'string').then((id) =>
|
||||
id === ERROR ? ERROR : regexers.uuid(id)
|
||||
),
|
||||
check('description', mod.description, typeof mod.description === 'string'),
|
||||
check('version', mod.version, typeof mod.version === 'string').then((version) =>
|
||||
version === ERROR ? ERROR : regexers.semver(version)
|
||||
),
|
||||
check('tags', mod.tags, Array.isArray(mod.tags)).then((tags) =>
|
||||
tags === ERROR ? ERROR : tags.map((tag) => check('tag', tag, typeof tag === 'string'))
|
||||
),
|
||||
check('authors', mod.authors, Array.isArray(mod.authors)).then((authors) =>
|
||||
authors === ERROR
|
||||
registry.validate = async (mod, err, check) => {
|
||||
let conditions = [
|
||||
check('name', mod.name, typeof mod.name === 'string'),
|
||||
check('id', mod.id, typeof mod.id === 'string').then((id) =>
|
||||
id === ERROR ? ERROR : regexers.uuid(id)
|
||||
),
|
||||
check('version', mod.version, typeof mod.version === 'string').then((version) =>
|
||||
version === ERROR ? ERROR : regexers.semver(version)
|
||||
),
|
||||
check('description', mod.description, typeof mod.description === 'string'),
|
||||
check(
|
||||
'preview',
|
||||
mod.preview,
|
||||
mod.preview === undefined || typeof mod.preview === 'string'
|
||||
).then((preview) =>
|
||||
preview ? (preview === ERROR ? ERROR : regexers.url(preview)) : undefined
|
||||
),
|
||||
check('tags', mod.tags, Array.isArray(mod.tags)).then((tags) =>
|
||||
tags === ERROR ? ERROR : tags.map((tag) => check('tag', tag, typeof tag === 'string'))
|
||||
),
|
||||
check('authors', mod.authors, Array.isArray(mod.authors)).then((authors) =>
|
||||
authors === ERROR
|
||||
? ERROR
|
||||
: authors.map((author) => [
|
||||
check('author.name', author.name, typeof author.name === 'string'),
|
||||
check(
|
||||
'author.email',
|
||||
author.email,
|
||||
typeof author.email === 'string'
|
||||
).then((email) => (email === ERROR ? ERROR : regexers.email(email))),
|
||||
check('author.url', author.url, typeof author.url === 'string').then((url) =>
|
||||
url === ERROR ? ERROR : regexers.url(url)
|
||||
),
|
||||
check('author.icon', author.icon, typeof author.icon === 'string').then((icon) =>
|
||||
icon === ERROR ? ERROR : regexers.url(icon)
|
||||
),
|
||||
])
|
||||
),
|
||||
check(
|
||||
'css',
|
||||
mod.css,
|
||||
mod.css && typeof mod.css === 'object' && !Array.isArray(mod.css)
|
||||
).then((css) =>
|
||||
css
|
||||
? css === ERROR
|
||||
? ERROR
|
||||
: authors.map((author) => [
|
||||
check('author.name', author.name, typeof author.name === 'string'),
|
||||
check(
|
||||
'author.email',
|
||||
author.email,
|
||||
typeof author.email === 'string'
|
||||
).then((email) => (email === ERROR ? ERROR : regexers.email(email))),
|
||||
check('author.url', author.url, typeof author.url === 'string').then((url) =>
|
||||
url === ERROR ? ERROR : regexers.url(url)
|
||||
),
|
||||
check('author.icon', author.icon, typeof author.icon === 'string').then((icon) =>
|
||||
icon === ERROR ? ERROR : regexers.url(icon)
|
||||
),
|
||||
])
|
||||
),
|
||||
check(
|
||||
'css',
|
||||
mod.css,
|
||||
!!mod.css && typeof mod.css === 'object' && !Array.isArray(mod.css)
|
||||
).then((css) => {
|
||||
if (css === ERROR) return ERROR;
|
||||
if (!css) return undefined;
|
||||
return ['frame', 'client', 'menu']
|
||||
.filter((dest) => css[dest])
|
||||
.map(async (dest) =>
|
||||
check(`css.${dest}`, css[dest], Array.isArray(css[dest])).then((files) =>
|
||||
files === ERROR
|
||||
? ERROR
|
||||
: files.map(async (file) =>
|
||||
check(
|
||||
`css.${dest} file`,
|
||||
file,
|
||||
await fs.isFile(`${mod._dir}/${file}`, '.css')
|
||||
)
|
||||
)
|
||||
)
|
||||
);
|
||||
}),
|
||||
check(
|
||||
'js',
|
||||
mod.js,
|
||||
!!mod.js && typeof mod.js === 'object' && !Array.isArray(mod.js)
|
||||
).then(async (js) => {
|
||||
: ['frame', 'client', 'menu']
|
||||
.filter((dest) => css[dest])
|
||||
.map(async (dest) =>
|
||||
check(`css.${dest}`, css[dest], Array.isArray(css[dest])).then((files) =>
|
||||
files === ERROR
|
||||
? ERROR
|
||||
: files.map(async (file) =>
|
||||
check(
|
||||
`css.${dest} file`,
|
||||
file,
|
||||
await fs.isFile(`repo/${mod._dir}/${file}`, '.css')
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
: undefined
|
||||
),
|
||||
check('js', mod.js, mod.js && typeof mod.js === 'object' && !Array.isArray(mod.js)).then(
|
||||
async (js) => {
|
||||
if (js === ERROR) return ERROR;
|
||||
if (!js) return undefined;
|
||||
return [
|
||||
check('js.client', js.client, !js.client ?? Array.isArray(js.client)).then(
|
||||
check('js.client', js.client, !js.client || Array.isArray(js.client)).then(
|
||||
(client) => {
|
||||
if (client === ERROR) return ERROR;
|
||||
if (!client) return undefined;
|
||||
return client.map(async (file) =>
|
||||
check('js.client file', file, await fs.isFile(file, '.js'))
|
||||
check(
|
||||
'js.client file',
|
||||
file,
|
||||
await fs.isFile(`repo/${mod._dir}/${file}`, '.js')
|
||||
)
|
||||
);
|
||||
}
|
||||
),
|
||||
check('js.electron', js.electron, !js.electron ?? Array.isArray(js.electron)).then(
|
||||
check('js.electron', js.electron, !js.electron || Array.isArray(js.electron)).then(
|
||||
(electron) => {
|
||||
if (electron === ERROR) return ERROR;
|
||||
if (!electron) return undefined;
|
||||
@ -217,7 +234,7 @@ registry.validate = async (mod, err, check) =>
|
||||
check(
|
||||
'js.electron file',
|
||||
file,
|
||||
!!file && typeof file === 'object' && !Array.isArray(file)
|
||||
file && typeof file === 'object' && !Array.isArray(file)
|
||||
).then(async (file) =>
|
||||
file === ERROR
|
||||
? ERROR
|
||||
@ -225,7 +242,7 @@ registry.validate = async (mod, err, check) =>
|
||||
check(
|
||||
'js.electron file source',
|
||||
file.source,
|
||||
await fs.isFile(file.source, '.js')
|
||||
await fs.isFile(`repo/${mod._dir}/${file.source}`, '.js')
|
||||
),
|
||||
// referencing the file within the electron app
|
||||
// existence can't be validated, so only format is
|
||||
@ -240,23 +257,86 @@ registry.validate = async (mod, err, check) =>
|
||||
}
|
||||
),
|
||||
];
|
||||
}),
|
||||
check(
|
||||
'options',
|
||||
mod.options,
|
||||
!mod.options ?? (await fs.isFile(mod.options, '.json'))
|
||||
).then(async (filepath) => {
|
||||
if (filepath === ERROR) return ERROR;
|
||||
if (!filepath) return undefined;
|
||||
try {
|
||||
const options = await fs.getJSON(`repo/${mod._dir}/${mod.options}`);
|
||||
// todo: validate options
|
||||
} catch {
|
||||
err(`invalid options ${filepath}`);
|
||||
}
|
||||
}),
|
||||
].flat(Infinity)
|
||||
);
|
||||
}
|
||||
),
|
||||
check('options', mod.options, Array.isArray(mod.options)).then((options) =>
|
||||
options === ERROR
|
||||
? ERROR
|
||||
: options.map((option) => {
|
||||
const conditions = [];
|
||||
switch (option.type) {
|
||||
case 'toggle':
|
||||
conditions.push(
|
||||
check('option.value', option.value, typeof option.value === 'boolean')
|
||||
);
|
||||
break;
|
||||
case 'select':
|
||||
conditions.push(
|
||||
check(
|
||||
'option.values',
|
||||
option.values,
|
||||
Array.isArray(option.values)
|
||||
).then((value) =>
|
||||
value === ERROR
|
||||
? ERROR
|
||||
: value.map((option) =>
|
||||
check('option.values option', option, typeof option === 'string')
|
||||
)
|
||||
)
|
||||
);
|
||||
break;
|
||||
case 'text':
|
||||
conditions.push(
|
||||
check('option.value', option.value, typeof option.value === 'string')
|
||||
);
|
||||
break;
|
||||
case 'number':
|
||||
conditions.push(
|
||||
check('option.value', option.value, typeof option.value === 'number')
|
||||
);
|
||||
break;
|
||||
case 'file':
|
||||
conditions.push(
|
||||
check(
|
||||
'option.extensions',
|
||||
option.extensions,
|
||||
!option.extensions || Array.isArray(option.extensions)
|
||||
).then((extensions) =>
|
||||
extensions
|
||||
? extensions === ERROR
|
||||
? ERROR
|
||||
: extensions.map((ext) =>
|
||||
check('option.extension', ext, typeof ext === 'string')
|
||||
)
|
||||
: undefined
|
||||
)
|
||||
);
|
||||
break;
|
||||
default:
|
||||
return check('option.type', option.type, false);
|
||||
}
|
||||
return [
|
||||
conditions,
|
||||
check(
|
||||
'option.key',
|
||||
option.key,
|
||||
typeof option.key === 'string' && !option.key.match(/\s/)
|
||||
),
|
||||
check('option.label', option.label, typeof option.label === 'string'),
|
||||
check(
|
||||
'option.description',
|
||||
option.description,
|
||||
!option.description || typeof option.description === 'string'
|
||||
),
|
||||
];
|
||||
})
|
||||
),
|
||||
];
|
||||
do {
|
||||
conditions = await Promise.all(conditions.flat(Infinity));
|
||||
} while (conditions.some((condition) => Array.isArray(condition)));
|
||||
return conditions;
|
||||
};
|
||||
|
||||
registry.get = async (callback = () => {}) => {
|
||||
registry._list = [];
|
||||
@ -269,6 +349,7 @@ registry.get = async (callback = () => {}) => {
|
||||
mod.tags = mod.tags ?? [];
|
||||
mod.css = mod.css ?? [];
|
||||
mod.js = mod.js ?? {};
|
||||
mod.options = mod.options ?? [];
|
||||
|
||||
const check = (prop, value, condition) =>
|
||||
Promise.resolve(condition ? value : err(`invalid ${prop} ${JSON.stringify(value)}`)),
|
||||
@ -288,36 +369,10 @@ registry.errors = async (callback = () => {}) => {
|
||||
return registry._errors;
|
||||
};
|
||||
|
||||
export const markdown = {};
|
||||
|
||||
markdown.simple = (string) =>
|
||||
string
|
||||
.split('\n')
|
||||
.map((line) =>
|
||||
line
|
||||
.trim()
|
||||
.replace(/\s+/g, ' ')
|
||||
// > quote
|
||||
.replace(/^>\s+(.+)$/g, '<blockquote>$1</blockquote>')
|
||||
// ~~strikethrough~~
|
||||
.replace(/([^\\])?~~((?:(?!~~).)*[^\\])~~/g, '$1<s>$2</s>')
|
||||
// __underline__
|
||||
.replace(/([^\\])?__((?:(?!__).)*[^\\])__/g, '$1<u>$2</u>')
|
||||
// **bold**
|
||||
.replace(/([^\\])?\*\*((?:(?!\*\*).)*[^\\])\*\*/g, '$1<b>$2</b>')
|
||||
// *italic*
|
||||
.replace(/([^\\])?\*([^*]*[^\\*])\*/g, '$1<i>$2</i>')
|
||||
// _italic_
|
||||
.replace(/([^\\])?_([^_]*[^\\_])_/g, '$1<i>$2</i>')
|
||||
// `code`
|
||||
.replace(/([^\\])?`([^`]*[^\\`])`/g, '$1<code>$2</code>')
|
||||
// 
|
||||
.replace(
|
||||
/([^\\])?\!\[([^\]]*[^\\\]]?)\]\(([^)]*[^\\)])\)/g,
|
||||
`$1<img alt="$2" src="$3" onerror="this.remove()">`
|
||||
)
|
||||
// [link](destination)
|
||||
.replace(/([^\\])?\[([^\]]*[^\\\]]?)\]\(([^)]*[^\\)])\)/g, '$1<a href="$3">$2</a>')
|
||||
)
|
||||
.map((line) => (line.startsWith('<blockquote>') ? line : `<p>${line}</p>`))
|
||||
.join('');
|
||||
export const markdown = new markdownit({
|
||||
linkify: true,
|
||||
highlight(...args) {
|
||||
console.log(args);
|
||||
return '';
|
||||
},
|
||||
});
|
||||
|
@ -16,5 +16,6 @@ import(chrome.runtime.getURL('helpers.js')).then(({ web, registry }) => {
|
||||
import(chrome.runtime.getURL(`repo/${mod._dir}/${script}`));
|
||||
}
|
||||
}
|
||||
console.log(await registry.errors());
|
||||
});
|
||||
});
|
||||
|
@ -0,0 +1,322 @@
|
||||
# markdown tester
|
||||
|
||||
## table
|
||||
|
||||
| option | extended description | type | values/defaults | platform-specific details |
|
||||
| ---------------------------- | ---------------------------------------------------------------------------------------------------------- | ------------ | --------------- | ------------------------- |
|
||||
| height of frameless dragarea | the rectangle added at the top of a window in "integrated titlebar" mode, used to drag/move the window. | number input | 15 | macOS: forced to 0 |
|
||||
| width to wrap columns at | the size in pixels below which in-page columns are resized to appear full width so content isn't squished. | number input | 600 | |
|
||||
| integrated scrollbars | use scrollbars that fit better into notion's ui instead of the default chrome ones. | toggle | yes | |
|
||||
| snappy transitions | | toggle | no | |
|
||||
| thicker bold text | | toggle | yes | |
|
||||
| more readable line spacing | | toggle | no | |
|
||||
| hide help button | | toggle | no | |
|
||||
|
||||
# Markdown: Syntax
|
||||
|
||||
- [Overview](#overview)
|
||||
- [Philosophy](#philosophy)
|
||||
- [Inline HTML](#html)
|
||||
- [Automatic Escaping for Special Characters](#autoescape)
|
||||
- [Block Elements](#block)
|
||||
- [Paragraphs and Line Breaks](#p)
|
||||
- [Headers](#header)
|
||||
- [Blockquotes](#blockquote)
|
||||
- [Lists](#list)
|
||||
- [Code Blocks](#precode)
|
||||
- [Horizontal Rules](#hr)
|
||||
- [Span Elements](#span)
|
||||
- [Links](#link)
|
||||
- [Emphasis](#em)
|
||||
- [Code](#code)
|
||||
- [Images](#img)
|
||||
- [Miscellaneous](#misc)
|
||||
- [Backslash Escapes](#backslash)
|
||||
- [Automatic Links](#autolink)
|
||||
|
||||
**Note:** This document is itself written using Markdown; you
|
||||
can [see the source for it by adding '.text' to the URL](/projects/markdown/syntax.text).
|
||||
|
||||
---
|
||||
|
||||
## Overview
|
||||
|
||||
### Philosophy
|
||||
|
||||
Markdown is intended to be as easy-to-read and easy-to-write as is feasible.
|
||||
|
||||
Readability, however, is emphasized above all else. A Markdown-formatted
|
||||
document should be publishable as-is, as plain text, without looking
|
||||
like it's been marked up with tags or formatting instructions. While
|
||||
Markdown's syntax has been influenced by several existing text-to-HTML
|
||||
filters -- including [Setext](http://docutils.sourceforge.net/mirror/setext.html), [atx](http://www.aaronsw.com/2002/atx/), [Textile](http://textism.com/tools/textile/), [reStructuredText](http://docutils.sourceforge.net/rst.html),
|
||||
[Grutatext](http://www.triptico.com/software/grutatxt.html), and [EtText](http://ettext.taint.org/doc/) -- the single biggest source of
|
||||
inspiration for Markdown's syntax is the format of plain text email.
|
||||
|
||||
## Block Elements
|
||||
|
||||
### Paragraphs and Line Breaks
|
||||
|
||||
A paragraph is simply one or more consecutive lines of text, separated
|
||||
by one or more blank lines. (A blank line is any line that looks like a
|
||||
blank line -- a line containing nothing but spaces or tabs is considered
|
||||
blank.) Normal paragraphs should not be indented with spaces or tabs.
|
||||
|
||||
The implication of the "one or more consecutive lines of text" rule is
|
||||
that Markdown supports "hard-wrapped" text paragraphs. This differs
|
||||
significantly from most other text-to-HTML formatters (including Movable
|
||||
Type's "Convert Line Breaks" option) which translate every line break
|
||||
character in a paragraph into a `<br />` tag.
|
||||
|
||||
When you _do_ want to insert a `<br />` break tag using Markdown, you
|
||||
end a line with two or more spaces, then type return.
|
||||
|
||||
### Headers
|
||||
|
||||
Markdown supports two styles of headers, [Setext] [1] and [atx] [2].
|
||||
|
||||
Optionally, you may "close" atx-style headers. This is purely
|
||||
cosmetic -- you can use this if you think it looks better. The
|
||||
closing hashes don't even need to match the number of hashes
|
||||
used to open the header. (The number of opening hashes
|
||||
determines the header level.)
|
||||
|
||||
### Blockquotes
|
||||
|
||||
Markdown uses email-style `>` characters for blockquoting. If you're
|
||||
familiar with quoting passages of text in an email message, then you
|
||||
know how to create a blockquote in Markdown. It looks best if you hard
|
||||
wrap the text and put a `>` before every line:
|
||||
|
||||
> This is a blockquote with two paragraphs. Lorem ipsum dolor sit amet,
|
||||
> consectetuer adipiscing elit. Aliquam hendrerit mi posuere lectus.
|
||||
> Vestibulum enim wisi, viverra nec, fringilla in, laoreet vitae, risus.
|
||||
>
|
||||
> Donec sit amet nisl. Aliquam semper ipsum sit amet velit. Suspendisse
|
||||
> id sem consectetuer libero luctus adipiscing.
|
||||
|
||||
Markdown allows you to be lazy and only put the `>` before the first
|
||||
line of a hard-wrapped paragraph:
|
||||
|
||||
> This is a blockquote with two paragraphs. Lorem ipsum dolor sit amet,
|
||||
> consectetuer adipiscing elit. Aliquam hendrerit mi posuere lectus.
|
||||
> Vestibulum enim wisi, viverra nec, fringilla in, laoreet vitae, risus.
|
||||
|
||||
> Donec sit amet nisl. Aliquam semper ipsum sit amet velit. Suspendisse
|
||||
> id sem consectetuer libero luctus adipiscing.
|
||||
|
||||
Blockquotes can be nested (i.e. a blockquote-in-a-blockquote) by
|
||||
adding additional levels of `>`:
|
||||
|
||||
> This is the first level of quoting.
|
||||
>
|
||||
> > This is nested blockquote.
|
||||
>
|
||||
> Back to the first level.
|
||||
|
||||
Blockquotes can contain other Markdown elements, including headers, lists,
|
||||
and code blocks:
|
||||
|
||||
> ## This is a header.
|
||||
>
|
||||
> 1. This is the first list item.
|
||||
> 2. This is the second list item.
|
||||
>
|
||||
> Here's some example code:
|
||||
>
|
||||
> return shell_exec("echo $input | $markdown_script");
|
||||
|
||||
Any decent text editor should make email-style quoting easy. For
|
||||
example, with BBEdit, you can make a selection and choose Increase
|
||||
Quote Level from the Text menu.
|
||||
|
||||
### Lists
|
||||
|
||||
Markdown supports ordered (numbered) and unordered (bulleted) lists.
|
||||
|
||||
Unordered lists use asterisks, pluses, and hyphens -- interchangably
|
||||
-- as list markers:
|
||||
|
||||
- Red
|
||||
- Green
|
||||
- Blue
|
||||
|
||||
is equivalent to:
|
||||
|
||||
- Red
|
||||
- Green
|
||||
- Blue
|
||||
|
||||
and:
|
||||
|
||||
- Red
|
||||
- Green
|
||||
- Blue
|
||||
|
||||
Ordered lists use numbers followed by periods:
|
||||
|
||||
1. Bird
|
||||
2. McHale
|
||||
3. Parish
|
||||
|
||||
It's important to note that the actual numbers you use to mark the
|
||||
list have no effect on the HTML output Markdown produces. The HTML
|
||||
Markdown produces from the above list is:
|
||||
|
||||
If you instead wrote the list in Markdown like this:
|
||||
|
||||
1. Bird
|
||||
1. McHale
|
||||
1. Parish
|
||||
|
||||
or even:
|
||||
|
||||
3. Bird
|
||||
1. McHale
|
||||
1. Parish
|
||||
|
||||
you'd get the exact same HTML output. The point is, if you want to,
|
||||
you can use ordinal numbers in your ordered Markdown lists, so that
|
||||
the numbers in your source match the numbers in your published HTML.
|
||||
But if you want to be lazy, you don't have to.
|
||||
|
||||
To make lists look nice, you can wrap items with hanging indents:
|
||||
|
||||
- Lorem ipsum dolor sit amet, consectetuer adipiscing elit.
|
||||
Aliquam hendrerit mi posuere lectus. Vestibulum enim wisi,
|
||||
viverra nec, fringilla in, laoreet vitae, risus.
|
||||
- Donec sit amet nisl. Aliquam semper ipsum sit amet velit.
|
||||
Suspendisse id sem consectetuer libero luctus adipiscing.
|
||||
|
||||
But if you want to be lazy, you don't have to:
|
||||
|
||||
- Lorem ipsum dolor sit amet, consectetuer adipiscing elit.
|
||||
Aliquam hendrerit mi posuere lectus. Vestibulum enim wisi,
|
||||
viverra nec, fringilla in, laoreet vitae, risus.
|
||||
- Donec sit amet nisl. Aliquam semper ipsum sit amet velit.
|
||||
Suspendisse id sem consectetuer libero luctus adipiscing.
|
||||
|
||||
List items may consist of multiple paragraphs. Each subsequent
|
||||
paragraph in a list item must be indented by either 4 spaces
|
||||
or one tab:
|
||||
|
||||
1. This is a list item with two paragraphs. Lorem ipsum dolor
|
||||
sit amet, consectetuer adipiscing elit. Aliquam hendrerit
|
||||
mi posuere lectus.
|
||||
|
||||
Vestibulum enim wisi, viverra nec, fringilla in, laoreet
|
||||
vitae, risus. Donec sit amet nisl. Aliquam semper ipsum
|
||||
sit amet velit.
|
||||
|
||||
2. Suspendisse id sem consectetuer libero luctus adipiscing.
|
||||
|
||||
It looks nice if you indent every line of the subsequent
|
||||
paragraphs, but here again, Markdown will allow you to be
|
||||
lazy:
|
||||
|
||||
- This is a list item with two paragraphs.
|
||||
|
||||
This is the second paragraph in the list item. You're
|
||||
|
||||
only required to indent the first line. Lorem ipsum dolor
|
||||
sit amet, consectetuer adipiscing elit.
|
||||
|
||||
- Another item in the same list.
|
||||
|
||||
To put a blockquote within a list item, the blockquote's `>`
|
||||
delimiters need to be indented:
|
||||
|
||||
- A list item with a blockquote:
|
||||
|
||||
> This is a blockquote
|
||||
> inside a list item.
|
||||
|
||||
To put a code block within a list item, the code block needs
|
||||
to be indented _twice_ -- 8 spaces or two tabs:
|
||||
|
||||
- A list item with a code block:
|
||||
|
||||
<code goes here>
|
||||
|
||||
### Code Blocks
|
||||
|
||||
Pre-formatted code blocks are used for writing about programming or
|
||||
markup source code. Rather than forming normal paragraphs, the lines
|
||||
of a code block are interpreted literally. Markdown wraps a code block
|
||||
in both `<pre>` and `<code>` tags.
|
||||
|
||||
To produce a code block in Markdown, simply indent every line of the
|
||||
block by at least 4 spaces or 1 tab.
|
||||
|
||||
This is a normal paragraph:
|
||||
|
||||
This is a code block.
|
||||
|
||||
Here is an example of AppleScript:
|
||||
|
||||
tell application "Foo"
|
||||
beep
|
||||
end tell
|
||||
|
||||
A code block continues until it reaches a line that is not indented
|
||||
(or the end of the article).
|
||||
|
||||
Within a code block, ampersands (`&`) and angle brackets (`<` and `>`)
|
||||
are automatically converted into HTML entities. This makes it very
|
||||
easy to include example HTML source code using Markdown -- just paste
|
||||
it and indent it, and Markdown will handle the hassle of encoding the
|
||||
ampersands and angle brackets. For example, this:
|
||||
|
||||
<div class="footer">
|
||||
© 2004 Foo Corporation
|
||||
</div>
|
||||
|
||||
Regular Markdown syntax is not processed within code blocks. E.g.,
|
||||
asterisks are just literal asterisks within a code block. This means
|
||||
it's also easy to use Markdown to write about Markdown's own syntax.
|
||||
|
||||
```
|
||||
tell application "Foo"
|
||||
beep
|
||||
end tell
|
||||
```
|
||||
|
||||
## Span Elements
|
||||
|
||||
### Links
|
||||
|
||||
Markdown supports two style of links: _inline_ and _reference_.
|
||||
|
||||
In both styles, the link text is delimited by [square brackets].
|
||||
|
||||
To create an inline link, use a set of regular parentheses immediately
|
||||
after the link text's closing square bracket. Inside the parentheses,
|
||||
put the URL where you want the link to point, along with an _optional_
|
||||
title for the link, surrounded in quotes. For example:
|
||||
|
||||
This is [an example](http://example.com/) inline link.
|
||||
|
||||
[This link](http://example.net/) has no title attribute.
|
||||
|
||||
### Emphasis
|
||||
|
||||
Markdown treats asterisks (`*`) and underscores (`_`) as indicators of
|
||||
emphasis. Text wrapped with one `*` or `_` will be wrapped with an
|
||||
HTML `<em>` tag; double `*`'s or `_`'s will be wrapped with an HTML
|
||||
`<strong>` tag. E.g., this input:
|
||||
|
||||
_single asterisks_
|
||||
|
||||
_single underscores_
|
||||
|
||||
**double asterisks**
|
||||
|
||||
**double underscores**
|
||||
|
||||
### Code
|
||||
|
||||
To indicate a span of code, wrap it with backtick quotes (`` ` ``).
|
||||
Unlike a pre-formatted code block, a code span indicates code within a
|
||||
normal paragraph. For example:
|
||||
|
||||
Use the `printf()` function.
|
@ -0,0 +1,2 @@
|
||||
<!-- https://fontawesome.com/icons/file?style=solid -->
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 384 512"><path fill="currentColor" d="M224 136V0H24C10.7 0 0 10.7 0 24v464c0 13.3 10.7 24 24 24h336c13.3 0 24-10.7 24-24V160H248c-13.2 0-24-10.8-24-24zm160-14.1v6.1H256V0h6.1c6.4 0 12.5 2.5 17 7l97.9 98c4.5 4.5 7 10.6 7 16.9z"/></svg>
|
After Width: | Height: | Size: 343 B |
@ -33,28 +33,105 @@ header h1 a:not([data-active]) {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
main section[data-container='library'] {
|
||||
main section[data-container] {
|
||||
display: grid;
|
||||
grid-gap: 1.25em;
|
||||
grid-template-columns: 1fr 1fr 1fr;
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
main section[data-container='library'] article {
|
||||
@media (min-width: 550px) {
|
||||
main section[data-container] {
|
||||
grid-template-columns: 1fr 1fr;
|
||||
}
|
||||
main section[data-container='page'] > .documentation--buttons {
|
||||
grid-column: span 2;
|
||||
}
|
||||
}
|
||||
@media (min-width: 850px) {
|
||||
main section[data-container] {
|
||||
grid-template-columns: 1fr 1fr 1fr;
|
||||
}
|
||||
main section[data-container='page'] > .documentation--buttons {
|
||||
grid-column: span 3;
|
||||
}
|
||||
main section[data-container='page'] > .documentation--body {
|
||||
grid-column: span 2;
|
||||
}
|
||||
}
|
||||
@media (min-width: 1350px) {
|
||||
main section[data-container] {
|
||||
grid-template-columns: 1fr 1fr 1fr 1fr;
|
||||
}
|
||||
main section[data-container='page'] > .documentation--buttons {
|
||||
grid-column: span 4;
|
||||
}
|
||||
main section[data-container='page'] > .documentation--body {
|
||||
grid-column: span 3;
|
||||
}
|
||||
}
|
||||
@media (min-width: 2050px) {
|
||||
main section[data-container] {
|
||||
grid-template-columns: 1fr 1fr 1fr 1fr 1fr;
|
||||
}
|
||||
main section[data-container='page'] > .documentation--buttons {
|
||||
grid-column: span 5;
|
||||
}
|
||||
main section[data-container='page'] > .documentation--body {
|
||||
grid-column: span 4;
|
||||
}
|
||||
}
|
||||
main section[data-container] article {
|
||||
border-radius: 5px;
|
||||
box-shadow: rgb(0 0 0 / 10%) 0px 20px 25px -5px, rgb(0 0 0 / 4%) 0px 10px 10px -5px;
|
||||
border: 1px solid var(--theme--divider);
|
||||
background: var(--theme--page);
|
||||
}
|
||||
main section[data-container='library'] article > img {
|
||||
main section[data-container] article img {
|
||||
max-width: 100%;
|
||||
}
|
||||
main section[data-container] article > img {
|
||||
border-bottom: 1px solid var(--theme--divider);
|
||||
}
|
||||
main section[data-container='library'] article > div {
|
||||
padding: 1em;
|
||||
border-bottom: 1px solid var(--theme--divider);
|
||||
main section[data-container] article > div {
|
||||
padding: 1rem;
|
||||
}
|
||||
.library--title {
|
||||
|
||||
.documentation--buttons,
|
||||
.library--expand {
|
||||
margin: 0;
|
||||
display: flex;
|
||||
}
|
||||
.library--expand a {
|
||||
margin-left: auto;
|
||||
}
|
||||
.documentation--buttons a,
|
||||
.library--expand a {
|
||||
border-radius: 3px;
|
||||
padding: 0.35rem 0.45rem;
|
||||
text-decoration: none;
|
||||
display: flex;
|
||||
}
|
||||
.documentation--buttons span,
|
||||
.library--expand span {
|
||||
color: var(--theme--text_property);
|
||||
}
|
||||
.documentation--buttons a:hover,
|
||||
.library--expand a:hover {
|
||||
background: var(--theme--button-hover);
|
||||
}
|
||||
.documentation--buttons svg,
|
||||
.library--expand svg {
|
||||
width: 1em;
|
||||
height: 1em;
|
||||
padding-top: 2px;
|
||||
margin-right: 0.3rem;
|
||||
}
|
||||
.documentation--buttons svg polygon,
|
||||
.documentation--buttons svg path,
|
||||
.library--expand svg polygon,
|
||||
.library--expand svg path {
|
||||
fill: var(--theme--text_property);
|
||||
}
|
||||
|
||||
.library--version {
|
||||
font-weight: normal;
|
||||
font-size: 0.8rem;
|
||||
@ -63,58 +140,16 @@ main section[data-container='library'] article > div {
|
||||
background: var(--theme--tag_default);
|
||||
color: var(--theme--tag_default-text);
|
||||
}
|
||||
.library--toggle_label {
|
||||
align-items: center;
|
||||
display: flex;
|
||||
cursor: pointer;
|
||||
}
|
||||
.library--toggle {
|
||||
position: relative;
|
||||
margin-left: auto;
|
||||
}
|
||||
.library--toggle {
|
||||
width: 2rem;
|
||||
height: 1.25rem;
|
||||
display: block;
|
||||
border-radius: 9999px;
|
||||
background: var(--theme--toggle_off);
|
||||
}
|
||||
.library--toggle::after {
|
||||
content: '';
|
||||
transition: transform 200ms ease-out 0s, background 200ms ease-out 0s;
|
||||
height: 0.85rem;
|
||||
width: 0.8rem;
|
||||
left: 0.18rem;
|
||||
top: 0.175rem;
|
||||
position: absolute;
|
||||
border-radius: 9999px;
|
||||
background: var(--theme--toggle_dot);
|
||||
}
|
||||
.library--toggle_label input[type='checkbox']:checked ~ .library--toggle {
|
||||
background: var(--theme--toggle_on);
|
||||
}
|
||||
.library--toggle_label input[type='checkbox']:checked ~ .library--toggle::after {
|
||||
transform: translateX(100%);
|
||||
}
|
||||
.library--toggle_label input[type='checkbox'] {
|
||||
position: absolute;
|
||||
width: 1px;
|
||||
height: 1px;
|
||||
padding: 0;
|
||||
margin: -1px;
|
||||
overflow: hidden;
|
||||
clip: rect(0, 0, 0, 0);
|
||||
white-space: nowrap;
|
||||
border-width: 0;
|
||||
}
|
||||
.library--description {
|
||||
font-size: 0.8rem;
|
||||
margin: 0.25rem 0;
|
||||
}
|
||||
.library--tags,
|
||||
.library--authors {
|
||||
padding: 0;
|
||||
list-style-type: none;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
margin: 0.5em 0;
|
||||
}
|
||||
.library--tags li {
|
||||
@ -128,9 +163,7 @@ main section[data-container='library'] article > div {
|
||||
font-size: 0.8rem;
|
||||
text-decoration: none;
|
||||
border-radius: 5px;
|
||||
padding: 0.125rem 0.25rem 0.25rem 0.25rem;
|
||||
background: var(--theme--tag_default);
|
||||
color: var(--theme--tag_default-text);
|
||||
padding: 0.125rem 0.25rem 0.25rem 0;
|
||||
}
|
||||
.library--authors img {
|
||||
height: 1em;
|
||||
@ -142,6 +175,206 @@ main section[data-container='library'] article > div {
|
||||
object-fit: cover;
|
||||
}
|
||||
|
||||
main section:not([data-active]) {
|
||||
display: none;
|
||||
.library--options {
|
||||
border-top: 1px solid var(--theme--divider);
|
||||
}
|
||||
.library--toggle_label,
|
||||
.library--select_label,
|
||||
.library--text_label,
|
||||
.library--number_label,
|
||||
.library--file_label {
|
||||
margin: 0.6rem 0;
|
||||
display: block;
|
||||
appearance: none;
|
||||
font-size: 0.8rem;
|
||||
}
|
||||
.library--toggle_label *,
|
||||
.library--select_label *,
|
||||
.library--text_label *,
|
||||
.library--number_label *,
|
||||
.library--file_label * {
|
||||
appearance: none;
|
||||
font-size: 0.8rem;
|
||||
}
|
||||
.library--toggle_label > p,
|
||||
.library--toggle_label > p,
|
||||
.library--select_label > p,
|
||||
.library--text_label > p,
|
||||
.library--number_label > p,
|
||||
.library--file_label > p {
|
||||
margin: 0.6rem 0;
|
||||
}
|
||||
.library--toggle_label > :not(input) {
|
||||
align-items: center;
|
||||
display: flex;
|
||||
cursor: pointer;
|
||||
--toggle--buttonsground: var(--theme--toggle_off);
|
||||
--toggle--translation: 0%;
|
||||
}
|
||||
.library--toggle_label > :not(input) .library--toggle {
|
||||
position: relative;
|
||||
margin: auto 0 auto auto;
|
||||
width: 2.25rem;
|
||||
height: 1.25rem;
|
||||
display: block;
|
||||
border-radius: 40px;
|
||||
background: var(--toggle--buttonsground);
|
||||
}
|
||||
.library--toggle_label > :not(input) .library--toggle::after {
|
||||
content: '';
|
||||
transition: transform 200ms ease-out 0s, background 200ms ease-out 0s;
|
||||
height: 0.8rem;
|
||||
width: 0.8rem;
|
||||
left: 0.325rem;
|
||||
top: 0.225rem;
|
||||
position: absolute;
|
||||
border-radius: 100%;
|
||||
background: var(--theme--toggle_dot);
|
||||
transform: translateX(var(--toggle--translation));
|
||||
}
|
||||
.library--toggle_label input[type='checkbox']:checked + :not(input) {
|
||||
--toggle--buttonsground: var(--theme--toggle_on);
|
||||
--toggle--translation: 100%;
|
||||
}
|
||||
.library--toggle_label:focus-within .library--toggle,
|
||||
.library--file_label:focus-within .library--file,
|
||||
.library--select_label .library--select:focus-within {
|
||||
outline: solid thin;
|
||||
}
|
||||
.library--toggle_label input[type='checkbox'],
|
||||
.library--file_label input {
|
||||
position: absolute;
|
||||
width: 1px;
|
||||
height: 1px;
|
||||
padding: 0;
|
||||
margin: -1px;
|
||||
overflow: hidden;
|
||||
clip: rect(0, 0, 0, 0);
|
||||
white-space: nowrap;
|
||||
border-width: 0;
|
||||
}
|
||||
.library--text_label textarea {
|
||||
resize: none;
|
||||
min-height: calc(1em + 16px);
|
||||
height: var(--txt--scroll-height);
|
||||
}
|
||||
.library--text_label textarea,
|
||||
.library--number_label input,
|
||||
.library--select_label .library--select,
|
||||
.library--file_label .library--file {
|
||||
width: 100%;
|
||||
padding: 6px 8px;
|
||||
background: var(--theme--input);
|
||||
border-radius: 3px;
|
||||
border: none;
|
||||
box-shadow: var(--theme--input-border) 0px 0px 0px 1px inset;
|
||||
--theme--input_icon: var(--theme_dark--input_icon);
|
||||
}
|
||||
.library--select_label .library--select select {
|
||||
outline: none;
|
||||
}
|
||||
.library--select_label .library--select select option {
|
||||
background: var(--theme_dark--tag_select);
|
||||
}
|
||||
.library--select_label .library--select,
|
||||
.library--file_label .library--file {
|
||||
padding: 0;
|
||||
display: flex;
|
||||
}
|
||||
.library--select_label .library--select > :first-child,
|
||||
.library--file_label .library--file > :first-child {
|
||||
display: flex;
|
||||
padding: 6px 8px;
|
||||
background: var(--theme--input-border);
|
||||
}
|
||||
.library--select_label .library--select > :first-child svg,
|
||||
.library--file_label .library--file > :first-child svg {
|
||||
width: 0.9em;
|
||||
margin: auto 0;
|
||||
}
|
||||
.library--select_label .library--select > :last-child,
|
||||
.library--file_label .library--file > :last-child {
|
||||
margin: auto 0;
|
||||
padding: 6px 8px;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border: none;
|
||||
background: none;
|
||||
}
|
||||
.library--title {
|
||||
margin: 0;
|
||||
}
|
||||
.library--title h2 {
|
||||
margin: 0;
|
||||
}
|
||||
.library--title h2 > span {
|
||||
font-size: 1.25rem;
|
||||
padding-bottom: 0.25rem;
|
||||
}
|
||||
|
||||
.library--full_card,
|
||||
.documentation--body {
|
||||
max-height: calc(100vh - 10rem);
|
||||
overflow: auto;
|
||||
}
|
||||
.documentation--body {
|
||||
padding: 1rem 2rem;
|
||||
font-size: 0.8rem;
|
||||
}
|
||||
.documentation--body table {
|
||||
border-spacing: 0;
|
||||
border: 1px solid var(--theme--sidebar);
|
||||
}
|
||||
.documentation--body table th {
|
||||
text-align: left;
|
||||
}
|
||||
.documentation--body table th,
|
||||
.documentation--body table td {
|
||||
padding: 5px 8px 6px;
|
||||
border: 1px solid var(--theme--sidebar);
|
||||
}
|
||||
.documentation--body h1 {
|
||||
font-size: var(--theme--font_heading1-size);
|
||||
margin: 1rem 0 0.5rem 0;
|
||||
}
|
||||
.documentation--body h2 {
|
||||
font-size: var(--theme--font_heading2-size);
|
||||
margin: 1rem 0 0.5rem 0;
|
||||
}
|
||||
.documentation--body h3 {
|
||||
font-size: var(--theme--font_heading3-size);
|
||||
margin: 1rem 0 0.5rem 0;
|
||||
}
|
||||
.documentation--body ul,
|
||||
.documentation--body ol {
|
||||
padding-left: 1.25rem;
|
||||
}
|
||||
.documentation--body li {
|
||||
margin: 0.4rem 0;
|
||||
}
|
||||
.documentation--body ol li {
|
||||
padding-left: 0.25rem;
|
||||
}
|
||||
.documentation--body blockquote {
|
||||
border-left: 2px solid currentColor;
|
||||
padding-left: 0.5rem;
|
||||
margin: 0.5rem 0 0.5rem 0;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar {
|
||||
background: transparent;
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
}
|
||||
::-webkit-scrollbar-track {
|
||||
background: var(--theme--scrollbar_track);
|
||||
}
|
||||
::-webkit-scrollbar-corner {
|
||||
background: var(--theme--scrollbar_track);
|
||||
}
|
||||
::-webkit-scrollbar-thumb {
|
||||
background: var(--theme--scrollbar_thumb);
|
||||
}
|
||||
::-webkit-scrollbar-thumb:hover {
|
||||
background: var(--theme--scrollbar_thumb-hover);
|
||||
}
|
||||
|
@ -9,150 +9,13 @@
|
||||
<body>
|
||||
<header>
|
||||
<p><img width="24" src="../../icons/colour.svg" /></p>
|
||||
<h1><a href="#" data-target="library" data-active>library</a></h1>
|
||||
<h1><a href="#" data-target="alerts">alerts</a></h1>
|
||||
<h1><a href="#" data-target="documentation">documentation</a></h1>
|
||||
<h1><a href="?" data-target="library" data-active>library</a></h1>
|
||||
<h1><a href="?" data-target="alerts">alerts</a></h1>
|
||||
<h1><a href="https://github.com/notion-enhancer/extension">github</a></h1>
|
||||
<h1><a href="https://discord.gg/sFWPXtA">discord</a></h1>
|
||||
</header>
|
||||
<main>
|
||||
<section data-container="library" data-active>
|
||||
<article>
|
||||
<div>
|
||||
<label for="library.enable--ID1" class="library--toggle_label">
|
||||
<h2 class="library--title">
|
||||
custom inserts <span class="library--version">v0.2.0</span>
|
||||
</h2>
|
||||
<input type="checkbox" id="library.enable--ID1" checked />
|
||||
<span class="library--toggle"></span>
|
||||
</label>
|
||||
<ul class="library--tags">
|
||||
<li>#core</li>
|
||||
<li>#extension</li>
|
||||
<li>#customisation</li>
|
||||
</ul>
|
||||
<p class="library--description">
|
||||
link files for small client-side tweaks. (not sure how to do something? check out
|
||||
the
|
||||
<a
|
||||
href="https://github.com/notion-enhancer/notion-enhancer/blob/master/TWEAKS.md"
|
||||
>tweaks</a
|
||||
>
|
||||
collection.)
|
||||
</p>
|
||||
<ul class="library--authors">
|
||||
<li>
|
||||
<a href="https://dragonwocky.me"
|
||||
><img src="https://dragonwocky.me/avatar.jpg" /> <span>dragonwocky</span></a
|
||||
>
|
||||
</li>
|
||||
<li>
|
||||
<a href="https://dragonwocky.me"
|
||||
><img src="https://dragonwocky.me/avatar.jpg" /> <span>dragonwocky</span></a
|
||||
>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</article>
|
||||
<article>
|
||||
<img
|
||||
alt=""
|
||||
class="library--preview"
|
||||
src="https://raw.githubusercontent.com/notion-enhancer/notion-enhancer/dev/notion-enhancer%20v0.10.0%20banner.jpg"
|
||||
/>
|
||||
<div>
|
||||
<label for="library.enable--ID2" class="library--toggle_label">
|
||||
<h2 class="library--title">
|
||||
dark+ <span class="library--version">v0.2.0</span>
|
||||
</h2>
|
||||
<input type="checkbox" id="library.enable--ID2" />
|
||||
<span class="library--toggle"></span>
|
||||
</label>
|
||||
<ul class="library--tags">
|
||||
<li>#core</li>
|
||||
<li>#theme</li>
|
||||
<li>#dark</li>
|
||||
</ul>
|
||||
<p class="library--description">a vivid-colour near-black theme</p>
|
||||
<ul class="library--authors">
|
||||
<li>
|
||||
<a href="https://dragonwocky.me"
|
||||
><img src="https://dragonwocky.me/avatar.jpg" /> <span>dragonwocky</span></a
|
||||
>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</article>
|
||||
<article>
|
||||
<div>
|
||||
<label for="library.enable--ID3" class="library--toggle_label">
|
||||
<h2 class="library--title">
|
||||
custom inserts <span class="library--version">v0.2.0</span>
|
||||
</h2>
|
||||
<input type="checkbox" id="library.enable--ID3" checked />
|
||||
<span class="library--toggle"></span>
|
||||
</label>
|
||||
<ul class="library--tags">
|
||||
<li>#core</li>
|
||||
<li>#extension</li>
|
||||
<li>#customisation</li>
|
||||
</ul>
|
||||
<p class="library--description">
|
||||
link files for small client-side tweaks. (not sure how to do something? check out
|
||||
the
|
||||
<a
|
||||
href="https://github.com/notion-enhancer/notion-enhancer/blob/master/TWEAKS.md"
|
||||
>tweaks</a
|
||||
>
|
||||
collection.)
|
||||
</p>
|
||||
<ul class="library--authors">
|
||||
<li>
|
||||
<a href="https://dragonwocky.me"
|
||||
><img src="https://dragonwocky.me/avatar.jpg" /> <span>dragonwocky</span></a
|
||||
>
|
||||
</li>
|
||||
<li>
|
||||
<a href="https://dragonwocky.me"
|
||||
><img src="https://dragonwocky.me/avatar.jpg" /> <span>dragonwocky</span></a
|
||||
>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</article>
|
||||
<article>
|
||||
<div>
|
||||
<label for="library.enable--ID4" class="library--toggle_label">
|
||||
<h2 class="library--title">
|
||||
custom inserts <span class="library--version">v0.2.0</span>
|
||||
</h2>
|
||||
<input type="checkbox" id="library.enable--ID4" />
|
||||
<span class="library--toggle"></span>
|
||||
</label>
|
||||
<ul class="library--tags">
|
||||
<li>#core</li>
|
||||
<li>#extension</li>
|
||||
<li>#customisation</li>
|
||||
</ul>
|
||||
<p class="library--description">
|
||||
link files for small client-side tweaks. (not sure how to do something? check out
|
||||
the
|
||||
<a
|
||||
href="https://github.com/notion-enhancer/notion-enhancer/blob/master/TWEAKS.md"
|
||||
>tweaks</a
|
||||
>
|
||||
collection.)
|
||||
</p>
|
||||
<ul class="library--authors">
|
||||
<li>
|
||||
<a href="https://dragonwocky.me"
|
||||
><img src="https://dragonwocky.me/avatar.jpg" /> <span>dragonwocky</span></a
|
||||
>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</article>
|
||||
</section>
|
||||
<section data-container="alerts"></section>
|
||||
<section data-container="documentation">documentation</section>
|
||||
<section data-container="library" data-active></section>
|
||||
</main>
|
||||
<script src="./menu.js" type="module"></script>
|
||||
</body>
|
||||
|
@ -6,7 +6,7 @@
|
||||
|
||||
'use strict';
|
||||
|
||||
import { web, fs, registry } from '../../helpers.js';
|
||||
import { web, fs, registry, markdown } from '../../helpers.js';
|
||||
|
||||
for (let mod of await registry.get()) {
|
||||
for (let sheet of mod.css?.menu || []) {
|
||||
@ -14,20 +14,193 @@ for (let mod of await registry.get()) {
|
||||
}
|
||||
}
|
||||
|
||||
const tabs = ['library', 'alerts', 'documentation'].map((tab) => ({
|
||||
title: document.querySelector(`header [data-target="${tab}"]`),
|
||||
container: document.querySelector(`main [data-container="${tab}"]`),
|
||||
}));
|
||||
tabs.forEach((tab) => {
|
||||
tab.title.addEventListener('click', (event) => {
|
||||
tabs.forEach((_tab) => {
|
||||
_tab.title.removeAttribute('data-active');
|
||||
_tab.container.removeAttribute('data-active');
|
||||
});
|
||||
tab.title.dataset.active = true;
|
||||
tab.container.dataset.active = true;
|
||||
});
|
||||
});
|
||||
const components = {
|
||||
preview({ preview }) {
|
||||
if (!preview) return '';
|
||||
const element = web.createElement(
|
||||
`<img alt="" class="library--preview" src="${preview}" />`
|
||||
);
|
||||
return element;
|
||||
},
|
||||
name({ name, id, version }) {
|
||||
const element = web.createElement(`<label for="enable--${id}" class="library--title library--toggle_label">
|
||||
<input type="checkbox" id="enable--${id}" />
|
||||
<h2><span>${name} <span class="library--version">v${version}</span></span>
|
||||
<span class="library--toggle"></span></h2></label>`);
|
||||
return element;
|
||||
},
|
||||
tags({ tags }) {
|
||||
if (!tags || !tags.length) return '';
|
||||
const element = web.createElement(
|
||||
`<ul class="library--tags">${tags.map((tag) => `<li>#${tag}</li>`).join('')}</ul>`
|
||||
);
|
||||
return element;
|
||||
},
|
||||
description({ description }) {
|
||||
const element = web.createElement(
|
||||
`<p class="library--description">${markdown.renderInline(description)}</p>`
|
||||
);
|
||||
return element;
|
||||
},
|
||||
authors({ authors }) {
|
||||
const element = web.createElement(
|
||||
`<ul class="library--authors">${authors
|
||||
.map(
|
||||
(author) =>
|
||||
`<li><a href="${author.url}"><img src="${author.icon}"/> <span>${author.name}</span></a></li>`
|
||||
)
|
||||
.join('')}</ul>`
|
||||
);
|
||||
return element;
|
||||
},
|
||||
expand({ id }) {
|
||||
const element = web.createElement(`<p class="library--expand"><a href="?mod=${id}">
|
||||
<!-- https://fontawesome.com/icons/long-arrow-alt-right?style=solid -->
|
||||
<span><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><path fill="currentColor"
|
||||
d="M313.941 216H12c-6.627 0-12 5.373-12 12v56c0 6.627 5.373 12 12 12h301.941v46.059c0 21.382 25.851 32.09 40.971 16.971l86.059-86.059c9.373-9.373 9.373-24.569 0-33.941l-86.059-86.059c-15.119-15.119-40.971-4.411-40.971 16.971V216z">
|
||||
</path></svg></span> <span>settings & documentation</span></a></p>`);
|
||||
return element;
|
||||
},
|
||||
toggle(id, { key, label, value }) {
|
||||
const element = web.createElement(`<label for="toggle--${id}.${key}" class="library--toggle_label">
|
||||
<input type="checkbox" id="toggle--${id}.${key}" />
|
||||
<p><span>${label}</span><span class="library--toggle"></span></p></label>`);
|
||||
return element;
|
||||
},
|
||||
select(id, { key, label, values }) {
|
||||
const element = web.createElement(`<label for="select--${id}.${key}" class="library--select_label">
|
||||
<p>${label}</p><p class="library--select"><span>
|
||||
<!-- https://fontawesome.com/icons/caret-down?style=solid -->
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 512">
|
||||
<path fill="currentColor" d="M31.3 192h257.3c17.8 0 26.7 21.5 14.1 34.1L174.1 354.8c-7.8 7.8-20.5 7.8-28.3 0L17.2 226.1C4.6 213.5 13.5 192 31.3 192z"></path></svg></span>
|
||||
<select id="select--${id}.${key}">${values.map(
|
||||
(value) => `<option value="${value}">${value}</option>`
|
||||
)}</select></p></label>`);
|
||||
return element;
|
||||
},
|
||||
text(id, { key, label, value }) {
|
||||
const element = web.createElement(`<label for="text--${id}.${key}" class="library--text_label">
|
||||
<p>${label}</p><textarea id="text--${id}.${key}" rows="1"></textarea></label>`);
|
||||
element.querySelector('textarea').addEventListener('input', (ev) => {
|
||||
ev.target.style.removeProperty('--txt--scroll-height');
|
||||
ev.target.style.setProperty('--txt--scroll-height', ev.target.scrollHeight + 'px');
|
||||
});
|
||||
return element;
|
||||
},
|
||||
number(id, { key, label, value }) {
|
||||
const element = web.createElement(`<label for="number--${id}.${key}" class="library--number_label">
|
||||
<p>${label}</p><input id="number--${id}.${key}" type="number"></inpu></label>`);
|
||||
return element;
|
||||
},
|
||||
file(id, { key, label, extensions }) {
|
||||
const accept =
|
||||
extensions && extensions.length ? ` accept="${extensions.join(',')}"` : '';
|
||||
const element = web.createElement(`<label for="file--${id}.${key}" class="library--file_label">
|
||||
<input type="file" id="file--${id}.${key}"${accept}/><p>${label}</p>
|
||||
<p class="library--file"><span><!-- https://fontawesome.com/icons/file?style=solid -->
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 384 512"><path fill="currentColor"
|
||||
d="M224 136V0H24C10.7 0 0 10.7 0 24v464c0 13.3 10.7 24 24 24h336c13.3 0 24-10.7 24-24V160H248c-13.2 0-24-10.8-24-24zm160-14.1v6.1H256V0h6.1c6.4 0 12.5 2.5 17 7l97.9 98c4.5 4.5 7 10.6 7 16.9z"
|
||||
/></svg></span><span class="library--file_path">choose file...</span></p></label>`);
|
||||
element.querySelector('input[type="file"]').addEventListener('change', (ev) => {
|
||||
element.querySelector('.library--file_path').innerText = ev.target.files[0].name;
|
||||
});
|
||||
return element;
|
||||
},
|
||||
documentation_buttons({ _dir }) {
|
||||
const element = web.createElement(`<p class="documentation--buttons">
|
||||
<a href="?"><!-- https://fontawesome.com/icons/long-arrow-alt-left?style=solid -->
|
||||
<span><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><path fill="currentColor"
|
||||
d="M134.059 296H436c6.627 0 12-5.373 12-12v-56c0-6.627-5.373-12-12-12H134.059v-46.059c0-21.382-25.851-32.09-40.971-16.971L7.029 239.029c-9.373 9.373-9.373 24.569 0 33.941l86.059 86.059c15.119 15.119 40.971 4.411 40.971-16.971V296z">
|
||||
</path></svg></span> <span>back to library</span></a>
|
||||
<a href="https://github.com/notion-enhancer/extension/tree/main/repo/${encodeURIComponent(
|
||||
_dir
|
||||
)}"><!-- https://fontawesome.com/icons/code?style=solid -->
|
||||
<span><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 512"><path fill="currentColor"
|
||||
d="M278.9 511.5l-61-17.7c-6.4-1.8-10-8.5-8.2-14.9L346.2 8.7c1.8-6.4 8.5-10 14.9-8.2l61 17.7c6.4 1.8 10 8.5 8.2 14.9L293.8 503.3c-1.9 6.4-8.5 10.1-14.9 8.2zm-114-112.2l43.5-46.4c4.6-4.9 4.3-12.7-.8-17.2L117 256l90.6-79.7c5.1-4.5 5.5-12.3.8-17.2l-43.5-46.4c-4.5-4.8-12.1-5.1-17-.5L3.8 247.2c-5.1 4.7-5.1 12.8 0 17.5l144.1 135.1c4.9 4.6 12.5 4.4 17-.5zm327.2.6l144.1-135.1c5.1-4.7 5.1-12.8 0-17.5L492.1 112.1c-4.8-4.5-12.4-4.3-17 .5L431.6 159c-4.6 4.9-4.3 12.7.8 17.2L523 256l-90.6 79.7c-5.1 4.5-5.5 12.3-.8 17.2l43.5 46.4c4.5 4.9 12.1 5.1 17 .6z">
|
||||
</path></svg></span> <span>view source code</span></a>
|
||||
</p>`);
|
||||
return element;
|
||||
},
|
||||
},
|
||||
generators = {
|
||||
summary_card(mod) {
|
||||
const article = web.createElement('<article class="library--summary_card"></article>'),
|
||||
body = web.createElement('<div></div>');
|
||||
article.append(components.preview(mod));
|
||||
body.append(components.name(mod));
|
||||
body.append(components.tags(mod));
|
||||
body.append(components.description(mod));
|
||||
body.append(components.authors(mod));
|
||||
body.append(components.expand(mod));
|
||||
article.append(body);
|
||||
return article;
|
||||
},
|
||||
full_card(mod) {
|
||||
const article = web.createElement('<article class="library--full_card"></article>'),
|
||||
body = web.createElement('<div></div>');
|
||||
article.append(components.preview(mod));
|
||||
body.append(components.name(mod));
|
||||
body.append(components.tags(mod));
|
||||
body.append(components.description(mod));
|
||||
body.append(components.authors(mod));
|
||||
article.append(body);
|
||||
if (mod.options && mod.options.length) {
|
||||
const options = web.createElement(`<div class="library--options"></div>`);
|
||||
mod.options.forEach((opt) => options.append(components[opt.type](mod.id, opt)));
|
||||
article.append(options);
|
||||
}
|
||||
return article;
|
||||
},
|
||||
async documentation(mod) {
|
||||
const content = (await fs.isFile(`repo/${mod._dir}/README.md`))
|
||||
? markdown.render(await fs.getText(`repo/${mod._dir}/README.md`))
|
||||
: '',
|
||||
article = web.createElement(
|
||||
`<article class="documentation--body">${content}</article>`
|
||||
);
|
||||
return article;
|
||||
},
|
||||
},
|
||||
tabs = {
|
||||
library: {
|
||||
title: document.querySelector('header [data-target="library"]'),
|
||||
async container() {
|
||||
document.querySelector('[data-target][data-active]').removeAttribute('data-active');
|
||||
this.title.dataset.active = true;
|
||||
const $container = document.querySelector('[data-container]');
|
||||
$container.dataset.container = 'library';
|
||||
$container.innerHTML = '';
|
||||
for (let mod of await registry.get()) $container.append(generators.summary_card(mod));
|
||||
},
|
||||
},
|
||||
mod: {
|
||||
title: document.querySelector('header [data-target="library"]'),
|
||||
async container(mod) {
|
||||
document.querySelector('[data-target][data-active]').removeAttribute('data-active');
|
||||
this.title.dataset.active = true;
|
||||
const $container = document.querySelector('[data-container]');
|
||||
$container.dataset.container = 'page';
|
||||
$container.innerHTML = '';
|
||||
$container.append(components.documentation_buttons(mod));
|
||||
$container.append(generators.full_card(mod));
|
||||
$container.append(await generators.documentation(mod));
|
||||
},
|
||||
},
|
||||
};
|
||||
tabs.library.title.addEventListener('click', (ev) => tabs.library.container());
|
||||
|
||||
(async () => {
|
||||
const search = new Map(
|
||||
location.search
|
||||
.slice(1)
|
||||
.split('&')
|
||||
.map((query) => query.split('='))
|
||||
),
|
||||
mod = (await registry.get()).find((mod) => mod.id === search.get('mod'));
|
||||
if (mod) {
|
||||
tabs.mod.container(mod);
|
||||
} else tabs.library.container();
|
||||
})();
|
||||
|
||||
// registry.errors().then((err) => {
|
||||
// document.querySelector('[data-section="alerts"]').innerHTML = JSON.stringify(err);
|
||||
|
@ -1,8 +1,9 @@
|
||||
{
|
||||
"name": "menu",
|
||||
"id": "a6621988-551d-495a-97d8-3c568bca2e9e",
|
||||
"description": "the enhancer's graphical menu, related buttons and shortcuts.",
|
||||
"version": "0.11.0",
|
||||
"description": "the enhancer's [graphical](https://github.com) menu, related buttons and shortcuts.",
|
||||
"preview": "https://raw.githubusercontent.com/notion-enhancer/notion-enhancer/dev/notion-enhancer%20v0.10.0%20banner.jpg",
|
||||
"tags": ["core"],
|
||||
"authors": [
|
||||
{
|
||||
@ -18,5 +19,37 @@
|
||||
},
|
||||
"js": {
|
||||
"client": ["client.js"]
|
||||
}
|
||||
},
|
||||
"options": [
|
||||
{
|
||||
"type": "toggle",
|
||||
"key": "toggle",
|
||||
"label": "toggle",
|
||||
"value": true
|
||||
},
|
||||
{
|
||||
"type": "select",
|
||||
"key": "select",
|
||||
"label": "select",
|
||||
"values": ["option a", "option b", "option c"]
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"key": "text",
|
||||
"label": "text",
|
||||
"value": "default"
|
||||
},
|
||||
{
|
||||
"type": "number",
|
||||
"key": "number",
|
||||
"label": "number",
|
||||
"value": 0
|
||||
},
|
||||
{
|
||||
"type": "file",
|
||||
"key": "file",
|
||||
"label": "file picker (.css only)",
|
||||
"extensions": [".css"]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
@ -44,7 +44,7 @@ const enhancerMenu = {
|
||||
return this._tab;
|
||||
},
|
||||
};
|
||||
chrome.action.onClicked.addListener(enhancerMenu.open);
|
||||
chrome.action.onClicked.addListener(() => enhancerMenu.open());
|
||||
|
||||
chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
|
||||
switch (request.type) {
|
||||
|
Loading…
Reference in New Issue
Block a user