First commit

This commit is contained in:
kaffarell 2023-04-01 15:04:34 +02:00
parent 7212fbb64e
commit f0cfb30c41
14 changed files with 2500 additions and 98 deletions

10
.editorconfig Normal file
View file

@ -0,0 +1,10 @@
# top-most EditorConfig file
root = true
[*]
charset = utf-8
end_of_line = lf
insert_final_newline = true
indent_style = tab
indent_size = 4
tab_width = 4

3
.eslintignore Normal file
View file

@ -0,0 +1,3 @@
node_modules/
main.js

23
.eslintrc Normal file
View file

@ -0,0 +1,23 @@
{
"root": true,
"parser": "@typescript-eslint/parser",
"env": { "node": true },
"plugins": [
"@typescript-eslint"
],
"extends": [
"eslint:recommended",
"plugin:@typescript-eslint/eslint-recommended",
"plugin:@typescript-eslint/recommended"
],
"parserOptions": {
"sourceType": "module"
},
"rules": {
"no-unused-vars": "off",
"@typescript-eslint/no-unused-vars": ["error", { "args": "none" }],
"@typescript-eslint/ban-ts-comment": "off",
"no-prototype-builtins": "off",
"@typescript-eslint/no-empty-function": "off"
}
}

114
.gitignore vendored
View file

@ -1,104 +1,22 @@
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
lerna-debug.log*
# vscode
.vscode
# Diagnostic reports (https://nodejs.org/api/report.html)
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
# Intellij
*.iml
.idea
# Runtime data
pids
*.pid
*.seed
*.pid.lock
# npm
node_modules
# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov
# Don't include the compiled main.js file in the repo.
# They should be uploaded to GitHub releases instead.
main.js
# Coverage directory used by tools like istanbul
coverage
*.lcov
# Exclude sourcemaps
*.map
# nyc test coverage
.nyc_output
# obsidian
data.json
# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
.grunt
# Bower dependency directory (https://bower.io/)
bower_components
# node-waf configuration
.lock-wscript
# Compiled binary addons (https://nodejs.org/api/addons.html)
build/Release
# Dependency directories
node_modules/
jspm_packages/
# TypeScript v1 declaration files
typings/
# TypeScript cache
*.tsbuildinfo
# Optional npm cache directory
.npm
# Optional eslint cache
.eslintcache
# Microbundle cache
.rpt2_cache/
.rts2_cache_cjs/
.rts2_cache_es/
.rts2_cache_umd/
# Optional REPL history
.node_repl_history
# Output of 'npm pack'
*.tgz
# Yarn Integrity file
.yarn-integrity
# dotenv environment variables file
.env
.env.test
# parcel-bundler cache (https://parceljs.org/)
.cache
# Next.js build output
.next
# Nuxt.js build / generate output
.nuxt
dist
# Gatsby files
.cache/
# Comment in the public line in if your project uses Gatsby and *not* Next.js
# https://nextjs.org/blog/next-9-1#public-directory-support
# public
# vuepress build output
.vuepress/dist
# Serverless directories
.serverless/
# FuseBox cache
.fusebox/
# DynamoDB Local files
.dynamodb/
# TernJS port file
.tern-port
# Exclude macOS Finder (System Explorer) View States
.DS_Store

1
.npmrc Normal file
View file

@ -0,0 +1 @@
tag-version-prefix=""

View file

@ -1,2 +1,3 @@
# obsidian-tesseract-ocr
Runs ocr on pasted images and posts result in details box. This allows to search in images.

48
esbuild.config.mjs Normal file
View file

@ -0,0 +1,48 @@
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");
const context = await esbuild.context({
banner: {
js: banner,
},
entryPoints: ["src/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",
target: "es2018",
logLevel: "info",
sourcemap: prod ? false : "inline",
treeShaking: true,
outfile: "dist/main.js",
});
if (prod) {
await context.rebuild();
process.exit(0);
} else {
await context.watch();
}

11
manifest.json Normal file
View file

@ -0,0 +1,11 @@
{
"id": "obsidian-tesseract-ocr",
"name": "Obsidian Image OCR",
"version": "1.0.0",
"minAppVersion": "0.15.0",
"description": "Runs ocr on pasted images and posts result in details box. This allows to search in images.",
"author": "kaffarell",
"authorUrl": "https://github.com/kaffarell",
"fundingUrl": "https://github.com/kaffarell",
"isDesktopOnly": false
}

2214
package-lock.json generated Normal file

File diff suppressed because it is too large Load diff

24
package.json Normal file
View file

@ -0,0 +1,24 @@
{
"name": "obsidian-tesseract-ocr",
"version": "1.0.0",
"description": "Runs ocr on pasted images and posts result in details box. This allows to search in images.",
"main": "dist/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.17.3",
"obsidian": "latest",
"tslib": "2.4.0",
"typescript": "4.7.4"
}
}

108
src/main.ts Normal file
View file

@ -0,0 +1,108 @@
import { App, Editor, FileSystemAdapter, MarkdownView, Modal, Notice, Plugin, PluginSettingTab, Setting, TAbstractFile, Vault } from 'obsidian';
import { exec as execCb } from 'child_process';
import {promisify} from 'util';
const exec = promisify(execCb);
// Remember to rename these classes and interfaces!
interface MyPluginSettings {
imagePath: string;
}
const DEFAULT_SETTINGS: MyPluginSettings = {
imagePath: 'Meta/Attachments'
}
export default class MyPlugin extends Plugin {
settings: MyPluginSettings;
async onload() {
await this.loadSettings();
// This adds a simple command that can be triggered anywhere
this.addCommand({
id: 'run-on-all-images',
name: 'Run tesseract on all images',
callback: () => {
let allImages: TAbstractFile[] = [];
Vault.recurseChildren(app.vault.getRoot(), (file: TAbstractFile) => {
if(file.path.contains(this.settings.imagePath) && this.isImage(file.name)) {
allImages.push(file);
}
});
Vault.recurseChildren(app.vault.getRoot(), (file: TAbstractFile) => {
if(this.isMarkdown(file.name)) {
//console.log(file.name);
let linkRegex = /!\[\[.*\]\]/g
this.app.vault.adapter.read(file.path).then(content => {
// Search for ![[]] links in content
let matches = [...content.matchAll(linkRegex)];
matches.forEach(match => {
// Now check if the link content exists as a image file
let imageFile = allImages.find(e => {
return match[0].contains(e.name);
});
if (imageFile !== undefined) {
// We found a link with a file, now we need to check if the details alread exist
if(!content.contains(match[0] + '<details>')) {
// details don't exist yet, run tesseract
console.log('details dont exist on file: ' + file.name + ' link: ' + match[0]);
this.getTextFromImage(imageFile.path).then(text => {
//console.log(text);
});
}else {
console.log('details already added on file: ' + file.name + ' link: ' + match[0]);
}
}
})
});
}
});
console.log(allImages.length);
}
});
}
onunload() {
}
async loadSettings() {
this.settings = Object.assign({}, DEFAULT_SETTINGS, await this.loadData());
}
async saveSettings() {
await this.saveData(this.settings);
}
private isImage(fileName: string): boolean {
if(['jpg','png','jpeg'].includes(fileName.split('.')[1])) {
return true;
}else {
return false;
}
}
private isMarkdown(fileName: string): boolean {
if(['md'].includes(fileName.split('.')[1])) {
return true;
}else {
return false;
}
}
private async getTextFromImage(filePath: string): Promise<string> {
// TODO : get console output
let fullPath = (this.app.vault.adapter as FileSystemAdapter).getFullPath(filePath);
console.log('command to be run: ' + 'tesseract ' + fullPath);
try {
const { stdout, stderr } = await exec('tesseract ' + fullPath);
console.log('stderr:', stderr);
return stdout;
} catch (e) {
console.error(e);
return e;
}
}
}

24
tsconfig.json Normal file
View file

@ -0,0 +1,24 @@
{
"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"
]
},
"include": [
"**/*.ts"
]
}

14
version-bump.mjs Normal file
View file

@ -0,0 +1,14 @@
import { readFileSync, writeFileSync } from "fs";
const targetVersion = process.env.npm_package_version;
// read minAppVersion from manifest.json and bump version to target version
let manifest = JSON.parse(readFileSync("manifest.json", "utf8"));
const { minAppVersion } = manifest;
manifest.version = targetVersion;
writeFileSync("manifest.json", JSON.stringify(manifest, null, "\t"));
// update versions.json with target version and minAppVersion from manifest.json
let versions = JSON.parse(readFileSync("versions.json", "utf8"));
versions[targetVersion] = minAppVersion;
writeFileSync("versions.json", JSON.stringify(versions, null, "\t"));

3
versions.json Normal file
View file

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