diff --git a/README.md b/README.md index e7f5a0f..5e04733 100644 --- a/README.md +++ b/README.md @@ -1,14 +1,17 @@ # obsidian-plotly Obsidian plugin, which allow user to embed Plotly charts into markdown notes. -## Usage -Use double-click to add basic plotly template: +# Usage +## Basic (using plotly block) +Use Command Palette (`Ctrl-P`) to add basic plotly template: ![Command example](./media/plotly-command-demo.gif) -## Examples -Plugin supports both JSON and YAML formats. -Those plots are identical: +This approach allows you to create JSON or YAML inside `plotly` block +with payload for data, layout and config objects. +It does NOT support JavaScript examples from plotly.com site - it only support static payload forvarding to `Plotly.newPlot` function. +For JavaScript support use Advanced approach with DataViewJS. +Basic example (those YAML and JSON result in identical plots): ```yaml ```plotly data: @@ -27,4 +30,53 @@ Those plots are identical: } ``` ``` + +## Advanced (using dataviewjs block) +Use Command Palette (`Ctrl-P`) to add plotly template: +![Command example](./media/plotly-dataviewjs-command-demo.gif) + +This approach DOES support any example from plotly.com. +(I haven't checked them all, feel free to create issue if some aren't working). +However, this approach require DataView plugin to process JavaScript. +As a benefit, you can create plots based on data from you notes which you retrieve via DataView API! +(By the way, this sounds similar to what [obsidian-tracker](https://github.com/pyrochlore/obsidian-tracker) plugin does). + +To use it, just add DataviewJS block with Plotly command, copy desired example and paste it. +NOTE: All examples use `Plotly.newPlot(component, data, layout, config)` to draw, and it takes some extra code to work in Obsidian. +There is a wrapper function available as `window.renderPlotly(this.component, data, layout, config)`, which will draw plot inside DataViewJS block. +(Wrapper parameters should be same as in example). + +A lot of examples are on [Plotly](https://plotly.com/javascript/) official site. + +![How to copy examples from plotly.com](./media/plotly-copy-from-examples-demo.gif) + +NOTE: Some examples also require d3 library. This is large library and rarely needed. That's why I do not want to have it in plugin. +If you need this library, there is a workaround: you can download d3 library from official [site](https://d3js.org/d3.v7.min.js) (Open link->Right click->Save as...), place it in your vault and import using `require`; + +```js + ```dataviewjs + //Some plotly examples require d3 library to work. + //Since it's large and used by few examples, + //I propose a workaround to import d3; + //You need to download dependency from https://d3js.org/d3.v7.min.js + //and place it in your vault. + let path = app.vault.adapter.basePath;//absolute path to your vault + var d3 = require(path+"\\utils\\d3.v7.min.js"); + + //Replace this block with any example from plotly.com + //NOTE: `Plotly.newPlot` won't work here, use `window.renderPlotly` instead + var data = [ + {x:[0,1,2,3,4,5,6,7,8,9],y:[4,4,2,2,3,3,2,2,4,4]}, + {x:[0,1,2,3,4,5,6,7,8,9],y:[3,3,1,1,2,2,1,1,3,3]} + ]; + var layout = {title:"Example in DataViewJS"}; + var config = {displaylogo:false}; + + window.renderPlotly(this.container, data, layout, config) + ``` +``` + +# Examples +TODO: create vault to test this plugin with examples. + More examples on [Plotly](https://plotly.com/javascript/) official site. diff --git a/media/plotly-copy-from-examples-demo.gif b/media/plotly-copy-from-examples-demo.gif new file mode 100644 index 0000000..624d7db Binary files /dev/null and b/media/plotly-copy-from-examples-demo.gif differ diff --git a/media/plotly-dataviewjs-command-demo.gif b/media/plotly-dataviewjs-command-demo.gif new file mode 100644 index 0000000..8678a67 Binary files /dev/null and b/media/plotly-dataviewjs-command-demo.gif differ diff --git a/src/main.ts b/src/main.ts index 2b0bcbb..6316279 100644 --- a/src/main.ts +++ b/src/main.ts @@ -1,6 +1,7 @@ -import { Editor, MarkdownView, Plugin } from 'obsidian'; +import * as Plotly from 'plotly.js-dist-min'; -import { preprocessor } from './preprocessor'; +import { Editor, MarkdownView, Plugin } from 'obsidian'; +import { preprocessor, renderPlotly } from './preprocessor'; const basicPlotlyChart = [ '```plotly', @@ -9,7 +10,6 @@ const basicPlotlyChart = [ '\t y: [0,1,0]', '```\n' ].join('\n') - const NEW_PLOTLY_CHART_NAME = "New Plotly Chart"; const newPlotlyChart = (editor: Editor)=>{ let doc = editor.getDoc(); @@ -17,10 +17,45 @@ const newPlotlyChart = (editor: Editor)=>{ doc.replaceRange(basicPlotlyChart, cursor); } +const dataviewjsPlotlyChart = [ + '```dataviewjs', + '//Some plotly examples require d3 library to work.', + '//Since it\'s large and used by few examples,', + '//I propose a workaround to import d3;', + '//You need to download dependency from https://d3js.org/d3.v7.min.js', + '//and place it in your vault.', + 'let path = app.vault.adapter.basePath;//absolute path to your vault', + 'var d3 = require(path+"\\\\utils\\\\d3.v7.min.js");', + '', + '//Replace this block with any example from plotly.com', + '//NOTE: `Plotly.newPlot` won\'t work here, use `window.renderPlotly` instead', + 'var data = [', + '{x:[0,1,2,3,4,5,6,7,8,9],y:[4,4,2,2,3,3,2,2,4,4]},', + '{x:[0,1,2,3,4,5,6,7,8,9],y:[3,3,1,1,2,2,1,1,3,3]}', + '];', + 'var layout = {};', + 'var config = {};', + '', + 'window.renderPlotly(this.container, data, layout, config)', + '```' +].join('\n') +const NEW_PLOTLY_CHART_BY_DATAVIEWJS_NAME = "New Plotly Chart generated by Dataviewjs"; +const newPlotlyChartByDataviewjs = (editor: Editor)=>{ + let doc = editor.getDoc(); + let cursor = doc.getCursor(); + doc.replaceRange(dataviewjsPlotlyChart, cursor); +} + + export default class PlotlyPlugin extends Plugin { + Plotly: object async onload() { + //@ts-ignore + window.renderPlotly = renderPlotly; + console.log('loading Plotly plugin'); + this.Plotly = Plotly; this.registerMarkdownCodeBlockProcessor('plotly', preprocessor); @@ -29,6 +64,12 @@ export default class PlotlyPlugin extends Plugin { name: NEW_PLOTLY_CHART_NAME, editorCallback: (editor: Editor, view: MarkdownView)=>newPlotlyChart(editor) }); + + this.addCommand({ + id: "add-plotly-dataviewjs-example", + name: NEW_PLOTLY_CHART_BY_DATAVIEWJS_NAME, + editorCallback: (editor: Editor, view: MarkdownView)=>newPlotlyChartByDataviewjs(editor) + }); } onunload() { diff --git a/src/preprocessor.ts b/src/preprocessor.ts index 3c89476..09f5386 100644 --- a/src/preprocessor.ts +++ b/src/preprocessor.ts @@ -6,18 +6,8 @@ export const preprocessor = (content: string, el: HTMLElement, ctx: MarkdownPost let json; try{ json = parseYaml(content); - validate(json, el) - - const destination = document.createElement('div'); - - if(el.firstElementChild!=null){ - Plotly.update(destination, json.data, json.layout, json.config); - el.replaceChild(destination, el.firstElementChild); - } else { - Plotly.newPlot(destination, json.data, json.layout, json.config); - el.appendChild(destination); - } + render(json, el) } catch (error) { let errorDiv = document.createElement('div'); errorDiv.textContent = "Couldn't render plot:" + error; @@ -38,3 +28,19 @@ const validate = (json: any, el: HTMLElement) => { } }) } + +const render = (json: any, el: HTMLElement) => { + renderPlotly(el, json.data, json.layout, json.config) +} + +export const renderPlotly = (el: HTMLElement, data: Object[], layout: Object, config: Object) => { + const destination = document.createElement('div'); + + if(el.firstElementChild!=null){ + Plotly.update(destination, data as any, layout, config as any); + el.replaceChild(destination, el.firstElementChild); + } else { + Plotly.newPlot(destination, data, layout, config); + el.appendChild(destination); + } +}