Skip to content

Commit

Permalink
initial version - v0.1.0
Browse files Browse the repository at this point in the history
  • Loading branch information
tomzorz committed Oct 18, 2021
1 parent 685047c commit b6b8c71
Show file tree
Hide file tree
Showing 5 changed files with 148 additions and 127 deletions.
62 changes: 17 additions & 45 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,57 +1,29 @@
## Obsidian Sample Plugin
# Obsidian Link Archive

This is a sample plugin for Obsidian (https://obsidian.md).
This plugin archives links in your note so they're available to you even if the original site goes down or gets removed.

This project uses Typescript to provide type checking and documentation.
The repo depends on the latest plugin API (obsidian.d.ts) in Typescript Definition format, which contains TSDoc comments describing what it does.
## How it works

**Note:** The Obsidian API is still in early alpha and is subject to change at any time!
Upon pressing the "Archive Links" button in the ribbon/left sidebar, the plugin:

This sample plugin demonstrates some of the basic functionality the plugin API can do.
- Changes the default font color to red using `styles.css`.
- Adds a ribbon icon, which shows a Notice when clicked.
- Adds a command "Open Sample Modal" which opens a Modal.
- Adds a plugin setting tab to the settings page.
- Registers a global click event and output 'click' to the console.
- Registers a global interval which logs 'setInterval' to the console.
1. looks up every external link in the current note,
2. sumbits each of them to https://archive.org,
3. as soon as they are saved, it embeds an `(Archived)` link after the regular link in your note.

### First time developing plugins?
The plugin will attempt not to recreate archive links for already-archived links (and the archive links themselves) - but this relies on not modifying the formatting of the archive links.

Quick starting guide for new plugin devs:
## Installation

- Make a copy of this repo as a template with the "Use this template" button (login to GitHub if you don't see it).
- Clone your repo to a local development folder. For convenience, you can place this folder in your `.obsidian/plugins/your-plugin-name` folder.
- Install NodeJS, then run `npm i` in the command line under your repo folder.
- Run `npm run dev` to compile your plugin from `main.ts` to `main.js`.
- Make changes to `main.ts` (or create new `.ts` files). Those changes should be automatically compiled into `main.js`.
- Reload Obsidian to load the new version of your plugin.
- Enable plugin in settings window.
- For updates to the Obsidian API run `npm update` in the command line under your repo folder.
In Obsidian, navigate to **Settings > Community Plugins**, turn off **Safe mode** if you haven't yet, then press the **Browse** button - you should be able to find it in the list there.

### Releasing new releases
Alternatively, clone/download this repository, and copy its contents to you vault's `.obsidian/plugins/obsidian-link-archive` folder and then enable it under **Settings > Community Plugins** (the note about disabling above applies here as well).
## Changelog

- Update your `manifest.json` with your new version number, such as `1.0.1`, and the minimum Obsidian version required for your latest release.
- Update your `versions.json` file with `"new-plugin-version": "minimum-obsidian-version"` so older versions of Obsidian can download an older version of your plugin that's compatible.
- Create new GitHub release using your new version number as the "Tag version". Use the exact version number, don't include a prefix `v`. See here for an example: https://github.com/obsidianmd/obsidian-sample-plugin/releases
- Upload the files `manifest.json`, `main.js`, `styles.css` as binary attachments.
- Publish the release.
**v0.1.0**

### Adding your plugin to the community plugin list
Initial release.

- Publish an initial version.
- Make sure you have a `README.md` file in the root of your repo.
- Make a pull request at https://github.com/obsidianmd/obsidian-releases to add your plugin.
## Future plans

### How to use

- Clone this repo.
- `npm i` or `yarn` to install dependencies
- `npm run dev` to start compilation in watch mode.

### Manually installing the plugin

- Copy over `main.js`, `styles.css`, `manifest.json` to your vault `VaultFolder/.obsidian/plugins/your-plugin-id/`.

### API Documentation

See https://github.com/obsidianmd/obsidian-api
- Support for other archive providers
- Custom formatting for archive links
194 changes: 124 additions & 70 deletions main.ts
Original file line number Diff line number Diff line change
@@ -1,60 +1,111 @@
import { App, Modal, Notice, Plugin, PluginSettingTab, Setting } from 'obsidian';
import { Console } from 'console';
import { App, MarkdownView, Modal, Notice, Plugin, PluginSettingTab, request, Setting } from 'obsidian';
import { Url } from 'url';

export const enum ArchiveOptions {
wayback,
archiveis,
both
}

interface MyPluginSettings {
mySetting: string;
interface LinkArchivePluginSettings {
archiveOption: ArchiveOptions;
}

const DEFAULT_SETTINGS: MyPluginSettings = {
mySetting: 'default'
const DEFAULT_SETTINGS: LinkArchivePluginSettings = {
archiveOption: ArchiveOptions.archiveis
}

export default class MyPlugin extends Plugin {
settings: MyPluginSettings;
const urlRegex =/(\b(https?|file):\/\/[-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|])/ig;

const waybackUrl = 'https://web.archive.org/web/';
const waybackSaveUrl = 'https://web.archive.org/save/';

const archiveText = '[(Archived)]';

export default class ObsidianLinkArchivePlugin extends Plugin {
settings: LinkArchivePluginSettings;

async onload() {
console.log('loading plugin');
console.log('Loading Link Archive plugin...');

await this.loadSettings();

this.addRibbonIcon('dice', 'Sample Plugin', () => {
new Notice('This is a notice!');
});
this.addRibbonIcon('restore-file-glyph', 'Archive Links', async () => {

// test save
//new Notice('Archive option: ' + this.settings.archiveOption.toString());

this.addStatusBarItem().setText('Status Bar Text');

this.addCommand({
id: 'open-sample-modal',
name: 'Open Sample Modal',
// callback: () => {
// console.log('Simple Callback');
// },
checkCallback: (checking: boolean) => {
let leaf = this.app.workspace.activeLeaf;
if (leaf) {
if (!checking) {
new SampleModal(this.app).open();
}
return true;
}
return false;
}
});
const view = this.app.workspace.getActiveViewOfType(MarkdownView);

this.addSettingTab(new SampleSettingTab(this.app, this));
if(view) {
const viewData = view.getViewData();

this.registerCodeMirror((cm: CodeMirror.Editor) => {
console.log('codemirror', cm);
});
let reverseArray: Array<[string, number]> = [];

let linkArray;
while ((linkArray = urlRegex.exec(viewData)) !== null) {
console.log(`Found ${linkArray[0]}. Next starts at ${urlRegex.lastIndex}.`);

if(linkArray[0].startsWith(waybackUrl)) continue;

if(viewData.substring(urlRegex.lastIndex, urlRegex.lastIndex + 14).contains(archiveText)) continue;

reverseArray.unshift([linkArray[0], urlRegex.lastIndex]);
}

console.log(reverseArray);

this.registerDomEvent(document, 'click', (evt: MouseEvent) => {
console.log('click', evt);
if(reverseArray.length == 0) {
new Notice('No (new) links to archive.');
return;
}

new Notice(`Preparing to archive ${reverseArray.length} link(s), this might take a while - please be patient...`, 10 * 1000);

for (const tuple of reverseArray) {
let currentLink = tuple[0];
let saveLink = `${waybackSaveUrl}${currentLink}`;
let archiveLink = ` ${archiveText}(${waybackUrl}${currentLink})`;
let offset = view.editor.offsetToPos(tuple[1]);
let message = `Successfully archived ${currentLink}!`;

await request({
url: saveLink
});

view.editor.replaceRange(archiveLink, offset);
console.log(message);
new Notice(message);
}

// reverseArray.forEach(async function (tuple) {
// let currentLink = tuple[0];
// let saveLink = `${waybackSaveUrl}${currentLink}`;
// let archiveLink = ` ${archiveText}(${waybackUrl}${currentLink})`;
// let offset = view.editor.offsetToPos(tuple[1]);
// let message = `Successfully archived ${currentLink}!`;

// request({
// url: saveLink
// }).then(function(pageRes) {
// view.editor.replaceRange(archiveLink, offset);
// console.log(message);
// new Notice(message);
// });
// });

new Notice('Link archiving done!');
} else {
new Notice('Link archiving only works if you have a note open.');
}
});

this.registerInterval(window.setInterval(() => console.log('setInterval'), 5 * 60 * 1000));
this.addSettingTab(new LinkArchiveSettingTab(this.app, this));
}

onunload() {
console.log('unloading plugin');
console.log('Unloading Link Archive plugin...');
}

async loadSettings() {
Expand All @@ -66,47 +117,50 @@ export default class MyPlugin extends Plugin {
}
}

class SampleModal extends Modal {
constructor(app: App) {
super(app);
}

onOpen() {
let {contentEl} = this;
contentEl.setText('Woah!');
}

onClose() {
let {contentEl} = this;
contentEl.empty();
}
}

class SampleSettingTab extends PluginSettingTab {
plugin: MyPlugin;
class LinkArchiveSettingTab extends PluginSettingTab {
plugin: ObsidianLinkArchivePlugin;

constructor(app: App, plugin: MyPlugin) {
constructor(app: App, plugin: ObsidianLinkArchivePlugin) {
super(app, plugin);
this.plugin = plugin;
}

display(): void {
const plugin: ObsidianLinkArchivePlugin = (this as any).plugin;

let {containerEl} = this;

containerEl.empty();

containerEl.createEl('h2', {text: 'Settings for my awesome plugin.'});

new Setting(containerEl)
.setName('Setting #1')
.setDesc('It\'s a secret')
.addText(text => text
.setPlaceholder('Enter your secret')
.setValue(this.plugin.settings.mySetting)
.onChange(async (value) => {
console.log('Secret: ' + value);
this.plugin.settings.mySetting = value;
await this.plugin.saveSettings();
}));
// containerEl.createEl('h2', {text: 'Archive Settings'});

// new Setting(containerEl)
// .setName('Archive Provider')
// .setDesc('Choose a provider for the link archive')
// .addDropdown((dropdown) => {
// const options: Record<ArchiveOptions, string> = {
// 0: "Internet Archive",
// 1: "archive.is",
// 2: "Both"
// };

// dropdown
// .addOptions(options)
// .setValue(plugin.settings.archiveOption.toString())
// .onChange(async (value) => {
// console.log('Archive option: ' + value);
// plugin.settings.archiveOption = +value;
// await plugin.saveSettings();
// this.display();
// })
// });

containerEl.createEl('h2', {text: 'About Link Archive'});

containerEl.createEl('p', {text: 'This plugin archives links in your note so they\'re available to you even if the original site goes down or gets removed.'});

containerEl.createEl('a', {text: 'Open GitHub repository', href: 'https://github.com/tomzorz/obsidian-link-archive'});

// TODO github support and ko-fi
}
}
12 changes: 6 additions & 6 deletions manifest.json
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
{
"id": "obsidian-sample-plugin",
"name": "Sample Plugin",
"version": "1.0.1",
"id": "obsidian-link-archive",
"name": "Link Archive",
"version": "0.1.0",
"minAppVersion": "0.9.12",
"description": "This is a sample plugin for Obsidian. This plugin demonstrates some of the capabilities of the Obsidian API.",
"author": "Obsidian",
"authorUrl": "https://obsidian.md/about",
"description": "This plugin archives links in your note so they're available to you even if the original site goes down or gets removed.",
"author": "Tamás Deme - @tomzorz_",
"authorUrl": "https://tomzorz.me",
"isDesktopOnly": false
}
4 changes: 0 additions & 4 deletions styles.css
Original file line number Diff line number Diff line change
@@ -1,4 +0,0 @@
/* Sets all the text color to red! */
body {
color: red;
}
3 changes: 1 addition & 2 deletions versions.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
{
"1.0.1": "0.9.12",
"1.0.0": "0.9.7"
"0.1.0": "0.9.12"
}

0 comments on commit b6b8c71

Please sign in to comment.