mirror of
https://github.com/tmcw/obsidian-freeform.git
synced 2026-07-22 10:10:32 +00:00
Initial commit
This commit is contained in:
commit
e41c172422
14 changed files with 476 additions and 0 deletions
1
.github/FUNDING.yml
vendored
Normal file
1
.github/FUNDING.yml
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
ko_fi: "joleaf"
|
||||
88
.github/workflows/release.yml
vendored
Normal file
88
.github/workflows/release.yml
vendored
Normal file
|
|
@ -0,0 +1,88 @@
|
|||
name: Release Obsidian Plugin
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- '*'
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
fetch-depth: 0 # otherwise, you will failed to push refs to dest repo
|
||||
- name: Use Node.js
|
||||
uses: actions/setup-node@v1
|
||||
with:
|
||||
node-version: '18.x'
|
||||
- name: Get Version
|
||||
id: version
|
||||
run: |
|
||||
echo "::set-output name=tag::$(git describe --abbrev=0)"
|
||||
# Build the plugin
|
||||
- name: Build
|
||||
id: build
|
||||
run: |
|
||||
npm install
|
||||
npm run build --if-present
|
||||
# Package the required files into a zip
|
||||
- name: Package
|
||||
run: |
|
||||
mkdir ${{ github.event.repository.name }}
|
||||
cp main.js manifest.json README.md styles.css ${{ github.event.repository.name }}
|
||||
zip -r ${{ github.event.repository.name }}.zip ${{ github.event.repository.name }}
|
||||
# Create the release on github
|
||||
- name: Create Release
|
||||
id: create_release
|
||||
uses: actions/create-release@v1
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
VERSION: ${{ github.ref }}
|
||||
with:
|
||||
tag_name: ${{ github.ref }}
|
||||
release_name: ${{ github.ref }}
|
||||
draft: false
|
||||
prerelease: false
|
||||
# Upload the packaged release file
|
||||
- name: Upload zip file
|
||||
id: upload-zip
|
||||
uses: actions/upload-release-asset@v1
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
upload_url: ${{ steps.create_release.outputs.upload_url }}
|
||||
asset_path: ./${{ github.event.repository.name }}.zip
|
||||
asset_name: ${{ github.event.repository.name }}-${{ steps.version.outputs.tag }}.zip
|
||||
asset_content_type: application/zip
|
||||
# Upload the main.js
|
||||
- name: Upload main.js
|
||||
id: upload-main
|
||||
uses: actions/upload-release-asset@v1
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
upload_url: ${{ steps.create_release.outputs.upload_url }}
|
||||
asset_path: ./main.js
|
||||
asset_name: main.js
|
||||
asset_content_type: text/javascript
|
||||
# Upload the manifest.json
|
||||
- name: Upload manifest.json
|
||||
id: upload-manifest
|
||||
uses: actions/upload-release-asset@v1
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
upload_url: ${{ steps.create_release.outputs.upload_url }}
|
||||
asset_path: ./manifest.json
|
||||
asset_name: manifest.json
|
||||
asset_content_type: application/json
|
||||
# Upload the styles.css
|
||||
- name: Upload styles.css
|
||||
id: upload-styles
|
||||
uses: actions/upload-release-asset@v1
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
upload_url: ${{ steps.create_release.outputs.upload_url }}
|
||||
asset_path: ./styles.css
|
||||
asset_name: styles.css
|
||||
asset_content_type: text/css
|
||||
13
.gitignore
vendored
Normal file
13
.gitignore
vendored
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
# Intellij
|
||||
*.iml
|
||||
.idea
|
||||
|
||||
# npm
|
||||
node_modules
|
||||
package-lock.json
|
||||
|
||||
# build
|
||||
main.js
|
||||
*.js.map
|
||||
|
||||
.DS_Store
|
||||
9
CHANGELOG.md
Normal file
9
CHANGELOG.md
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
# Changelog
|
||||
|
||||
All changes to this plugin are listed here.
|
||||
|
||||
## 0.1.0 (17.12.2022)
|
||||
|
||||
### Added
|
||||
|
||||
- Base functionality
|
||||
21
LICENSE
Normal file
21
LICENSE
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
MIT License
|
||||
|
||||
Copyright (c) 2022 Jonas Blatt
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
59
README.md
Normal file
59
README.md
Normal file
|
|
@ -0,0 +1,59 @@
|
|||
# Email Block for Obsidian [](https://github.com/joleaf/obsidian-email-block-plugin/releases) [](https://github.com/joleaf/obsidian-email-block-plugin/actions/workflows/release.yml) 
|
||||
|
||||
This plugin lets you plan small emails inside your [Obsidian](https://www.obsidian.md) notes.
|
||||
|
||||
## Install ..
|
||||
|
||||
### .. automatically in Obsidian (not yet)
|
||||
|
||||
1. Go to **Community Plugins** in your Obsidian Settings and **disable** Safe Mode
|
||||
2. Click on **Browse** and search for "Email Block"
|
||||
3. Click install
|
||||
4. Toggle the plugin on in the **Community Plugins** tab
|
||||
|
||||
### .. manually from this repo
|
||||
|
||||
1. Download the latest [release](https://github.com/joleaf/obsidian-email-block-plugin/releases) `*.zip` file.
|
||||
2. Unpack the zip in the `.obsidan/plugins` folder of your obsidian vault
|
||||
|
||||
## How to use
|
||||
|
||||
Add the "email" code block into your note:
|
||||
|
||||
````
|
||||
```email
|
||||
to: info@randommail.com
|
||||
subject: My Subject
|
||||
body: "Hey info,
|
||||
|
||||
here is some content"
|
||||
```
|
||||
````
|
||||
|
||||
### Parameter
|
||||
|
||||
You can customize the view with the following parameters:
|
||||
|
||||
| Parameter | Description | Values |
|
||||
|------------|--------------------------------------------------------------------|----------------------------|
|
||||
| to | The main receiver of the mail. Multiple receiver seperated by ",". | String value |
|
||||
| cc | The cc receiver of the mail. Multiple receiver seperated by ",". | String value |
|
||||
| cc | The bcc receiver of the mail. Multiple receiver seperated by ",". | String value |
|
||||
| subject | The subject of the email. | String value |
|
||||
| body | The body of the email. | String value |
|
||||
| showmailto | Show the "mailto" link after the mail body. | true/false (Default: true) |
|
||||
|
||||
### Example
|
||||
|
||||

|
||||
|
||||
## How to dev
|
||||
|
||||
1. Clone this repo into the plugin folder of a (non-productive) vault (`.obsidian/plugins/`)
|
||||
2. `npm i`
|
||||
3. `npm run dev`
|
||||
4. Toggle the plugin on in the **Community Plugins** tab
|
||||
|
||||
## Donate
|
||||
|
||||
<a href='https://ko-fi.com/joleaf' target='_blank'><img height='35' style='border:0px;height:46px;' src='https://az743702.vo.msecnd.net/cdn/kofi3.png?v=0' border='0' alt='Buy Me a Coffee at ko-fi.com' />
|
||||
42
esbuild.config.mjs
Normal file
42
esbuild.config.mjs
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
import esbuild from "esbuild";
|
||||
import process from "process";
|
||||
import builtins from 'builtin-modules'
|
||||
|
||||
const banner =
|
||||
`/*
|
||||
THIS IS A GENERATED/BUNDLED FILE BY ESBUILD
|
||||
if you want to view the source, please visit the github repository of this plugin
|
||||
*/
|
||||
`;
|
||||
|
||||
const prod = (process.argv[2] === 'production');
|
||||
|
||||
esbuild.build({
|
||||
banner: {
|
||||
js: banner,
|
||||
},
|
||||
entryPoints: ['main.ts'],
|
||||
bundle: true,
|
||||
external: [
|
||||
'obsidian',
|
||||
'electron',
|
||||
'@codemirror/autocomplete',
|
||||
'@codemirror/collab',
|
||||
'@codemirror/commands',
|
||||
'@codemirror/language',
|
||||
'@codemirror/lint',
|
||||
'@codemirror/search',
|
||||
'@codemirror/state',
|
||||
'@codemirror/view',
|
||||
'@lezer/common',
|
||||
'@lezer/highlight',
|
||||
'@lezer/lr',
|
||||
...builtins],
|
||||
format: 'cjs',
|
||||
watch: !prod,
|
||||
target: 'es2018',
|
||||
logLevel: "info",
|
||||
sourcemap: prod ? false : 'inline',
|
||||
treeShaking: true,
|
||||
outfile: 'main.js',
|
||||
}).catch(() => process.exit(1));
|
||||
BIN
example/email-block-plugin.gif
Normal file
BIN
example/email-block-plugin.gif
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 33 KiB |
132
main.ts
Normal file
132
main.ts
Normal file
|
|
@ -0,0 +1,132 @@
|
|||
import {Plugin} from "obsidian";
|
||||
import YAML from 'yaml'
|
||||
|
||||
interface MailBlockParameters {
|
||||
to: string | undefined;
|
||||
cc: string | undefined;
|
||||
bcc: string | undefined;
|
||||
subject: string | undefined;
|
||||
body: string | undefined; // Future version: can be a note, which will be formatted as html for the body
|
||||
showmailto: boolean | undefined;
|
||||
}
|
||||
|
||||
export default class MailBlockPlugin extends Plugin {
|
||||
|
||||
async onload() {
|
||||
console.log("email block loading...");
|
||||
|
||||
this.registerMarkdownCodeBlockProcessor("email", async (src, el, ctx) => {
|
||||
// Get Parameters
|
||||
let parameters: MailBlockParameters | null = null;
|
||||
try {
|
||||
parameters = this.readParameters(src);
|
||||
} catch (e) {
|
||||
el.createEl("h3", {text: "Email parameters invalid: \n" + e.message});
|
||||
return;
|
||||
}
|
||||
|
||||
console.log("Render the Email");
|
||||
try {
|
||||
const rootEl = el.createEl("div", {cls: "email-block"});
|
||||
//rootEl.createEl("a", {text: "Send", href: "mailto:" + parameters.to + "#subject" + parameters.subject})
|
||||
if (parameters.to !== undefined) {
|
||||
rootEl.createEl("div", {cls: "email-block-info", text: "To:"});
|
||||
rootEl.createEl("div", {cls: "email-block-info-value", text: this.renderAddress(parameters.to)});
|
||||
}
|
||||
if (parameters.cc !== undefined) {
|
||||
rootEl.createEl("div", {cls: "email-block-info", text: "Cc:"});
|
||||
rootEl.createEl("div", {cls: "email-block-info-value", text: this.renderAddress(parameters.cc)});
|
||||
}
|
||||
if (parameters.bcc !== undefined) {
|
||||
rootEl.createEl("div", {cls: "email-block-info", text: "Bcc:"});
|
||||
rootEl.createEl("div", {cls: "email-block-info-value", text: this.renderAddress(parameters.bcc)});
|
||||
}
|
||||
rootEl.createEl("div", {cls: "email-block-info", text: "Subject:"});
|
||||
rootEl.createEl("div", {cls: "email-block-info-value", text: parameters.subject});
|
||||
const bodyContent = rootEl.createEl("div", {cls: "email-block-body"});
|
||||
this.renderBody(bodyContent, parameters.body);
|
||||
const data = "mailto:" + this.encodeToHtml(parameters.to) +
|
||||
"?subject=" + this.encodeToHtml(parameters.subject) +
|
||||
"&cc=" + this.encodeToHtml(parameters.cc) +
|
||||
"&bcc=" + this.encodeToHtml(parameters.bcc) +
|
||||
"&body=" + this.encodeToHtml(parameters.body);
|
||||
if (parameters.showmailto) {
|
||||
rootEl.createEl("a", {href: data, text: "Mailto"});
|
||||
}
|
||||
} catch (error) {
|
||||
el.createEl("h3", {text: error});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
private readParameters(jsonString: string) {
|
||||
if (jsonString.contains("[[") && !jsonString.contains('"[[')) {
|
||||
jsonString = jsonString.replace("[[", '"[[');
|
||||
jsonString = jsonString.replace("]]", ']]"');
|
||||
}
|
||||
|
||||
const parameters: MailBlockParameters = YAML.parse(jsonString);
|
||||
|
||||
parameters.to = this.fixAddress(parameters.to)
|
||||
parameters.cc = this.fixAddress(parameters.cc)
|
||||
parameters.bcc = this.fixAddress(parameters.bcc)
|
||||
|
||||
if (parameters.subject == undefined) {
|
||||
parameters.subject = ""
|
||||
}
|
||||
|
||||
if (parameters.showmailto == undefined) {
|
||||
parameters.showmailto = true;
|
||||
}
|
||||
|
||||
//Transform internal Link to external
|
||||
if (parameters.body === undefined) {
|
||||
parameters.body = "";
|
||||
} else if (parameters.body.startsWith("[[")) {
|
||||
parameters.body = parameters.body.substring(2, parameters.body.length - 2);
|
||||
// @ts-ignore
|
||||
parameters.url = this.app.metadataCache.getFirstLinkpathDest(
|
||||
parameters.body,
|
||||
""
|
||||
).path;
|
||||
// TODO: for future version: transform content to html!
|
||||
}
|
||||
|
||||
return parameters;
|
||||
}
|
||||
|
||||
private fixAddress(address: string | undefined) {
|
||||
if (address === undefined) {
|
||||
return undefined;
|
||||
}
|
||||
let fixedAddress = address.replace(/\s/g, "").replace(";", ",");
|
||||
return fixedAddress;
|
||||
}
|
||||
|
||||
private renderAddress(address: string) {
|
||||
return address.split(",").join(", ");
|
||||
}
|
||||
|
||||
private renderBody(bodyContentEl: HTMLElement, bodyContent: string | undefined) {
|
||||
if (bodyContent === undefined) {
|
||||
return;
|
||||
}
|
||||
let lines = bodyContent.split("\n");
|
||||
lines.forEach(line => {
|
||||
bodyContentEl.createEl("div", {cls: "email-block-body-line", text: line});
|
||||
})
|
||||
}
|
||||
|
||||
private encodeToHtml(rawStr: string | undefined) {
|
||||
if (rawStr === undefined) {
|
||||
return "";
|
||||
}
|
||||
let retStr = encodeURIComponent(rawStr);
|
||||
return retStr;
|
||||
}
|
||||
|
||||
onunload() {
|
||||
console.log("Unloading email plugin...");
|
||||
}
|
||||
}
|
||||
11
manifest.json
Normal file
11
manifest.json
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
{
|
||||
"id": "email-block-plugin",
|
||||
"name": "Email code block",
|
||||
"version": "0.1.0",
|
||||
"minAppVersion": "0.15.0",
|
||||
"description": "This plugin renders an email code block.",
|
||||
"author": "JoLeaf",
|
||||
"authorUrl": "https://github.com/JoLeaf",
|
||||
"fundingUrl": "https://ko-fi.com/joleaf",
|
||||
"isDesktopOnly": true
|
||||
}
|
||||
27
package.json
Normal file
27
package.json
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
{
|
||||
"name": "email-block-plugin",
|
||||
"version": "0.1.0",
|
||||
"description": "This plugin renders an email code block.",
|
||||
"main": "main.js",
|
||||
"scripts": {
|
||||
"dev": "node esbuild.config.mjs",
|
||||
"build": "tsc -noEmit -skipLibCheck && node esbuild.config.mjs production",
|
||||
"version": "node version-bump.mjs && git add manifest.json versions.json"
|
||||
},
|
||||
"keywords": [],
|
||||
"author": "",
|
||||
"license": "MIT",
|
||||
"devDependencies": {
|
||||
"@types/node": "^16.11.6",
|
||||
"@typescript-eslint/eslint-plugin": "5.29.0",
|
||||
"@typescript-eslint/parser": "5.29.0",
|
||||
"builtin-modules": "3.3.0",
|
||||
"esbuild": "0.14.47",
|
||||
"obsidian": "latest",
|
||||
"tslib": "2.4.0",
|
||||
"typescript": "4.7.4"
|
||||
},
|
||||
"dependencies": {
|
||||
"yaml": "^2.1.3"
|
||||
}
|
||||
}
|
||||
41
styles.css
Normal file
41
styles.css
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
/* Styles */
|
||||
|
||||
.email-block {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 8fr;
|
||||
row-gap: 5px;
|
||||
border: 1px solid gray;
|
||||
padding: 4px;
|
||||
}
|
||||
|
||||
.email-block-info {
|
||||
font-style: italic;
|
||||
font-size: 80%;
|
||||
align-self: center;
|
||||
}
|
||||
|
||||
.email-block-info-value {
|
||||
font-weight: bold;
|
||||
font-size: 90%;
|
||||
align-self: center;
|
||||
}
|
||||
|
||||
.email-block-body {
|
||||
grid-column-start: 1;
|
||||
grid-column-end: span 2;
|
||||
border-left: 1px gray solid;
|
||||
padding-left: 5px;
|
||||
}
|
||||
|
||||
.email-block-body-line {
|
||||
|
||||
}
|
||||
|
||||
.email-block-mailto {
|
||||
grid-column-start: 1;
|
||||
grid-column-end: span 2;
|
||||
}
|
||||
|
||||
.email-block-error {
|
||||
color: red !important;
|
||||
}
|
||||
29
tsconfig.json
Normal file
29
tsconfig.json
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
{
|
||||
"compilerOptions": {
|
||||
"baseUrl": ".",
|
||||
"inlineSourceMap": true,
|
||||
"inlineSources": true,
|
||||
"module": "ESNext",
|
||||
"target": "ES6",
|
||||
"allowJs": true,
|
||||
"noImplicitAny": true,
|
||||
"moduleResolution": "node",
|
||||
"importHelpers": true,
|
||||
"isolatedModules": true,
|
||||
"strictNullChecks": true,
|
||||
"lib": [
|
||||
"DOM",
|
||||
"ES5",
|
||||
"ES6",
|
||||
"ES7"
|
||||
],
|
||||
"allowSyntheticDefaultImports": true
|
||||
},
|
||||
"include": [
|
||||
"**/*.ts"
|
||||
],
|
||||
"typeRoots": [
|
||||
"./typings",
|
||||
"./node_modules/@types/"
|
||||
]
|
||||
}
|
||||
3
versions.json
Normal file
3
versions.json
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
{
|
||||
"0.1.0": "0.15.0"
|
||||
}
|
||||
Loading…
Reference in a new issue