Initial commit

This commit is contained in:
Jonas Blatt 2022-12-17 18:42:48 +01:00
commit e41c172422
14 changed files with 476 additions and 0 deletions

1
.github/FUNDING.yml vendored Normal file
View file

@ -0,0 +1 @@
ko_fi: "joleaf"

88
.github/workflows/release.yml vendored Normal file
View 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
View 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
View 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
View 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
View file

@ -0,0 +1,59 @@
# Email Block for Obsidian [![GitHub tag (latest by date)](https://img.shields.io/github/v/tag/joleaf/obsidian-email-block-plugin)](https://github.com/joleaf/obsidian-email-block-plugin/releases) [![Release Obsidian Plugin](https://github.com/joleaf/obsidian-email-block-plugin/actions/workflows/release.yml/badge.svg)](https://github.com/joleaf/obsidian-email-block-plugin/actions/workflows/release.yml) ![GitHub all releases](https://img.shields.io/github/downloads/joleaf/obsidian-email-block-plugin/total)
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
![Example](example/email-block-plugin.gif)
## 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
View 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));

Binary file not shown.

After

Width:  |  Height:  |  Size: 33 KiB

132
main.ts Normal file
View 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
View 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
View 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
View 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
View 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
View file

@ -0,0 +1,3 @@
{
"0.1.0": "0.15.0"
}