Skip to content

Commit

Permalink
Release Version 0.1.2
Browse files Browse the repository at this point in the history
  • Loading branch information
Elias Sundqvist committed Dec 2, 2021
1 parent 55c0b7b commit 8167c0c
Show file tree
Hide file tree
Showing 8 changed files with 98 additions and 57 deletions.
20 changes: 20 additions & 0 deletions README.md
Expand Up @@ -147,6 +147,26 @@ You can make a [pull request](https://github.com/elias-sundqvist/obsidian-react-

## Changelog

### 0.1.2 (2021-12-03) *Component Codeblocks + improved startup and stability*
* Components should no longer dissapear when navigating between views.
* Removed flickering of components at startup.
* It is now possible to write codeblocks like
* ````markdown
```jsx::ComponentName
someText
```
````
Which is equivalent to
````markdown
```jsx:
<ComponentName src={`someText`}/>
```
````
but less cluttered.

Example:
![Component Codeblock Example](https://user-images.githubusercontent.com/9102856/144520183-5dbdee07-76ae-49a6-aca6-732f53971a55.png)

### 0.1.1 (2021-08-29) *Improved component unmounting*

* Old components are now more reliably removed/disposed during rerenders.
Expand Down
4 changes: 2 additions & 2 deletions manifest.json
@@ -1,8 +1,8 @@
{
"id": "obsidian-react-components",
"name": "React Components",
"version": "0.1.1",
"minAppVersion": "0.9.12",
"version": "0.1.2",
"minAppVersion": "0.12.19",
"description": "This is a plugin for Obsidian. It allows you to write and use React components with Jsx inside your Obsidian notes.",
"author": "Elias Sundqvist",
"authorUrl": "https://github.com/elias-sundqvist",
Expand Down
4 changes: 2 additions & 2 deletions package.json
@@ -1,8 +1,8 @@
{
"name": "obsidian-react-components",
"version": "0.1.0",
"version": "0.1.2",
"description": "This is a plugin for Obsidian (https://obsidian.md). It allows you to write and use React components with Jsx inside your Obsidian notes.",
"main": "main.js",
"main": "src/main.js",
"scripts": {
"prettier-format": "prettier --config .prettierrc.js *.tsx --write",
"lint": "eslint . --ext .ts,.tsx",
Expand Down
2 changes: 1 addition & 1 deletion rollup.config.js
Expand Up @@ -21,7 +21,7 @@ const vault_plugin_dir = fs.existsSync('./.vault_plugin_dir') ?
'.';

export default {
input: 'main.tsx',
input: 'src/main.tsx',
output: {
dir: vault_plugin_dir,
sourcemap: 'inline',
Expand Down
78 changes: 27 additions & 51 deletions main.tsx → src/main.tsx
Expand Up @@ -4,8 +4,6 @@ import {
normalizePath,
Notice,
Plugin,
PluginSettingTab,
Setting,
TAbstractFile,
TFile,
TFolder,
Expand All @@ -17,6 +15,7 @@ import OfflineReactDOM from 'react-dom';
import Babel from '@babel/standalone';
import isVarName from 'is-var-name';
import reactToWebComponent from './react-webcomponent';
import { ReactComponentsSettingTab } from './settings';

type ReactComponentContextData = {
markdownPostProcessorContext: MarkdownPostProcessorContext;
Expand Down Expand Up @@ -49,6 +48,7 @@ export default class ReactComponentsPlugin extends Plugin {
ReactDOM: typeof OfflineReactDOM;
renderedHeaderMap: WeakMap<Element, MarkdownPostProcessorContext> = new WeakMap();
mountPoints: Set<Element> = new Set();
refreshTimeoutId?: NodeJS.Timeout;

noteHeaderComponent: (any) => JSX.Element = () => {
const React = this.React;
Expand Down Expand Up @@ -202,10 +202,10 @@ export default class ReactComponentsPlugin extends Plugin {

getPropertyValue(propertyName: string, file: TFile) {
const dataViewPropertyValue = (this.app as any)?.plugins?.plugins?.dataview?.api // eslint-disable-line
?.page(file.path)?.[propertyName];
?.page(file?.path)?.[propertyName];
if (dataViewPropertyValue) {
if (dataViewPropertyValue.path) {
return this.app.metadataCache.getFirstLinkpathDest(dataViewPropertyValue.path, file.path).path;
return this.app.metadataCache.getFirstLinkpathDest(dataViewPropertyValue?.path, file?.path)?.path;
}
const externalLinkMatch = /^\[.*\]\((.*)\)$/gm.exec(dataViewPropertyValue)?.[1];
if (externalLinkMatch) {
Expand Down Expand Up @@ -359,7 +359,7 @@ export default class ReactComponentsPlugin extends Plugin {
const newNoteHeaderComponent = namespaceObject[file.basename];
if (this.noteHeaderComponent != newNoteHeaderComponent && typeof newNoteHeaderComponent == 'function') {
this.noteHeaderComponent = newNoteHeaderComponent;
this.app.workspace.trigger('react-components:component-updated');
this.requestComponentUpdate();
}
}
}
Expand All @@ -373,7 +373,7 @@ export default class ReactComponentsPlugin extends Plugin {
codeBlocks.set(componentName, code);
await this.refreshComponentScope();
if (this.settings.auto_refresh && !suppressComponentRefresh) {
this.app.workspace.trigger('react-components:component-updated');
this.requestComponentUpdate();
}
}
try {
Expand Down Expand Up @@ -426,7 +426,7 @@ export default class ReactComponentsPlugin extends Plugin {
await this.registerComponents(file, true);
}
await this.refreshComponentScope();
this.app.workspace.trigger('react-components:component-updated');
this.requestComponentUpdate()
} catch (e) {}
}

Expand Down Expand Up @@ -513,9 +513,16 @@ export default class ReactComponentsPlugin extends Plugin {
name: 'Refresh React Components',
callback: async () => {
await this.loadComponents();
this.app.workspace.trigger('react-components:component-updated');
this.requestComponentUpdate();
}
});
this.addCommand({
id: 'cleanup-react-components',
name: 'Clean Up React Components',
callback: async () => {
this.cleanUpComponents();
}
})
this.registerEvent(this.app.vault.on('create', registerIfCodeBlockFile.bind(this)));
this.registerEvent(this.app.vault.on('modify', registerIfCodeBlockFile.bind(this)));
this.registerEvent(this.app.vault.on('rename', registerIfCodeBlockFile.bind(this)));
Expand All @@ -532,6 +539,14 @@ export default class ReactComponentsPlugin extends Plugin {
this.app.workspace.onLayoutReady(async () => this.refreshPanes());
}

async requestComponentUpdate() {
if(this.refreshTimeoutId !== null) {
clearTimeout(this.refreshTimeoutId);
}
// Only rerender after no new request has been made for 2 seconds.
this.refreshTimeoutId = setTimeout(()=>this.app.workspace.trigger('react-components:component-updated'), 2000);
}

registerHeaderProcessor() {
this.registerMarkdownPostProcessor(async (_, ctx) => {
if (!ctx.containerEl?.hasClass('markdown-preview-section')) {
Expand Down Expand Up @@ -573,14 +588,17 @@ export default class ReactComponentsPlugin extends Plugin {

registerCodeProcessor() {
this.registerMarkdownPostProcessor(async (el, ctx) => {
this.cleanUpComponents();
const codeblocks = el.querySelectorAll('code');
const toReplace = [];
for (let index = 0; index < codeblocks.length; index++) {
const codeblock = codeblocks.item(index);
if (codeblock.className == 'language-jsx:' || codeblock.className == 'language-jsx-') {
const source = codeblock.innerText;
toReplace.push({ codeblock: codeblock.parentNode, source });
} else if (codeblock.className.startsWith('language-jsx::')) {
const componentName = codeblock.className.substr('language-jsx::'.length).trim();
const source = `<${componentName} src={${JSON.stringify(codeblock.innerText)}}/>`;
toReplace.push({ codeblock: codeblock.parentNode, source });
} else {
const text = codeblock.innerText.trim();
if (text.startsWith('jsx-') || text.startsWith('jsx:')) {
Expand Down Expand Up @@ -638,45 +656,3 @@ export default class ReactComponentsPlugin extends Plugin {
return files;
}
}

class ReactComponentsSettingTab extends PluginSettingTab {
plugin: ReactComponentsPlugin;

constructor(plugin: ReactComponentsPlugin) {
super(plugin.app, plugin);
this.plugin = plugin;
}

display(): void {
const { containerEl } = this;

containerEl.empty();

containerEl.createEl('h2', { text: 'React Components Settings' });

new Setting(containerEl)
.setName('Components folder location')
.setDesc('Files in this folder will be available as components/functions.')
.addText(text => {
text.setPlaceholder('Example: folder 1/folder 2')
.setValue(this.plugin.settings.template_folder)
.onChange(new_folder => {
this.plugin.settings.template_folder = new_folder;
this.plugin.loadComponents();
this.plugin.saveSettings();
});
});

new Setting(containerEl)
.setName('Automatically Refresh Components')
.setDesc(
'Useful to disable if reloading components is costly (like if they perform api calls or read a lot of files). To refresh the components manually, run the `Refresh React Components` command'
)
.addToggle(toggle => {
toggle.setValue(this.plugin.settings.auto_refresh).onChange(auto_refresh => {
this.plugin.settings.auto_refresh = auto_refresh;
this.plugin.saveSettings();
});
});
}
}
File renamed without changes.
44 changes: 44 additions & 0 deletions src/settings.tsx
@@ -0,0 +1,44 @@
import { PluginSettingTab, Setting } from "obsidian";
import ReactComponentsPlugin from "./main";

export class ReactComponentsSettingTab extends PluginSettingTab {
plugin: ReactComponentsPlugin;

constructor(plugin: ReactComponentsPlugin) {
super(plugin.app, plugin);
this.plugin = plugin;
}

display(): void {
const { containerEl } = this;

containerEl.empty();

containerEl.createEl('h2', { text: 'React Components Settings' });

new Setting(containerEl)
.setName('Components folder location')
.setDesc('Files in this folder will be available as components/functions.')
.addText(text => {
text.setPlaceholder('Example: folder 1/folder 2')
.setValue(this.plugin.settings.template_folder)
.onChange(new_folder => {
this.plugin.settings.template_folder = new_folder;
this.plugin.loadComponents();
this.plugin.saveSettings();
});
});

new Setting(containerEl)
.setName('Automatically Refresh Components')
.setDesc(
'Useful to disable if reloading components is costly (like if they perform api calls or read a lot of files). To refresh the components manually, run the `Refresh React Components` command'
)
.addToggle(toggle => {
toggle.setValue(this.plugin.settings.auto_refresh).onChange(auto_refresh => {
this.plugin.settings.auto_refresh = auto_refresh;
this.plugin.saveSettings();
});
});
}
}
3 changes: 2 additions & 1 deletion versions.json
Expand Up @@ -9,5 +9,6 @@
"0.0.8": "0.9.12",
"0.0.9": "0.9.12",
"0.1.0": "0.9.12",
"0.1.1": "0.9.12"
"0.1.1": "0.9.12",
"0.1.2": "0.12.19"
}

0 comments on commit 8167c0c

Please sign in to comment.