Skip to content

Commit

Permalink
feat: Added Icon Packs (close #181)
Browse files Browse the repository at this point in the history
  • Loading branch information
valentine195 committed Feb 25, 2022
1 parent bfd460e commit e973cec
Show file tree
Hide file tree
Showing 14 changed files with 633 additions and 190 deletions.
46 changes: 36 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -203,7 +203,7 @@ Please note that by default, the background color of the title is simply the col

### Images as Icons

Images can be uploaded to use as an admonition icon instead of an icon from Font Awesome or RPG Awesome.
Images can be uploaded to use as an admonition icon instead of an icon from a downloaded icon set.

These images will be resized to 24px x 24px to be stored in the plugin's saved data.

Expand Down Expand Up @@ -507,15 +507,13 @@ As of v6.8.0, an additional non-code block syntax can be used that is inspired b

![](https://raw.githubusercontent.com/valentine195/obsidian-admonition/master/images/msdocs.png)


This syntax can also be used on indented code blocks:

```md
[!quote]
This is an admonition!
```


### Title

A title can be added to the MSDoc-style admonition by appending it after the type.
Expand All @@ -525,7 +523,7 @@ A title can be added to the MSDoc-style admonition by appending it after the typ
> This is an admonition!
```

Like the code block syntax, providing an empty title will remove the title from the rendered admonition.
Like the code block syntax, providing an empty title will remove the title from the rendered admonition.

```md
> [!quote:]
Expand Down Expand Up @@ -557,6 +555,18 @@ Instructions:

Please note that I can give no guarantees of stability on your publish site. Other JavaScript you include may conflict with this file. If you run into an issue using it, please create an issue on this repository and I will try to help you.

## Icon Packs

Additional icon packs can be downloaded in settings.

### Adding Icon Packs

Want to add an existing icon pack? Make a pull request with the following:

1. Add a new folder in the [icons](./icons) folder with the name of your icon set.
2. Create an `icons.json` file that has the icons defined as an Object. Please see the [Octicons json](./icons/octicons/icons.json) for reference.
3. Put your icon pack's information in the two variables in the [Icon Packs](./src/icons/packs.ts) file.

# Settings

## Custom Admonition Types
Expand All @@ -577,7 +587,7 @@ If this setting is off, rendered admonitions will receive the `.no-drop` class.

All admonitions will be collapsible by default, unless `collapse: none` is set in the admonition parameters.

### Default Collapse Type
### Default Collapse Type

> :warning: This setting is only available when Collapsible By Default is true.
Expand All @@ -601,16 +611,32 @@ Turn this off to totally control color via CSS.

Admonitions with no content are hidden by default.

> :warning: Please note that this only works for Admonitions that have *no text content whatsoever*.
> :warning: Please note that this only works for Admonitions that have _no text content whatsoever_.
## Icon Packs

### Use Font Awesome Icons

The plugin comes pre-bundled with the entire [Font Awesome Free](https://fontawesome.com/search?m=free&s=brands%2Cregular%2Csolid) icon set. Turn this setting off to not include them in the icon picker.

Existing custom Admonitions that use Font Awesome icons will continue to work.

### Additional Icon Packs

Additional icon packs can be downloaded to supplement the included Font Awesome Free icon set.

**Downloading an icon pack requires an internet connection.**

Current additional icon packs available are the [Octicons](https://primer.style/octicons/) set and the [RPG Awesome](https://nagoshiashumari.github.io/Rpg-Awesome/) set.

> :pencil: For backwards compability, if an Admonition was created prior to version **7.0.0** using an RPG Awesome icon, the pack will try to be downloaded.
## Additional Syntaxes

### Enable Non-codeblock Admonitions

> :heavy_exclamation_mark: This syntax will be removed in a future version!
> :heavy_exclamation_mark: This setting has been removed as of version **7.0.0**.
>
> It is no longer possible to enable this setting. Legacy support will continue until version **7.0.0**.
>
> It is recommended to use the [Microsoft Document Syntax](#microsoft-document-syntax) instead.
Enabled use of `!!! ad-<type>` style admonitions. No longer supported, will be removed in a future version.
Expand Down Expand Up @@ -647,7 +673,7 @@ If you require links to be fully synced, it is recommended to use the [Microsoft

### Generate JS for Publish

Use this setting to enable Admonitions on custom-domain Obsidian Publish websites.
Use this setting to enable Admonitions on custom-domain Obsidian Publish websites.

See [Publish](#publish) for more information.

Expand Down
1 change: 0 additions & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

18 changes: 13 additions & 5 deletions src/@types/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { MarkdownPostProcessorContext, Plugin_2 } from "obsidian";
import { IconName } from "src/util";
import { IconName } from "@fortawesome/fontawesome-svg-core";
import { DownloadableIconPack } from "src/icons/manager";

export interface Admonition {
type: string;
Expand Down Expand Up @@ -29,19 +29,27 @@ export interface AdmonitionSettings {
defaultCollapseType: "open" | "closed";
syncLinks: boolean;
version: string;
warnedAboutNC: boolean;
injectColor: boolean;
parseTitles: boolean;
allowMSSyntax: boolean;
msSyntaxIndented: boolean;
livePreviewMS: boolean;
dropShadow: boolean;
hideEmpty: boolean;
icons: Array<DownloadableIconPack>;
useFontAwesome: boolean;
rpgDownloadedOnce: boolean;
open: {
admonitions: boolean;
icons: boolean;
other: boolean;
advanced: boolean;
};
}

export type AdmonitionIconDefinition = {
type?: "font-awesome" | "rpg" | "image";
name?: IconName | RPGIconName | string;
type?: "font-awesome" | "image" | DownloadableIconPack;
name?: IconName | string;
};

export type AdmonitionIconName = AdmonitionIconDefinition["name"];
Expand Down
10 changes: 9 additions & 1 deletion src/assets/main.css
Original file line number Diff line number Diff line change
Expand Up @@ -311,6 +311,14 @@ input.is-invalid {
.admonition-settings details[open] > summary > .collapser > .handle {
transform: rotate(90deg);
}
.admonition-setting-warning {
display: flex;
gap: 0.25rem;
align-items: center;
}
.admonition-setting-warning.text-warning {
color: var(--text-error);
}

.admonitions-nested-settings .setting-item {
border: 0px;
Expand Down Expand Up @@ -376,4 +384,4 @@ input.is-invalid {

.is-live-preview .admonition-content .math-block > mjx-container {
padding: 0;
}
}
149 changes: 149 additions & 0 deletions src/icons/manager.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
import { faCopy, far, IconPrefix } from "@fortawesome/free-regular-svg-icons";
import { fas } from "@fortawesome/free-solid-svg-icons";
import { fab } from "@fortawesome/free-brands-svg-icons";
import {
IconDefinition,
findIconDefinition,
icon as getFAIcon,
library
} from "@fortawesome/fontawesome-svg-core";

import type { IconName } from "@fortawesome/fontawesome-svg-core";

/* import { RPG } from "./rpgawesome"; */
import type { AdmonitionIconDefinition } from "src/@types";
import type ObsidianAdmonition from "src/main";
import { Notice } from "obsidian";
import { type DownloadableIconPack, DownloadableIcons } from "./packs";

export { type DownloadableIconPack, DownloadableIcons };

/** Load Font Awesome Library */
library.add(fas, far, fab, faCopy);

export class IconManager {
DOWNLOADED: {
[key in DownloadableIconPack]?: Record<string, string>;
} = {};
FONT_AWESOME_MAP = new Map(
[Object.values(fas), Object.values(far), Object.values(fab)]
.flat()
.map((i: IconDefinition) => {
return [
i.iconName,
{
name: i.iconName,
type: "font-awesome" as "font-awesome"
}
];
})
);
constructor(public plugin: ObsidianAdmonition) {}
async load() {
for (const icon of this.plugin.data.icons) {
const exists = await this.plugin.app.vault.adapter.exists(
this.localIconPath(icon)
);
if (!exists) {
await this.downloadIcon(icon);
} else {
this.DOWNLOADED[icon] = JSON.parse(
await this.plugin.app.vault.adapter.read(
`${this.plugin.app.plugins.getPluginFolder()}/obsidian-admonition/${icon}.json`
)
);
}
}
}
iconDefinitions: AdmonitionIconDefinition[] = [];
setIconDefinitions() {
const downloaded: AdmonitionIconDefinition[] = [];
for (const pack of this.plugin.data.icons) {
if (!(pack in this.DOWNLOADED)) continue;
const icons = this.DOWNLOADED[pack];
downloaded.push(
...Object.keys(icons).map((name) => {
return { type: pack, name };
})
);
}
this.iconDefinitions = [
...(this.plugin.data.useFontAwesome
? this.FONT_AWESOME_MAP.values()
: []),
...downloaded
];
}
iconPath(pack: DownloadableIconPack) {
return `https://raw.githubusercontent.com/valentine195/obsidian-admonition/master/icons/${pack}/icons.json`;
}
localIconPath(pack: DownloadableIconPack) {
return `${this.plugin.app.plugins.getPluginFolder()}/obsidian-admonition/${pack}.json`;
}
async downloadIcon(pack: DownloadableIconPack) {
try {
const icons: Record<string, string> = await (
await fetch(this.iconPath(pack))
).json();
this.plugin.data.icons.push(pack);
this.plugin.data.icons = [...new Set(this.plugin.data.icons)];
await this.plugin.app.vault.adapter.write(
this.localIconPath(pack),
JSON.stringify(icons)
);
this.DOWNLOADED[pack] = icons;
await this.plugin.saveSettings();
this.setIconDefinitions();

new Notice(`${DownloadableIcons[pack]} successfully downloaded.`);
} catch (e) {
console.error(e);
new Notice("Could not download icon pack");
}
}
async removeIcon(pack: DownloadableIconPack) {
await this.plugin.app.vault.adapter.remove(this.localIconPath(pack));
delete this.DOWNLOADED[pack];
this.plugin.data.icons.remove(pack);
this.plugin.data.icons = [...new Set(this.plugin.data.icons)];
await this.plugin.saveSettings();
this.setIconDefinitions();
}
getIconType(str: string): "font-awesome" | DownloadableIconPack {
if (findIconDefinition({ iconName: str as IconName, prefix: "fas" }))
return "font-awesome";
if (findIconDefinition({ iconName: str as IconName, prefix: "far" }))
return "font-awesome";
if (findIconDefinition({ iconName: str as IconName, prefix: "fab" }))
return "font-awesome";
for (const [pack, icons] of Object.entries(this.DOWNLOADED)) {
if (Object.keys(icons).find((icon) => icon == str))
return pack as DownloadableIconPack;
}
}
getIconModuleName(icon: AdmonitionIconDefinition) {
if (icon.type === "font-awesome") return "Font Awesome";
if (icon.type === "image") return;
if (icon.type in DownloadableIcons) return DownloadableIcons[icon.type];
}
getIconNode(icon: AdmonitionIconDefinition): Element {
if (icon.type === "image") {
const img = new Image();
img.src = icon.name;
return img;
}
if (this.DOWNLOADED[icon.type as DownloadableIconPack]?.[icon.name]) {
const el = createDiv();
el.innerHTML =
this.DOWNLOADED[icon.type as DownloadableIconPack]?.[icon.name];
return el.children[0];
}
for (const prefix of ["fas", "far", "fab"] as IconPrefix[]) {
const definition = findIconDefinition({
iconName: icon.name as IconName,
prefix
});
if (definition) return getFAIcon(definition).node[0];
}
}
}
6 changes: 6 additions & 0 deletions src/icons/packs.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
export type DownloadableIconPack = "octicons" | "rpg";

export const DownloadableIcons: Record<DownloadableIconPack, string> = {
octicons: "Octicons",
rpg: "RPG Awesome"
} as const;
Loading

0 comments on commit e973cec

Please sign in to comment.