Merge commit 'a7a196e10ff1b3429e9d6094dc250929d36474cf' into jpg

This commit is contained in:
2025-09-05 14:14:19 +02:00
17 changed files with 105 additions and 650 deletions

1
content/.gitignore vendored
View File

@@ -1,3 +1,4 @@
.obsidian/workspace.json .obsidian/workspace.json
.obsidian/workspace-mobile.json
0- Do-Not-Commit 0- Do-Not-Commit
.DS_Store .DS_Store

View File

@@ -1,5 +1,4 @@
[ [
"obsidian-markdown-furigana", "obsidian-markdown-furigana",
"obsidian-style-settings", "obsidian-style-settings"
"obsidian42-brat"
] ]

View File

@@ -27,5 +27,7 @@
"file-recovery": true, "file-recovery": true,
"publish": false, "publish": false,
"sync": false, "sync": false,
"webviewer": false "webviewer": false,
"footnotes": false,
"bases": true
} }

View File

@@ -9,29 +9,29 @@ var obsidian = require('obsidian');
var state = require('@codemirror/state'); var state = require('@codemirror/state');
var view = require('@codemirror/view'); var view = require('@codemirror/view');
/****************************************************************************** /******************************************************************************
Copyright (c) Microsoft Corporation. Copyright (c) Microsoft Corporation.
Permission to use, copy, modify, and/or distribute this software for any Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted. purpose with or without fee is hereby granted.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE. PERFORMANCE OF THIS SOFTWARE.
***************************************************************************** */ ***************************************************************************** */
function __awaiter(thisArg, _arguments, P, generator) { function __awaiter(thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) { return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next()); step((generator = generator.apply(thisArg, _arguments || [])).next());
}); });
} }
// Regular Expression for {{kanji|kana|kana|...}} format // Regular Expression for {{kanji|kana|kana|...}} format

View File

@@ -1,10 +1,10 @@
{ {
"id": "obsidian-markdown-furigana", "id": "obsidian-markdown-furigana",
"name": "Markdown Furigana", "name": "Markdown Furigana",
"version": "1.3.0", "version": "1.3.0",
"minAppVersion": "0.9.12", "minAppVersion": "0.9.12",
"description": "Simple Markdown to Furigana Rendering Plugin for Obsidian.", "description": "Simple Markdown to Furigana Rendering Plugin for Obsidian.",
"author": "Steven Kraft", "author": "Steven Kraft",
"authorUrl": "https://github.com/steven-kraft/obsidian-markdown-furigana", "authorUrl": "https://github.com/steven-kraft/obsidian-markdown-furigana",
"isDesktopOnly": false "isDesktopOnly": false
} }

View File

@@ -1,377 +0,0 @@
/*
THIS IS A GENERATED/BUNDLED FILE BY ESBUILD
if you want to view the source, please visit the github repository of this plugin
*/
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
// main.ts
var main_exports = {};
__export(main_exports, {
default: () => Opener
});
module.exports = __toCommonJS(main_exports);
var import_obsidian2 = require("obsidian");
// node_modules/monkey-around/mjs/index.js
function around(obj, factories) {
const removers = Object.keys(factories).map((key) => around1(obj, key, factories[key]));
return removers.length === 1 ? removers[0] : function() {
removers.forEach((r) => r());
};
}
function around1(obj, method, createWrapper) {
const original = obj[method], hadOwn = obj.hasOwnProperty(method);
let current = createWrapper(original);
if (original)
Object.setPrototypeOf(current, original);
Object.setPrototypeOf(wrapper, current);
obj[method] = wrapper;
return remove;
function wrapper(...args) {
if (current === original && obj[method] === wrapper)
remove();
return current.apply(this, args);
}
function remove() {
if (obj[method] === wrapper) {
if (hadOwn)
obj[method] = original;
else
delete obj[method];
}
if (current === original)
return;
current = original;
Object.setPrototypeOf(wrapper, original || Function);
}
}
// settings.ts
var import_obsidian = require("obsidian");
var OpenerSettingTab = class extends import_obsidian.PluginSettingTab {
display() {
const { containerEl } = this;
const plugin = this.plugin;
containerEl.empty();
new import_obsidian.Setting(containerEl).setName("New Tab Default").setDesc(
"Enable to open new files in a new tab (or existing tab, if it was previously opened). Disable for default Obsidian behavior."
).addToggle(
(toggle) => toggle.setValue(plugin.settings.newTab).onChange((value) => {
plugin.settings.newTab = value;
plugin.saveSettings();
})
);
new import_obsidian.Setting(containerEl).setName("PDF Default App").setDesc(
"Enable to open pdfs with system viewer app. Disable for default behavior (open pdfs in Obsidian)."
).addToggle(
(toggle) => toggle.setValue(plugin.settings.PDFApp).onChange((value) => {
plugin.settings.PDFApp = value;
plugin.saveSettings();
})
);
new import_obsidian.Setting(containerEl).setName("Default app only when Ctrl/Cmd-Key is held").setDesc(
"Open in default app only when Ctrl/Cmd-Key is held. Disable to always\u201A open with system viewer."
).addToggle(
(toggle) => toggle.setValue(plugin.settings.extOnlyWhenMetaKey).onChange((value) => {
plugin.settings.extOnlyWhenMetaKey = value;
plugin.saveSettings();
})
);
new import_obsidian.Setting(containerEl).setName("Open everything outside of Obsidian").setDesc(
"Enable to open all obsidian supported extensions with system viewer instead. Disable for default behavior (open within Obsidian). Defaults supported extensions are 'png', 'webp', 'jpg', 'jpeg', 'gif', 'bmp', 'svg', 'mp3', 'webm', 'wav', 'm4a', 'ogg','3gp', 'flac', 'mp4', 'ogv', 'mov', 'mkv'."
).addToggle(
(toggle) => toggle.setValue(plugin.settings.allExt).onChange((value) => {
plugin.settings.allExt = value;
plugin.saveSettings();
})
);
new import_obsidian.Setting(containerEl).setName("Open Outside Obsidian: Manual List").setDesc("This shouldn't be necessary, but you can manually enable custom extensions here.").addToggle(
(toggle) => toggle.setValue(plugin.settings.custExt).onChange((value) => {
plugin.settings.custExt = value;
plugin.saveSettings();
this.display();
})
);
if (plugin.settings.custExt) {
new import_obsidian.Setting(containerEl).setName("Manual List").setDesc("Enter extension names (without the dot, ie, just docx separated by newlines).").addTextArea((textArea) => {
textArea.inputEl.rows = 5;
textArea.setValue(plugin.settings.custExtList.join("\n")).onChange(async (value) => {
plugin.settings.custExtList = value.split("\n");
plugin.saveSettings();
});
}).settingEl.style.borderTop = "none";
}
}
};
// constants.ts
var DEFAULT_SETTINGS = {
newTab: true,
PDFApp: true,
extOnlyWhenMetaKey: true,
allExt: false,
custExt: false,
custExtList: []
};
// main.ts
var Opener = class extends import_obsidian2.Plugin {
constructor() {
super(...arguments);
this.isMetaKeyHeld = null;
this.sameTabOnce = false;
// Meta key listeners
// arrow syntax to preserve `this` context
this.keyDownHandler = (e) => {
if (e.key === "Meta" || e.key === "Control") {
this.isMetaKeyHeld = true;
}
};
this.keyUpHandler = (e) => {
if (e.key === "Meta" || e.key === "Control") {
this.isMetaKeyHeld = false;
}
};
// Mouse handler is needed because the key handler will not fire if the app is out of focus
this.mouseDownHandler = (e) => {
if (e.metaKey || e.ctrlKey) {
this.isMetaKeyHeld = true;
} else {
this.isMetaKeyHeld = false;
}
};
}
async onload() {
console.log("loading " + this.manifest.name + " plugin");
await this.loadSettings();
this.addSettingTab(new OpenerSettingTab(this.app, this));
this.updateMetaKeyListeners();
this.monkeyPatchOpenFile();
this.addCommands();
this.addMenuItem();
}
onunload() {
this.uninstallMonkeyPatchOpenFile && this.uninstallMonkeyPatchOpenFile();
this.removeMetaKeyListeners();
console.log("unloading " + this.manifest.name + " plugin");
}
async loadSettings() {
const data = await this.loadData();
this.settings = Object.assign({}, DEFAULT_SETTINGS, data);
}
async saveSettings() {
await this.saveData(this.settings);
this.updateMetaKeyListeners();
}
addCommands() {
this.addCommand({
id: "same-tab-once",
name: "Open next file in same tab (Obsidian default behavior)",
checkCallback: (checking) => {
if (checking) {
return this.settings.newTab;
}
this.sameTabOnce = true;
new import_obsidian2.Notice("Next file will open in same tab");
}
});
this.addCommand({
id: "enable-new-tab",
name: "Enable new tab for all files",
checkCallback: (checking) => {
if (checking) {
return !this.settings.newTab;
}
this.settings.newTab = true;
this.saveSettings();
new import_obsidian2.Notice("Opener: New tab for all files enabled");
}
});
this.addCommand({
id: "disable-new-tab",
name: "Disable new tab for all files",
checkCallback: (checking) => {
if (checking) {
return this.settings.newTab;
}
this.settings.newTab = false;
this.saveSettings();
new import_obsidian2.Notice("Opener: New tab for all files disabled");
}
});
this.addCommand({
id: "enable-pdf",
name: "Enable open all PDFs with default app",
checkCallback: (checking) => {
if (checking) {
return !this.settings.PDFApp;
}
this.settings.PDFApp = true;
this.saveSettings();
new import_obsidian2.Notice("Opener: Open all PDFs with default app enabled");
}
});
this.addCommand({
id: "disable-pdf",
name: "Disable open all PDFs with default app",
checkCallback: (checking) => {
if (checking) {
return this.settings.PDFApp;
}
this.settings.PDFApp = false;
this.saveSettings();
new import_obsidian2.Notice("Opener: Open all PDFs with default app disabled");
}
});
this.addCommand({
id: "open-graph-view-in-new-tab",
name: "Open Graph View in new tab",
callback: () => {
this.app.commands.executeCommandById("workspace:new-tab");
this.app.commands.executeCommandById("graph:open");
}
});
}
// add command to right-click menu
addMenuItem() {
this.registerEvent(
this.app.workspace.on("file-menu", (menu, file, source, leaf) => {
if (file instanceof import_obsidian2.TFile) {
menu.addItem((item) => {
item.setSection("open");
item.setTitle("Open in same tab").onClick(() => {
this.sameTabOnce = true;
this.app.workspace.getLeaf().openFile(file);
});
});
}
})
);
}
addMetaKeyListeners() {
if (this.isMetaKeyHeld !== null)
return;
this.isMetaKeyHeld = false;
document.addEventListener("keydown", this.keyDownHandler);
document.addEventListener("keyup", this.keyUpHandler);
document.addEventListener("mousedown", this.mouseDownHandler, { capture: true });
}
removeMetaKeyListeners() {
if (this.isMetaKeyHeld === null)
return;
document.removeEventListener("keydown", this.keyDownHandler);
document.removeEventListener("keyup", this.keyUpHandler);
document.removeEventListener("mousedown", this.mouseDownHandler, { capture: true });
this.isMetaKeyHeld = null;
}
updateMetaKeyListeners() {
if (this.settings.extOnlyWhenMetaKey) {
this.addMetaKeyListeners();
} else {
this.removeMetaKeyListeners();
}
}
monkeyPatchOpenFile() {
const parentThis = this;
this.uninstallMonkeyPatchOpenFile = around(import_obsidian2.WorkspaceLeaf.prototype, {
openFile(oldOpenFile) {
return async function(file, openState) {
var _a, _b, _c, _d, _e, _f, _g, _h;
const defaultBehavior = () => {
return oldOpenFile.apply(this, [file, openState]);
};
const preparedEmptyLeave = ((_a = this.getViewState()) == null ? void 0 : _a.type) == "empty";
if (((_b = openState == null ? void 0 : openState.state) == null ? void 0 : _b.mode) && preparedEmptyLeave) {
return defaultBehavior();
}
if (file.path == ((_c = app.workspace.getActiveFile()) == null ? void 0 : _c.path) && ((_d = openState == null ? void 0 : openState.eState) == null ? void 0 : _d.subpath)) {
return defaultBehavior();
}
if (parentThis.sameTabOnce) {
parentThis.sameTabOnce = false;
return defaultBehavior();
}
const ALLEXT = ["png", "webp", "jpg", "jpeg", "gif", "bmp", "svg", "mp3", "webm", "wav", "m4a", "ogg", "3gp", "flac", "mp4", "ogv", "mov", "mkv"];
const OBSID_OPENABLE = ALLEXT.concat(["md", "canvas", "pdf"]);
if (parentThis.settings.PDFApp && file.extension == "pdf" || parentThis.settings.allExt && ALLEXT.includes(file.extension) || parentThis.settings.custExt && parentThis.settings.custExtList.includes(file.extension)) {
if (!parentThis.settings.extOnlyWhenMetaKey || parentThis.isMetaKeyHeld) {
new import_obsidian2.Notice("Opening external file with default app (Opener Plugin)");
if (preparedEmptyLeave) {
this.detach();
}
parentThis.app.openWithDefaultApp(file.path);
return;
} else {
new import_obsidian2.Notice("Opener Tip: Hold Cmd/Ctrl key to open with default app");
}
}
if (!parentThis.settings.newTab) {
return defaultBehavior();
}
if (this.group) {
new import_obsidian2.Notice("Opener: This is a Linked Tab! Opening in same tab therefore.");
return defaultBehavior();
}
const matchingLeaves = [];
const pushLeaveIfMatching = (leaf) => {
var _a2;
if (((_a2 = leaf.getViewState().state) == null ? void 0 : _a2.file) == file.path) {
matchingLeaves.push(leaf);
}
};
app.workspace.iterateRootLeaves(pushLeaveIfMatching);
(_g = (_f = (_e = app.workspace.getLayout()) == null ? void 0 : _e.floating) == null ? void 0 : _f.children) == null ? void 0 : _g.forEach((win) => {
var _a2;
if ((win == null ? void 0 : win.type) !== "window")
return console.log("Opener-Plugin: Strange floating object found (no window)", win);
(_a2 = win.children) == null ? void 0 : _a2.forEach((tabs) => {
var _a3;
if ((tabs == null ? void 0 : tabs.type) !== "tabs")
return console.log("Opener-Plugin: Strange floating object found (no tabs)", tabs);
(_a3 = tabs.children) == null ? void 0 : _a3.forEach((leaf) => {
if ((leaf == null ? void 0 : leaf.type) !== "leaf")
return console.log("Opener-Plugin: Strange floating object found (no leaf)", leaf);
pushLeaveIfMatching(app.workspace.getLeafById(leaf.id));
});
});
});
if (matchingLeaves.length) {
if (preparedEmptyLeave) {
new import_obsidian2.Notice(`File is now open in ${matchingLeaves.length + 1} Tabs`);
return defaultBehavior();
} else {
return oldOpenFile.apply(matchingLeaves[0], [file, openState]);
}
}
if (preparedEmptyLeave) {
return defaultBehavior();
}
if (!((_h = parentThis.app.viewRegistry) == null ? void 0 : _h.getTypeByExtension(file.extension))) {
return defaultBehavior();
}
return oldOpenFile.apply(app.workspace.getLeaf("tab"), [
file,
openState
]);
};
}
});
}
};

View File

@@ -1 +0,0 @@
{"id":"obsidian-opener","name":"Opener","minAppVersion":"0.15.9","description":"Open links in new/existing tabs by default. Open PDFs in System App by default. Can open other file formats in System Apps if desired.","author":"Aidan Gibson","authorUrl":"https://github.com/aidan-gibson","isDesktopOnly":false,"version":"2.1.2"}

View File

@@ -1,16 +0,0 @@
{
"pluginList": [
"aidan-gibson/obsidian-opener"
],
"pluginSubListFrozenVersion": [],
"themesList": [],
"updateAtStartup": true,
"updateThemesAtStartup": true,
"enableAfterInstall": true,
"loggingEnabled": false,
"loggingPath": "BRAT-log",
"loggingVerboseEnabled": false,
"debuggingMode": false,
"notificationsEnabled": true,
"personalAccessToken": ""
}

File diff suppressed because one or more lines are too long

View File

@@ -1,14 +0,0 @@
{
"id": "obsidian42-brat",
"name": "BRAT",
"version": "1.1.7",
"minAppVersion": "1.7.2",
"description": "Easily install a beta version of a plugin for testing.",
"author": "TfTHacker",
"authorUrl": "https://github.com/TfTHacker/obsidian42-brat",
"helpUrl": "https://tfthacker.com/BRAT",
"isDesktopOnly": false,
"fundingUrl": {
"Visit my site": "https://tfthacker.com"
}
}

View File

@@ -1,105 +0,0 @@
.brat-modal .modal-button-container {
margin-top: 5px !important;
}
.brat-modal .disabled-setting {
opacity: 0.5;
}
.brat-modal .disabled-setting:hover {
cursor: not-allowed;
}
/* Input validation styles */
.brat-settings .valid-input,
.brat-modal .valid-repository {
border-color: var(--color-green) !important;
}
.brat-settings .invalid-input,
.brat-modal .invalid-repository {
border-color: var(--color-red) !important;
}
.brat-settings .validation-error,
.brat-modal .validation-error {
border-color: var(--color-orange) !important;
}
/* Version selector */
.brat-version-selector {
width: 100%;
max-width: 400px;
justify-content: left;
}
.brat-token-input {
min-width: 33%;
}
/* Token info container styles */
.brat-token-info {
margin-top: 8px;
font-size: 0.8em;
padding: 8px;
border-radius: 4px;
background-color: var(--background-secondary);
}
/* Token status indicators */
.brat-token-info.valid,
.brat-token-status.valid {
color: var(--color-green);
}
.brat-token-info.invalid,
.brat-token-status.invalid {
color: var(--color-red);
}
.brat-token-info.valid {
border-left: 3px solid var(--color-green);
}
.brat-token-info.invalid {
border-left: 3px solid var(--color-red);
}
/* Token details and status */
.brat-token-status {
margin-bottom: 4px;
}
.brat-token-details {
margin-top: 4px;
color: var(--text-muted);
}
/* Token warnings */
.brat-token-warning {
color: var(--color-orange);
margin-top: 4px;
}
/* Token additional info */
.brat-token-scopes,
.brat-token-rate {
color: var(--text-muted);
margin-top: 2px;
}
/* Flex break utility */
.brat-modal .break {
flex-basis: 100%;
height: 0;
}
/* Validation status */
.brat-modal .validation-status-error {
color: var(--text-error);
}
.brat-modal .validation-status {
margin-top: 0.5em;
margin-bottom: 0.5em;
font-size: 0.8em;
text-align: left;
}

View File

@@ -1,3 +1,3 @@
.cm-s-obsidian span.cm-formatting-highlight, .cm-s-obsidian span.cm-highlight, .markdown-rendered mark { .cm-s-obsidian span.cm-formatting-highlight, .cm-s-obsidian span.cm-highlight, .markdown-rendered mark {
--text-highlight-bg: #e6cee7; --text-highlight-bg: #e6cee7;
} }

View File

@@ -1,3 +1,3 @@
.cm-s-obsidian .cm-line.HyperMD-header { .cm-s-obsidian .cm-line.HyperMD-header {
padding-top: 0; padding-top: 0;
} }

View File

@@ -1,55 +1,55 @@
.usage { .usage {
display:flex; display:flex;
flex-direction: row; flex-direction: row;
align-items: center; align-items: center;
} }
.usage p { .usage p {
margin:0; margin:0;
} }
.usage .box { .usage .box {
border: 1px solid black; border: 1px solid black;
border-radius: 0.5rem; border-radius: 0.5rem;
padding: 0.2rem 0.3rem 0.2rem 0.3rem; padding: 0.2rem 0.3rem 0.2rem 0.3rem;
display: inline-block; display: inline-block;
width: fit-content; width: fit-content;
margin: 0.2rem; margin: 0.2rem;
} }
.usage .left { .usage .left {
padding-right: 1.7rem; padding-right: 1.7rem;
background-image: linear-gradient(black, black), linear-gradient(black, black); background-image: linear-gradient(black, black), linear-gradient(black, black);
background-repeat: no-repeat; background-repeat: no-repeat;
background-size: 8px 2px; background-size: 8px 2px;
background-position: top right, bottom right; background-position: top right, bottom right;
border-right: solid black; border-right: solid black;
border-width: 0 2px; border-width: 0 2px;
} }
.usage .right { .usage .right {
padding-left: 1rem; padding-left: 1rem;
} }
.usage .r { .usage .r {
margin-left: 0.25rem; margin-left: 0.25rem;
margin-right: 0.25rem; margin-right: 0.25rem;
} }
.usage .ileft { .usage .ileft {
padding-left: 1.7rem; padding-left: 1.7rem;
background-image: linear-gradient(black, black), linear-gradient(black, black); background-image: linear-gradient(black, black), linear-gradient(black, black);
background-repeat: no-repeat; background-repeat: no-repeat;
background-size: 8px 2px; background-size: 8px 2px;
background-position: top left, bottom left; background-position: top left, bottom left;
border-left: solid black; border-left: solid black;
border-width: 0 2px; border-width: 0 2px;
} }
.usage .iright { .usage .iright {
padding-right: 1rem; padding-right: 1rem;
} }

View File

@@ -79,7 +79,7 @@ Means "glad that".
## ているところ ## ているところ
Means "in the process/middle of doing". Can either talk about the exact moment or in general. Means "in the process/middle of doing". Can either talk about the exact moment or in general.
See also [[🔰 Grammar/Time#たところ]]. See also [[Time - recently#たところ]].
> [!info] Example > [!info] Example
> {現在|げんざい}、{求職|きゅうしょく}し==ているところ==です。 > {現在|げんざい}、{求職|きゅうしょく}し==ているところ==です。

View File

@@ -1,3 +1,8 @@
---
title: Japanese Grammar
---
# Japanese Grammar # Japanese Grammar
Welcome to my Japanese Grammar project! Welcome to my Japanese Grammar project!
@@ -13,10 +18,10 @@ Of course, since I'm _learning_ the language, I need to get inspired from differ
* [Bunpro](https://bunpro.jp/grammar_points) * [Bunpro](https://bunpro.jp/grammar_points)
* [JLPT Sensei](https://jlptsensei.com/#jlpt-grammar-lists) * [JLPT Sensei](https://jlptsensei.com/#jlpt-grammar-lists)
* [Maggie Sensei](https://maggiesensei.com/) * [Maggie Sensei](https://maggiesensei.com/)
* [Try! Series of books](https://ask-books.com/tag/try/) * [Try! Series of books](https://ask-books.com/jlpt-try-prep/)
* [A Handbook of Japanese Grammar](https://www.9640.jp/nihongo/en/detail/?678) * [A Handbook of Japanese Grammar](https://www.9640.jp/nihongo/en/detail/?678)
* [Hedgehog Japanese](https://hedgehog-japanese.com/category/grammar/) * [Hedgehog Japanese](https://hedgehog-japanese.com/category/grammar/)
* [Wasabi](https://www.wasabi-jpn.com/category/japanese-grammar/) * [Wasabi](https://wasabi-jpn.com/magazine/japanese-grammar/wasabis-online-japanese-grammar-reference/?lang=en)
* [Japanese StackExchange](https://japanese.stackexchange.com/) * [Japanese StackExchange](https://japanese.stackexchange.com/)
* [Tofugu](https://www.tofugu.com) * [Tofugu](https://www.tofugu.com)
* [Imabi](https://imabi.org/table-of-contents-%e7%9b%ae%e6%ac%a1/) * [Imabi](https://imabi.org/table-of-contents-%e7%9b%ae%e6%ac%a1/)

View File

@@ -21,7 +21,7 @@ It is more objective than から: it expresses a situation that exists, and that
## から ## から
See [[🔰 Particles (2)#から#Because]]. See [[🔰 Particles (2)#Because]].
It is more subjective than ので: it expresses more personal needs/actions/opinions. It is more subjective than ので: it expresses more personal needs/actions/opinions.
## ことから ## ことから