Skip to content

Commit 69eedc3

Browse files
committed
[Feat] initial release for obsidian-advanced-new-file
1 parent c228a70 commit 69eedc3

13 files changed

+174
-182
lines changed

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -12,3 +12,4 @@ main.js
1212

1313
# obsidian
1414
data.json
15+
.obsidian/

README.md

+24-57
Original file line numberDiff line numberDiff line change
@@ -1,57 +1,24 @@
1-
## Obsidian Sample Plugin
2-
3-
This is a sample plugin for Obsidian (https://obsidian.md).
4-
5-
This project uses Typescript to provide type checking and documentation.
6-
The repo depends on the latest plugin API (obsidian.d.ts) in Typescript Definition format, which contains TSDoc comments describing what it does.
7-
8-
**Note:** The Obsidian API is still in early alpha and is subject to change at any time!
9-
10-
This sample plugin demonstrates some of the basic functionality the plugin API can do.
11-
- Changes the default font color to red using `styles.css`.
12-
- Adds a ribbon icon, which shows a Notice when clicked.
13-
- Adds a command "Open Sample Modal" which opens a Modal.
14-
- Adds a plugin setting tab to the settings page.
15-
- Registers a global click event and output 'click' to the console.
16-
- Registers a global interval which logs 'setInterval' to the console.
17-
18-
### First time developing plugins?
19-
20-
Quick starting guide for new plugin devs:
21-
22-
- Make a copy of this repo as a template with the "Use this template" button (login to GitHub if you don't see it).
23-
- Clone your repo to a local development folder. For convenience, you can place this folder in your `.obsidian/plugins/your-plugin-name` folder.
24-
- Install NodeJS, then run `npm i` in the command line under your repo folder.
25-
- Run `npm run dev` to compile your plugin from `main.ts` to `main.js`.
26-
- Make changes to `main.ts` (or create new `.ts` files). Those changes should be automatically compiled into `main.js`.
27-
- Reload Obsidian to load the new version of your plugin.
28-
- Enable plugin in settings window.
29-
- For updates to the Obsidian API run `npm update` in the command line under your repo folder.
30-
31-
### Releasing new releases
32-
33-
- Update your `manifest.json` with your new version number, such as `1.0.1`, and the minimum Obsidian version required for your latest release.
34-
- 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.
35-
- 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
36-
- Upload the files `manifest.json`, `main.js`, `styles.css` as binary attachments.
37-
- Publish the release.
38-
39-
### Adding your plugin to the community plugin list
40-
41-
- Publish an initial version.
42-
- Make sure you have a `README.md` file in the root of your repo.
43-
- Make a pull request at https://github.com/obsidianmd/obsidian-releases to add your plugin.
44-
45-
### How to use
46-
47-
- Clone this repo.
48-
- `npm i` or `yarn` to install dependencies
49-
- `npm run dev` to start compilation in watch mode.
50-
51-
### Manually installing the plugin
52-
53-
- Copy over `main.js`, `styles.css`, `manifest.json` to your vault `VaultFolder/.obsidian/plugins/your-plugin-id/`.
54-
55-
### API Documentation
56-
57-
See https://github.com/obsidianmd/obsidian-api
1+
## Obsidian Advanced New File
2+
3+
Obsidian Advanced New file is a plugin for [Obsidian](https://obsidian.md/), that provide functionality to choose folder over note creation.
4+
The new note file is created with `Untitled.md` filename just to provide same behavior as default Obsidian.
5+
6+
The plugin is heavily inspired by [Note refactor](https://github.com/lynchjames/note-refactor-obsidian) amd [similar extension](https://marketplace.visualstudio.com/items?itemName=dkundel.vscode-new-file) for Vs Code.
7+
8+
## Feature
9+
10+
**Hint:** you can set command `advanced new file` to shortcut like `Ctrl/Cmd` + `Alt` + `N`.
11+
12+
Spawn command `advanced new file` and choose directory.
13+
14+
![Demo](images/demo.gif)
15+
16+
### How to develop
17+
18+
- Clone this repo.
19+
- `npm i` or `yarn` to install dependencies
20+
- `npm run dev` to start compilation in watch mode.
21+
22+
### Manually installing the plugin
23+
24+
- Copy over `main.js`, `styles.css`, `manifest.json` to your vault `VaultFolder/.obsidian/plugins/your-plugin-id/`.

TODO.md

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
# Road map obsidian-advanced-new-file
2+
3+
* [x] Add command to trigger panel
4+
* [x] Add sample panel
5+
* [x] Add panel to select folders
6+
* [c] Add panel to enter filename
7+
- Decide to create an untitled file like a default obsidian behavior.
8+
* [x] Create an `Untitled` file in selected folder.
9+
* [c] Create folders, if no suggestion triggered.
10+
- Decide currently only in known folders for creation.
11+
* [x] Rewrite logic for choosing folders without markdown files.
12+
* [x] Rewrite [[README]].
13+
* [ ] Add config for folder exclusion.

images/demo.gif

646 KB
Loading

main.ts

-112
This file was deleted.

manifest.json

+6-6
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
{
2-
"id": "obsidian-sample-plugin",
3-
"name": "Sample Plugin",
4-
"version": "1.0.1",
2+
"id": "obsidian-advanced-new-file",
3+
"name": "Advanced new file",
4+
"version": "1.0.0",
55
"minAppVersion": "0.9.12",
6-
"description": "This is a sample plugin for Obsidian. This plugin demonstrates some of the capabilities of the Obsidian API.",
7-
"author": "Obsidian",
8-
"authorUrl": "https://obsidian.md/about",
6+
"description": "This is a plugin for choosing folder on note creation.",
7+
"author": "vanadium23",
8+
"authorUrl": "https://vanadium23.me/",
99
"isDesktopOnly": false
1010
}

package.json

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
2-
"name": "obsidian-sample-plugin",
3-
"version": "0.12.0",
4-
"description": "This is a sample plugin for Obsidian (https://obsidian.md)",
2+
"name": "obsidian-advanced-new-file",
3+
"version": "1.0.0",
4+
"description": "Create notes in chosen folder for Obsidian (https://obsidian.md)",
55
"main": "main.js",
66
"scripts": {
77
"dev": "rollup --config rollup.config.js -w",

rollup.config.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ if you want to view the source visit the plugins github repository
1212
`;
1313

1414
export default {
15-
input: 'main.ts',
15+
input: 'src/main.ts',
1616
output: {
1717
dir: '.',
1818
sourcemap: 'inline',

scripts/install.sh

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
#!/bin/bash
2+
3+
cp main.js .obsidian/plugins/obsidian-advanced-new-file/
4+
cp manifest.json .obsidian/plugins/obsidian-advanced-new-file/
5+
cp styles.css .obsidian/plugins/obsidian-advanced-new-file/

src/main.ts

+28
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import { Plugin } from 'obsidian';
2+
import { ChooseFolderModal } from './modal';
3+
4+
5+
export default class AdvancedNewFilePlugin extends Plugin {
6+
async onload() {
7+
console.log('loading plugin');
8+
9+
this.addCommand({
10+
id: 'advanced-new-file',
11+
name: 'Create note',
12+
checkCallback: (checking: boolean) => {
13+
let leaf = this.app.workspace.activeLeaf;
14+
if (leaf) {
15+
if (!checking) {
16+
new ChooseFolderModal(this.app).open();
17+
}
18+
return true;
19+
}
20+
return false;
21+
}
22+
});
23+
}
24+
25+
onunload() {
26+
console.log('unloading plugin');
27+
}
28+
}

src/modal.ts

+91
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
import { App, FuzzySuggestModal, TFolder, Notice } from 'obsidian';
2+
3+
const EMPTY_TEXT = 'No files found to append content. Enter to create a new one.'
4+
const PLACEHOLDER_TEXT = 'Type file to append to or create';
5+
const instructions = [
6+
{command: '↑↓', purpose: 'to navigate'},
7+
{command: '↵', purpose: 'to choose folder'},
8+
{command: 'esc', purpose: 'to dismiss'}
9+
];
10+
11+
export class ChooseFolderModal extends FuzzySuggestModal<TFolder>{
12+
folders: TFolder[];
13+
chooseFolder: HTMLDivElement;
14+
suggestionEmpty: HTMLDivElement;
15+
noSuggestion: boolean;
16+
17+
constructor(app: App) {
18+
super(app);
19+
this.init();
20+
}
21+
22+
init() {
23+
const files = this.app.vault.getFiles();
24+
const folders = new Set() as Set<TFolder>;
25+
for (const file of files) {
26+
folders.add(file.parent)
27+
}
28+
this.folders = Array.from(folders);
29+
this.emptyStateText = EMPTY_TEXT;
30+
this.setPlaceholder(PLACEHOLDER_TEXT);
31+
this.setInstructions(instructions);
32+
this.initChooseFolderItem();
33+
}
34+
35+
getItems(): TFolder[] {
36+
return this.folders;
37+
}
38+
39+
getItemText(item: TFolder): string {
40+
this.noSuggestion = false;
41+
return item.path;
42+
}
43+
44+
onNoSuggestion() {
45+
this.noSuggestion = true;
46+
this.resultContainerEl.childNodes.forEach(c => c.parentNode.removeChild(c));
47+
this.chooseFolder.innerText = this.inputEl.value;
48+
this.itemInstructionMessage(this.chooseFolder, 'No folder found');
49+
this.resultContainerEl.appendChild(this.chooseFolder);
50+
this.resultContainerEl.appendChild(this.suggestionEmpty);
51+
}
52+
53+
onChooseItem(item: TFolder, evt: MouseEvent | KeyboardEvent): void {
54+
if(this.noSuggestion) {
55+
// TODO make something on
56+
return;
57+
}
58+
this.createNewNote(item);
59+
}
60+
61+
initChooseFolderItem() {
62+
this.chooseFolder = document.createElement('div');
63+
this.chooseFolder.addClasses(['suggestion-item', 'is-selected']);
64+
this.suggestionEmpty = document.createElement('div');
65+
this.suggestionEmpty.addClass('suggestion-empty');
66+
this.suggestionEmpty.innerText = EMPTY_TEXT;
67+
}
68+
69+
itemInstructionMessage(resultEl: HTMLElement, message: string) {
70+
const el = document.createElement('kbd');
71+
el.addClass('suggestion-hotkey');
72+
el.innerText = message;
73+
resultEl.appendChild(el);
74+
}
75+
76+
async createNewNote(item: TFolder) : Promise<void> {
77+
const fileName = `${item.path}/Untitled.md`
78+
try {
79+
// If files exists, throw error
80+
const fileExists = await this.app.vault.adapter.exists(fileName);
81+
if(fileExists){
82+
throw new Error("Untitled file already exists");
83+
}
84+
const file = await this.app.vault.create(fileName, "");
85+
this.app.workspace.activeLeaf.openFile(file);
86+
} catch (error) {
87+
new Notice(error);
88+
}
89+
}
90+
91+
}

styles.css

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
/* Sets all the text color to red! */
2-
body {
2+
/* body {
33
color: red;
4-
}
4+
} */

versions.json

-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
11
{
2-
"1.0.1": "0.9.12",
32
"1.0.0": "0.9.7"
43
}

0 commit comments

Comments
 (0)