Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 34 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
name: Release Obsidian plugin

on:
push:
tags:
- "*"

jobs:
build:
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v3

- name: Use Node.js
uses: actions/setup-node@v3
with:
node-version: "18.x"

- name: Build plugin
run: |
npm install
npm run build

- name: Create release
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
tag="${GITHUB_REF#refs/tags/}"

gh release create "$tag" \
--title="$tag" \
--draft \
main.js manifest.json styles.css
98 changes: 98 additions & 0 deletions code-parser.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
import { EmbedCodeFileSettings } from "./settings";

export interface CodeParser {
parseCode: (code: string) => string | Error;
getOutputLanguage: () => string;
}

//Factory method for future complex code types
export function createCodeParser(inputLanguage: string, settings: EmbedCodeFileSettings): CodeParser {
switch (inputLanguage) {
case "ipynb":
return new IpynbParser(settings.displayIpynbAsPython, settings.showIpynbCellNumbers);
break;
default:
return new DefaultParser(inputLanguage);
}
}

export class IpynbParser implements CodeParser {
private enabled: boolean;
private cellNumbers: boolean;

constructor(enabled: boolean, cellNumbers: boolean) {
this.enabled = enabled;
this.cellNumbers = cellNumbers;
}

parseCode(src: string): string | Error {
if (!this.enabled) {
return src;
}

let code = ""

let notebook;
try {
notebook = JSON.parse(src);
} catch (error) {
return new Error("Improperly formatted .ipynb file");
}

let codeBlocks: string[] = [];
if (Array.isArray(notebook.cells) && notebook.cells.length !== 0) {
notebook.cells.forEach((cell: any) => {
if (cell.cell_type === 'code' && Array.isArray(cell.source)) {
let codeBlock = cell.source.join('');
if (codeBlock.length > 0) {
codeBlocks.push(codeBlock);
}
}
});
} else {
return new Error("No cells found in the notebook");
}

if (codeBlocks.length === 0) {
return new Error("No code cells in the notebook");
}

codeBlocks.forEach((block: string, index: number) => {
if (codeBlocks.length != 1 && this.cellNumbers) {
code += `# Cell ${index + 1}:\n\n`;
}
code += block;
if (index !== codeBlocks.length - 1) {
code += "\n";
if (this.cellNumbers) {
code += "\n";
}
}
});

return code
}

getOutputLanguage(): string {
if (!this.enabled) {
return 'ipynb'
}
return 'python'
}
}

export class DefaultParser implements CodeParser {
private inputLanguage: string;

constructor(inputLanguage: string) {
this.inputLanguage = inputLanguage;
}

parseCode(src: string): string {
return src;
}

getOutputLanguage(): string {
return this.inputLanguage;
}
}
17 changes: 14 additions & 3 deletions main.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { Plugin, MarkdownRenderer, TFile, MarkdownPostProcessorContext, MarkdownView, parseYaml, requestUrl} from 'obsidian';
import { EmbedCodeFileSettings, EmbedCodeFileSettingTab, DEFAULT_SETTINGS} from "./settings";
import { analyseSrcLines, extractSrcLines} from "./utils";
import { createCodeParser, CodeParser } from "./code-parser";

export default class EmbedCodeFile extends Plugin {
settings: EmbedCodeFileSettings;
Expand Down Expand Up @@ -34,6 +35,7 @@ export default class EmbedCodeFile extends Plugin {
this.registerMarkdownCodeBlockProcessor(`embed-${lang}`, async (meta, el, ctx) => {
let fullSrc = ""
let src = ""
let codeParser: CodeParser = createCodeParser(lang, this.settings)

let metaYaml: any
try {
Expand Down Expand Up @@ -81,18 +83,27 @@ export default class EmbedCodeFile extends Plugin {
srcLinesNum = analyseSrcLines(srcLinesNumString)
}


let parsedSrc: any = codeParser.parseCode(fullSrc)
if (parsedSrc instanceof Error) {
const errMsg = `\`ERROR: ${parsedSrc.message}\``
await MarkdownRenderer.renderMarkdown(errMsg, el, '', this)
return
}

if (srcLinesNum.length == 0) {
src = fullSrc
src = parsedSrc
} else {
src = extractSrcLines(fullSrc, srcLinesNum)
src = extractSrcLines(parsedSrc, srcLinesNum)
}

let title = metaYaml.TITLE
if (!title) {
title = srcPath
}

await MarkdownRenderer.renderMarkdown('```' + lang + '\n' + src + '\n```', el, '', this)
let srcBlock = '```' + codeParser.getOutputLanguage() + '\n' + src + '\n```'
await MarkdownRenderer.renderMarkdown(srcBlock, el, '', this)
this.addTitleLivePreview(el, title);
});
}
Expand Down
31 changes: 28 additions & 3 deletions settings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,16 @@ export interface EmbedCodeFileSettings {
includedLanguages: string;
titleBackgroundColor: string;
titleFontColor: string;
displayIpynbAsPython: boolean;
showIpynbCellNumbers: boolean;
}

export const DEFAULT_SETTINGS: EmbedCodeFileSettings = {
includedLanguages: 'c,cs,cpp,java,python,go,ruby,javascript,js,typescript,ts,shell,sh,bash',
includedLanguages: 'c,cs,cpp,java,python,go,ruby,javascript,js,typescript,ts,shell,sh,bash,ipynb',
titleBackgroundColor: "#00000020",
titleFontColor: ""
titleFontColor: "",
displayIpynbAsPython: true,
showIpynbCellNumbers: true,
}

export class EmbedCodeFileSettingTab extends PluginSettingTab {
Expand Down Expand Up @@ -48,7 +52,7 @@ export class EmbedCodeFileSettingTab extends PluginSettingTab {
this.plugin.settings.titleFontColor = value;
await this.plugin.saveSettings();
}));

new Setting(containerEl)
.setName('Background color of title')
.addText(text => text
Expand All @@ -58,5 +62,26 @@ export class EmbedCodeFileSettingTab extends PluginSettingTab {
this.plugin.settings.titleBackgroundColor = value;
await this.plugin.saveSettings();
}));

new Setting(containerEl)
.setName('Display Jupyter Notebooks as python')
.setDesc('Parse .ipynb files to extract and display their python source code.')
.addToggle(toggle => toggle
.setValue(this.plugin.settings.displayIpynbAsPython)
.onChange(async (value) => {
this.plugin.settings.displayIpynbAsPython = value;
await this.plugin.saveSettings();
}));

new Setting(containerEl)
.setName('Jupyter Notebook Cell Numbers')
.setDesc('Show Jupyter Notebook cell numbers in the embedded python code.')
.addToggle(toggle => toggle
.setValue(this.plugin.settings.showIpynbCellNumbers)
.onChange(async (value) => {
this.plugin.settings.showIpynbCellNumbers = value;
await this.plugin.saveSettings();
}));

}
}