commit 0f1cc5ecd8deb9972b2d3811c367138369f42ee7 Author: lukeleppan Date: Mon Nov 9 15:33:44 2020 +0200 first commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..4776cd7 --- /dev/null +++ b/.gitignore @@ -0,0 +1,13 @@ +# Intellij +*.iml +.idea + +# npm +node_modules +package-lock.json + +# build +main.js +*.js.map +test-vault/ +*.zip \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..214ba76 --- /dev/null +++ b/README.md @@ -0,0 +1,7 @@ +## Better Word Count + +This plugin is the same as the built-in **Word Count** plugin, except when you select text, it will count the selected word instead of the whole document. I recommend turning off the built-in **Word Count** because this plugin is designed to replace that. + +**Note:** This plugin has only been tested with English. + +![Better Count Word](https://raw.githubusercontent.com/lukeleppan/obsidian-discordrpc/master/assets/better-word-count.gif) diff --git a/assets/better-word-count.gif b/assets/better-word-count.gif new file mode 100644 index 0000000..1b5562e Binary files /dev/null and b/assets/better-word-count.gif differ diff --git a/manifest.json b/manifest.json new file mode 100644 index 0000000..ac31146 --- /dev/null +++ b/manifest.json @@ -0,0 +1,9 @@ +{ + "id": "better-word-count", + "name": "Better Word Count", + "version": "0.1.0", + "description": "Counts the words of selected test in the editor.", + "author": "Luke Leppan", + "authorUrl": "https://lukeleppan.com", + "isDesktopOnly": false +} \ No newline at end of file diff --git a/package.json b/package.json new file mode 100644 index 0000000..b1e8f68 --- /dev/null +++ b/package.json @@ -0,0 +1,28 @@ +{ + "name": "better-word-count", + "version": "0.1.0", + "description": "Counts the words of selected test in the editor.", + "main": "main.js", + "scripts": { + "dev": "rollup --config rollup.config.js -w", + "build": "rollup --config rollup.config.js" + }, + "keywords": [ + "obsidian", + "obsidian-md", + "obsidian-plugin" + ], + "author": "Luke Leppan", + "license": "MIT", + "devDependencies": { + "@rollup/plugin-commonjs": "^15.1.0", + "@rollup/plugin-node-resolve": "^9.0.0", + "@rollup/plugin-typescript": "^6.0.0", + "@types/node": "^14.14.2", + "obsidian": "https://github.com/obsidianmd/obsidian-api/tarball/master", + "rollup": "^2.32.1", + "rollup-plugin-copy": "^3.3.0", + "tslib": "^2.0.3", + "typescript": "^4.0.3" + } +} diff --git a/rollup.config.js b/rollup.config.js new file mode 100644 index 0000000..d6cc18a --- /dev/null +++ b/rollup.config.js @@ -0,0 +1,27 @@ +import typescript from '@rollup/plugin-typescript'; +import {nodeResolve} from '@rollup/plugin-node-resolve'; +import commonjs from '@rollup/plugin-commonjs'; +import copy from 'rollup-plugin-copy'; +const TEST_VAULT = 'test-vault/.obsidian/plugins/better-word-count'; + +export default { + input: 'src/main.ts', + output: { + dir: 'dist/', + sourcemap: 'inline', + format: 'cjs', + exports: 'default' + }, + external: ['obsidian'], + plugins: [ + typescript(), + nodeResolve({browser: true}), + commonjs(), + copy({ + targets: [ + { src: 'dist/main.js', dest: TEST_VAULT }, + { src: ['manifest.json'], dest: TEST_VAULT } + ], flatten: true + }) + ] +}; \ No newline at end of file diff --git a/src/main.ts b/src/main.ts new file mode 100644 index 0000000..a42d783 --- /dev/null +++ b/src/main.ts @@ -0,0 +1,90 @@ +import { App, MarkdownView, Modal, Plugin, TFile } from "obsidian"; +import { StatusBar } from "./status-bar"; + +export default class BetterWordCount extends Plugin { + public recentlyTyped: boolean; + public statusBar: StatusBar; + + onload() { + let statusBarEl = this.addStatusBarItem(); + this.statusBar = new StatusBar(statusBarEl); + + this.recentlyTyped = false; + + this.registerEvent( + this.app.workspace.on("file-open", this.onFileOpen, this) + ); + + this.registerEvent( + this.app.workspace.on("quick-preview", this.onQuickPreview, this) + ); + + let activeLeaf = this.app.workspace.activeLeaf; + let files: TFile[] = this.app.vault.getMarkdownFiles(); + + files.forEach((file) => { + if ((file.basename = activeLeaf.getDisplayText())) { + this.onFileOpen(file); + } + }); + } + + async onFileOpen(file: TFile) { + if (file && file.extension === "md") { + const contents = await this.app.vault.cachedRead(file); + this.updateWordCount(contents); + } else { + this.updateWordCount(""); + } + + let activeLeaf = this.app.workspace.activeLeaf; + if (!activeLeaf || !(activeLeaf.view instanceof MarkdownView)) { + return; + } + + let editor = activeLeaf.view.sourceMode.cmEditor; + + activeLeaf.view.registerInterval( + window.setInterval(async () => { + if (editor.somethingSelected()) { + let content: string = editor.getSelection(); + this.updateWordCount(content); + this.recentlyTyped = false; + } else if (file && file.extension === "md" && !this.recentlyTyped) { + const contents = await this.app.vault.cachedRead(file); + this.updateWordCount(contents); + } else if (!this.recentlyTyped) { + this.updateWordCount(""); + } + }, 500) + ); + } + + onQuickPreview(file: TFile, contents: string) { + const leaf = this.app.workspace.activeLeaf; + if (leaf && leaf.view.getViewType() === "markdown") { + this.recentlyTyped = true; + this.updateWordCount(contents); + } + } + + updateWordCount(text: string) { + let words = 0; + + const matches = text.match( + /[a-zA-Z0-9_\u0392-\u03c9\u00c0-\u00ff\u0600-\u06ff]+|[\u4e00-\u9fff\u3400-\u4dbf\uf900-\ufaff\u3040-\u309f\uac00-\ud7af]+/gm + ); + + if (matches) { + for (let i = 0; i < matches.length; i++) { + if (matches[i].charCodeAt(0) > 19968) { + words += matches[i].length; + } else { + words += 1; + } + } + } + + this.statusBar.displayText(`${words} words ` + `${text.length} characters`); + } +} diff --git a/src/status-bar.ts b/src/status-bar.ts new file mode 100644 index 0000000..0694273 --- /dev/null +++ b/src/status-bar.ts @@ -0,0 +1,11 @@ +export class StatusBar { + private statusBarEl: HTMLElement; + + constructor(statusBarEl: HTMLElement) { + this.statusBarEl = statusBarEl; + } + + displayText(text: string) { + this.statusBarEl.setText(text); + } +} diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..d148fe0 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,22 @@ +{ + "compilerOptions": { + "baseUrl": ".", + "inlineSourceMap": true, + "inlineSources": true, + "module": "ESNext", + "target": "es5", + "allowJs": true, + "noImplicitAny": true, + "moduleResolution": "node", + "importHelpers": true, + "lib": [ + "dom", + "es5", + "scripthost", + "es2015" + ] + }, + "include": [ + "**/*.ts" + ] +}