This commit is contained in:
Heekang Park 2023-02-11 07:02:20 +09:00
parent b07a282205
commit 84d346d37d
16 changed files with 398 additions and 22 deletions

View file

@ -22,6 +22,30 @@ You can add title to the code block like this.
You must put the title in quotes. You can use both single and double quotes. You must put the title in quotes. You can use both single and double quotes.
### Collapse
You must use the title feature to use the collapse feature. You can collapse the code block like this.
```python title:"Title of the code block" collapse
print("Hello world")
```
Or like this.
```python title:"Title of the code block" collapse:true
print("Hello world")
```
![collapsible1](https://github.com/HeekangPark/obsidian-hk-code-block/raw/master/imgs/collapsible1.png)
![collapsible2](https://github.com/HeekangPark/obsidian-hk-code-block/raw/master/imgs/collapsible2.png)
If you want to explicitly expand the code block, you can do it like this.
```python title:"Title of the code block" collapse:false
print("Hello world")
```
### Line Numbers ### Line Numbers
You can add line numbers to the code block like this. You can add line numbers to the code block like this.
@ -238,6 +262,15 @@ You can change the default settings of each feature of HK Code Block in the sett
- default off, but on when specified : the title will only be shown if the title statement is specified - default off, but on when specified : the title will only be shown if the title statement is specified
- always off : the title will never be shown - always off : the title will never be shown
### Collapse
- Use Collapse
- always on : the code block will always be collapsible
- default on, but off when specified : the code block will always be collapsible, but will not be collapsed if collapse statement is specified as false
- default off, but on when specified : the code block will only be collapsible if the collapse statement is specified as true
- always off : the code block will never be collapsible
- Default Collapse State : the default collapse state of the code block
### Line numbers ### Line numbers
- Use Line Numbers - Use Line Numbers
@ -315,4 +348,9 @@ MIT License
### 0.1.0 ### 0.1.0
- Initial release - Initial release
### 0.2.0
- Add features
- Add collapse feature

View file

@ -22,6 +22,30 @@ HK CodeBlock을 이용하면 Code Block에 다양한 기능들을 추가할 수
반드시 따옴표 안에 제목을 넣어야 합니다. 큰따옴표와 작은 따옴표 모두 사용 가능합니다. 반드시 따옴표 안에 제목을 넣어야 합니다. 큰따옴표와 작은 따옴표 모두 사용 가능합니다.
### 접기
접기 기능을 사용하려면 반드시 제목을 설정해야 합니다. 다음과 같이 하고 제목을 클릭하면 Code Block을 접거나 펼 수 있습니다.
```python title:"Title of the code block" collapsible
print("Hello world")
```
또는 다음과 같이 할 수도 있습니다.
```python title:"Title of the code block" collapsible:true
print("Hello world")
```
![collapsible1](https://github.com/HeekangPark/obsidian-hk-code-block/raw/master/imgs/collapsible1.png)
![collapsible2](https://github.com/HeekangPark/obsidian-hk-code-block/raw/master/imgs/collapsible2.png)
다음과 같이 하면 명시적으로 접기 기능을 끌 수 있습니다.
```python title:"Title of the code block" collapsible:false
print("Hello world")
```
### 줄 번호 ### 줄 번호
다음과 같이 하면 Code Block에 줄 번호를 추가할 수 있습니다. 다음과 같이 하면 Code Block에 줄 번호를 추가할 수 있습니다.
@ -238,6 +262,15 @@ Result Code Block의 프롬프트는 설정에서 설정한 값(기본값: "Resu
- default off, but on when specified : 기본적으로 제목 기능을 사용하지 않습니다. 하지만 title 옵션을 명시하면 제목 기능을 사용합니다. - default off, but on when specified : 기본적으로 제목 기능을 사용하지 않습니다. 하지만 title 옵션을 명시하면 제목 기능을 사용합니다.
- always off : 제목 기능을 항상 사용하지 않습니다. - always off : 제목 기능을 항상 사용하지 않습니다.
### Collapse
- Use Collapse
- always on : 접기 기능을 항상 사용합니다.
- default on, but off when specified : 기본적으로 접기 기능을 사용합니다. 하지만 접기 기능을 사용하지 않는다고 명시하면 접기 기능을 사용하지 않습니다.
- default off, but on when specified : 기본적으로 접기 기능을 사용하지 않습니다. 하지만 접기 기능을 사용한다고 명시하면 접기 기능을 사용합니다.
- always off : 접기 기능을 항상 사용하지 않습니다.
- Default Collapse State : 접기 기능을 사용할 때, 기본적으로 접힌 상태로 보여줄지 펼쳐진 상태로 보여줄지를 설정합니다.
### Line numbers ### Line numbers
- Use Line Numbers - Use Line Numbers
@ -315,4 +348,9 @@ MIT License
### 0.1.0 ### 0.1.0
- 최초 배포 - 최초 배포
### 0.2.0
- 기능 추가
- 접기 기능 추가

83
dist/main.js vendored

File diff suppressed because one or more lines are too long

4
dist/manifest.json vendored
View file

@ -1,11 +1,11 @@
{ {
"id": "hk-code-block", "id": "hk-code-block",
"name": "HK Code Block", "name": "HK Code Block",
"version": "0.1.0", "version": "0.2.0",
"minAppVersion": "1.0.0", "minAppVersion": "1.0.0",
"description": "Obsidian plugin developed by Heekang Park; Make code block looking good on reading view", "description": "Obsidian plugin developed by Heekang Park; Make code block looking good on reading view",
"author": "Heekang Park", "author": "Heekang Park",
"authorUrl": "https://github.com/HeekangPark", "authorUrl": "https://github.com/HeekangPark",
"fundingUrl": "", "fundingUrl": "",
"isDesktopOnly": false "isDesktopOnly": false
} }

43
dist/styles.css vendored

File diff suppressed because one or more lines are too long

3
dist/versions.json vendored
View file

@ -1,3 +1,4 @@
{ {
"0.1.0": "0.15.0" "0.1.0": "1.0.0",
"0.2.0": "1.0.0"
} }

View file

@ -1,6 +1,7 @@
import esbuild from "esbuild"; import esbuild from "esbuild";
import process from "process"; import process from "process";
import builtins from "builtin-modules"; import builtins from "builtin-modules";
import { copyFile } from "fs/promises";
import { sassPlugin } from "esbuild-sass-plugin"; import { sassPlugin } from "esbuild-sass-plugin";
const banner = const banner =
@ -42,7 +43,18 @@ const context = await esbuild.context({
sourcemap: prod ? false : "inline", sourcemap: prod ? false : "inline",
treeShaking: true, treeShaking: true,
outdir: "./dist", outdir: "./dist",
plugins: [sassPlugin()] plugins: [
sassPlugin(),
{
name: "copy-build-files-to-root",
setup(build) {
build.onEnd(() => {
copyFile("./dist/main.js", "./main.js");
copyFile("./dist/styles.css", "./styles.css");
});
}
}
]
}); });
if (prod) { if (prod) {

BIN
imgs/collapsible1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.3 KiB

BIN
imgs/collapsible2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.3 KiB

View file

@ -1,7 +1,7 @@
{ {
"id": "hk-code-block", "id": "hk-code-block",
"name": "HK Code Block", "name": "HK Code Block",
"version": "0.1.0", "version": "0.2.0",
"minAppVersion": "1.0.0", "minAppVersion": "1.0.0",
"description": "Obsidian plugin developed by Heekang Park; Make code block looking good on reading view", "description": "Obsidian plugin developed by Heekang Park; Make code block looking good on reading view",
"author": "Heekang Park", "author": "Heekang Park",

View file

@ -1,8 +1,8 @@
{ {
"name": "obsidian-hk-code-block", "name": "obsidian-hk-code-block",
"version": "0.1.0", "version": "0.2.0",
"description": "Obsidian plugin developed by Heekang Park; Make code block looking good on reading view", "description": "Obsidian plugin developed by Heekang Park; Make code block looking good on reading view",
"main": "main.js", "main": "./dist/main.js",
"scripts": { "scripts": {
"dev": "node esbuild.config.mjs", "dev": "node esbuild.config.mjs",
"build": "tsc -noEmit -skipLibCheck && node esbuild.config.mjs production", "build": "tsc -noEmit -skipLibCheck && node esbuild.config.mjs production",

View file

@ -6,6 +6,8 @@ import type { HKCodeBlockSettings } from "./HKCodeBlockSettings";
const REGEX = { const REGEX = {
TITLE: /\stitle:(?:'(.*?)'|"(.*?)")\s/, TITLE: /\stitle:(?:'(.*?)'|"(.*?)")\s/,
COLLAPSIBLE_SIMPLE: /\scollapsible\s/,
COLLAPSIBLE_COMPLICATE: /\scollapsible:(true|false)\s/,
LINENOS_SIMPLE: /\slinenos\s/, LINENOS_SIMPLE: /\slinenos\s/,
LINENOS_COMPLICATE: /\slinenos:(true|false|(-{0,1}\d+))\s/, LINENOS_COMPLICATE: /\slinenos:(true|false|(-{0,1}\d+))\s/,
HIGHLIGHT: /\shighlight:(?:'(.*?)'|"(.*?)")\s/, HIGHLIGHT: /\shighlight:(?:'(.*?)'|"(.*?)")\s/,
@ -22,6 +24,7 @@ const REGEX = {
function getMeta(view: MarkdownView, elem_code: HTMLElement, section_code: MarkdownSectionInformation, settings: HKCodeBlockSettings): { function getMeta(view: MarkdownView, elem_code: HTMLElement, section_code: MarkdownSectionInformation, settings: HKCodeBlockSettings): {
showTitle: (boolean | undefined), showTitle: (boolean | undefined),
title: string, title: string,
isCollapsible: (boolean | undefined),
showLinenos: (boolean | undefined), showLinenos: (boolean | undefined),
linenosStart: number, linenosStart: number,
linenosNum: number, linenosNum: number,
@ -46,6 +49,20 @@ function getMeta(view: MarkdownView, elem_code: HTMLElement, section_code: Markd
title = regexResult_title[1] || regexResult_title[2]; title = regexResult_title[1] || regexResult_title[2];
} }
// collapsible
let isCollapsible: (boolean | undefined) = undefined;
const regexResult_collapsibleSimple = REGEX.COLLAPSIBLE_SIMPLE.exec(firstline);
const regexResult_collapsibleComplicate = REGEX.COLLAPSIBLE_COMPLICATE.exec(firstline);
if (regexResult_collapsibleSimple) {
isCollapsible = true;
} else if (regexResult_collapsibleComplicate) {
if (regexResult_collapsibleComplicate[1] === "true") {
isCollapsible = true;
} else if (regexResult_collapsibleComplicate[1] === "false") {
isCollapsible = false;
}
}
// linenos // linenos
let showLinenos: (boolean | undefined) = undefined; let showLinenos: (boolean | undefined) = undefined;
let linenosStart = settings.defaultLinenosStart; let linenosStart = settings.defaultLinenosStart;
@ -149,7 +166,7 @@ function getMeta(view: MarkdownView, elem_code: HTMLElement, section_code: Markd
const regexResultPrompt_result = REGEX.PROMPT_COMPLICATE.exec(firstline); const regexResultPrompt_result = REGEX.PROMPT_COMPLICATE.exec(firstline);
if (regexResult_result) { if (regexResult_result) {
isResult = true; isResult = true;
// override other meta data : only linenos, highlight are available // override other meta data : only linenos, highlight are available
showTitle = false; showTitle = false;
showLanguage = false; showLanguage = false;
@ -164,6 +181,7 @@ function getMeta(view: MarkdownView, elem_code: HTMLElement, section_code: Markd
return { return {
showTitle: showTitle, showTitle: showTitle,
title: title, title: title,
isCollapsible: isCollapsible,
showLinenos: showLinenos, showLinenos: showLinenos,
linenosStart: linenosStart, linenosStart: linenosStart,
linenosNum: linenosNum, linenosNum: linenosNum,
@ -205,9 +223,10 @@ export async function HKCodeBlockProcessor(
if (!section_code) return; if (!section_code) return;
// get metadata // get metadata
const { const {
showTitle, showTitle,
title, title,
isCollapsible,
showLinenos, showLinenos,
linenosStart, linenosStart,
linenosNum, linenosNum,
@ -223,7 +242,7 @@ export async function HKCodeBlockProcessor(
} = getMeta(view, elem_code, section_code, settings); } = getMeta(view, elem_code, section_code, settings);
if (settings.debugMode) { if (settings.debugMode) {
console.log({ console.log({
showTitle: showTitle, showTitle: showTitle,
title: title, title: title,
showLinenos: showLinenos, showLinenos: showLinenos,
@ -246,15 +265,60 @@ export async function HKCodeBlockProcessor(
elem_code.classList.add("hk-codeblock-code"); elem_code.classList.add("hk-codeblock-code");
elem_copyBtn.remove(); // remove the original copy button as default elem_copyBtn.remove(); // remove the original copy button as default
let elem_title: (HTMLElement | undefined) = undefined;
if (settings.useTitleGlobal === "default off, but on when specified" && (showTitle === true)) { if (settings.useTitleGlobal === "default off, but on when specified" && (showTitle === true)) {
elem_div.classList.add("hk-codeblock-show-title"); elem_div.classList.add("hk-codeblock-show-title");
const elem_title = document.createElement("div"); elem_title = document.createElement("div");
elem_title.classList.add("hk-codeblock-title"); elem_title.classList.add("hk-codeblock-title");
elem_title.innerHTML = title; elem_title.innerHTML = title;
elem_div.insertBefore(elem_title, elem_pre); elem_div.insertBefore(elem_title, elem_pre);
} }
if (
(settings.useCollapsibleGlobal === "always on") ||
(settings.useCollapsibleGlobal === "default on, but off when specified" && (isCollapsible === undefined || isCollapsible === true)) ||
(settings.useCollapsibleGlobal === "default off, but on when specified" && (isCollapsible === true))
) {
elem_div.classList.add("hk-codeblock-collapsible");
if (settings.defaultCollapse === "collapse") {
elem_div.classList.add("hk-codeblock-collapsed");
}
if (elem_title) {
elem_title.addEventListener("click", (ev) => {
ev.stopPropagation();
ev.preventDefault();
if (elem_div.classList.contains("hk-codeblock-collapsed")) {
elem_div.classList.remove("hk-codeblock-collapsed");
} else {
elem_div.classList.add("hk-codeblock-collapsed");
}
});
const elem_collapseBtns = document.createElement("div");
elem_collapseBtns.classList.add("hk-codeblock-collapse-btns");
const elem_collapseBtn = document.createElement("div");
elem_collapseBtn.classList.add("hk-codeblock-collapse-btn", "hk-codeblock-collapsed-btn");
elem_collapseBtn.innerHTML = `<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
<path d="M10 19a1 1 0 0 1-.64-.23 1 1 0 0 1-.13-1.41L13.71 12 9.39 6.63a1 1 0 0 1 .15-1.41 1 1 0 0 1 1.46.15l4.83 6a1 1 0 0 1 0 1.27l-5 6A1 1 0 0 1 10 19z"/>
</svg>`;
elem_collapseBtns.appendChild(elem_collapseBtn);
const elem_expandBtn = document.createElement("div");
elem_expandBtn.classList.add("hk-codeblock-collapse-btn", "hk-codeblock-expanded-btn");
elem_expandBtn.innerHTML = `<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
<path d="M12 16a1 1 0 0 1-.64-.23l-6-5a1 1 0 1 1 1.28-1.54L12 13.71l5.36-4.32a1 1 0 0 1 1.41.15 1 1 0 0 1-.14 1.46l-6 4.83A1 1 0 0 1 12 16z"/>
</svg>`;
elem_collapseBtns.appendChild(elem_expandBtn);
elem_title.prepend(elem_collapseBtns);
}
}
if ( if (
(settings.useLinenosGlobal === "always on") || (settings.useLinenosGlobal === "always on") ||
(settings.useLinenosGlobal === "default on, but off when specified" && (showLinenos === undefined || showLinenos === true)) || (settings.useLinenosGlobal === "default on, but off when specified" && (showLinenos === undefined || showLinenos === true)) ||
@ -334,7 +398,7 @@ export async function HKCodeBlockProcessor(
elem_pre.setAttribute("data-output", no_prompt_line_idxs.join(", ")); elem_pre.setAttribute("data-output", no_prompt_line_idxs.join(", "));
} }
if(settings.useResultGlobal === "enable" && (isResult === true)) { if (settings.useResultGlobal === "enable" && (isResult === true)) {
elem_div.classList.add("hk-codeblock-result"); elem_div.classList.add("hk-codeblock-result");
elem_code.classList.add("hk-codeblock-result-code"); elem_code.classList.add("hk-codeblock-result-code");

View file

@ -39,6 +39,44 @@ export class HKCodeBlockSettingTab extends PluginSettingTab {
}) })
); );
// collapse
containerEl.createEl('h2', { text: 'Collapse' });
new Setting(containerEl)
.setName('Use Collapse')
.setDesc(fragWithHTML(`- <b>always on</b> : the code block will always be collapsible
- <b>default on, but off when specified</b> : the code block will always be collapsible, but will not be collapsed if collapse statement is specified as false
- <b>default off, but on when specified</b> : the code block will only be collapsible if the collapse statement is specified as true
- <b>always off</b> : the code block will never be collapsible`))
.addDropdown(tc =>
tc.addOptions({
"always on": "always on",
"default on, but off when specified": "default on, but off when specified",
"default off, but on when specified": "default off, but on when specified",
"always off": "always off",
})
.setValue(this.plugin.settings.useCollapsibleGlobal)
.onChange(async (value: string) => {
this.plugin.settings.useCollapsibleGlobal = value as ("always on" | "default on, but off when specified" | "default off, but on when specified" | "always off");
await this.plugin.saveSettings();
})
);
new Setting(containerEl)
.setName('Default Collapse State')
.setDesc('The default collapse state of the code block.')
.addDropdown(tc =>
tc.addOptions({
"collapse": "collapse",
"expand": "expand",
})
.setValue(this.plugin.settings.defaultCollapse)
.onChange(async (value: string) => {
this.plugin.settings.defaultCollapse = value as ("collapse" | "expand");
await this.plugin.saveSettings();
})
);
// line numbers // line numbers
containerEl.createEl('h2', { text: 'Line Numbers' }); containerEl.createEl('h2', { text: 'Line Numbers' });
@ -181,8 +219,7 @@ export class HKCodeBlockSettingTab extends PluginSettingTab {
.setDesc(fragWithHTML(`- <b>always on</b> : prompt will always be shown .setDesc(fragWithHTML(`- <b>always on</b> : prompt will always be shown
- <b>default on, but off when specified</b> : prompt will always be shown, but will not be shown if the prompt statement is specified as false - <b>default on, but off when specified</b> : prompt will always be shown, but will not be shown if the prompt statement is specified as false
- <b>default off, but on when specified</b> : prompt will only be shown if the prompt statement is specified as true - <b>default off, but on when specified</b> : prompt will only be shown if the prompt statement is specified as true
- <b>always off</b> : prompt will never be shown - <b>always off</b> : prompt will never be shown`))
You can also specify the prompt by the statement like \`prompt:"My Prompt"\`. (default: "$")`))
.addDropdown(tc => .addDropdown(tc =>
tc.addOptions({ tc.addOptions({
"always on": "always on", "always on": "always on",

View file

@ -1,6 +1,10 @@
export interface HKCodeBlockSettings { export interface HKCodeBlockSettings {
useTitleGlobal: ("default off, but on when specified" | "always off"); useTitleGlobal: ("default off, but on when specified" | "always off");
useCollapsibleGlobal: ("always on" | "default on, but off when specified" | "default off, but on when specified" | "always off");
defaultCollapse: ("collapse" | "expand");
showCollapseBtn: boolean;
useLinenosGlobal: ("always on" | "default on, but off when specified" | "default off, but on when specified" | "always off"); useLinenosGlobal: ("always on" | "default on, but off when specified" | "default off, but on when specified" | "always off");
defaultLinenosStart: number; defaultLinenosStart: number;
showLinenosSplitter: boolean; showLinenosSplitter: boolean;
@ -26,6 +30,10 @@ export interface HKCodeBlockSettings {
export const DEFAULT_SETTINGS: HKCodeBlockSettings = { export const DEFAULT_SETTINGS: HKCodeBlockSettings = {
useTitleGlobal: "default off, but on when specified", useTitleGlobal: "default off, but on when specified",
useCollapsibleGlobal: "default on, but off when specified",
defaultCollapse: "expand",
showCollapseBtn: true,
useLinenosGlobal: "default off, but on when specified", useLinenosGlobal: "default off, but on when specified",
defaultLinenosStart: 1, defaultLinenosStart: 1,
showLinenosSplitter: true, showLinenosSplitter: true,

View file

@ -48,6 +48,10 @@
background-color: var(--hk-codeblock-background-color); background-color: var(--hk-codeblock-background-color);
border-bottom: 1px solid var(--hk-codeblock-border-color); border-bottom: 1px solid var(--hk-codeblock-border-color);
color: var(--hk-codeblock-title-text-color); color: var(--hk-codeblock-title-text-color);
display: flex;
flex-direction: row;
align-items: center;
} }
.hk-codeblock-title~pre { .hk-codeblock-title~pre {
@ -55,6 +59,63 @@
} }
} }
/* collapse */
.hk-codeblock.hk-codeblock-show-title.hk-codeblock-collapsible {
.hk-codeblock-title {
cursor: pointer;
position: relative;
.hk-codeblock-collapse-btns {
display: inline-flex;
align-items: center;
justify-content: center;
margin-right: 4px;
position: relative;
top: -1px;
.hk-codeblock-collapse-btn {
width: 16px;
height: 16px;
fill: var(--hk-codeblock-title-text-color);
stroke: var(--hk-codeblock-title-text-color);
stroke-width: 2;
opacity: 0.2;
&.hk-codeblock-collapsed-btn {
display: none;
}
&.hk-codeblock-expanded-btn {
display: inline-block;
}
}
}
}
&.hk-codeblock-collapsed {
.hk-codeblock-title {
border-bottom: none;
.hk-codeblock-collapse-btns {
.hk-codeblock-collapse-btn {
&.hk-codeblock-collapsed-btn {
display: inline-block;
}
&.hk-codeblock-expanded-btn {
display: none;
}
}
}
}
pre {
display: none;
}
}
}
/* linenos */ /* linenos */
.hk-codeblock.hk-codeblock-show-linenos { .hk-codeblock.hk-codeblock-show-linenos {
pre { pre {

View file

@ -1,3 +1,4 @@
{ {
"0.1.0": "0.15.0" "0.1.0": "1.0.0",
"0.2.0": "1.0.0"
} }