Skip to content

Commit 2b895e0

Browse files
committed
Extract the process into a single source file.
1 parent 162b2d4 commit 2b895e0

File tree

3 files changed

+195
-180
lines changed

3 files changed

+195
-180
lines changed

rollup.config.js

+5-5
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,18 @@
11
import typescript from '@rollup/plugin-typescript';
2-
import {nodeResolve} from '@rollup/plugin-node-resolve';
2+
import { nodeResolve } from '@rollup/plugin-node-resolve';
33
import commonjs from '@rollup/plugin-commonjs';
44

55
const isProd = (process.env.BUILD === 'production');
66

7-
const banner =
8-
`/*
7+
const banner =
8+
`/*
99
THIS IS A GENERATED/BUNDLED FILE BY ROLLUP
1010
if you want to view the source visit the plugins github repository
1111
*/
1212
`;
1313

1414
export default {
15-
input: 'main.ts',
15+
input: 'src/main.ts',
1616
output: {
1717
dir: '.',
1818
sourcemap: 'inline',
@@ -24,7 +24,7 @@ export default {
2424
external: ['obsidian'],
2525
plugins: [
2626
typescript(),
27-
nodeResolve({browser: true}),
27+
nodeResolve({ browser: true }),
2828
commonjs(),
2929
]
3030
};
+177-175
Original file line numberDiff line numberDiff line change
@@ -1,175 +1,177 @@
1-
import { Plugin } from 'obsidian';
2-
import { nanoid } from 'nanoid';
3-
4-
type GistJSON = {
5-
description: string,
6-
public: Boolean,
7-
created_at: string,
8-
files: [string],
9-
owner: string,
10-
div: string,
11-
stylesheet: string
12-
}
13-
14-
const pluginName = "obsidian-gist"
15-
const obsidianAppOrigin = 'app://obsidian.md'
16-
17-
export default class GistPlugin extends Plugin {
18-
async onload() {
19-
this._injectContainerHeightAdjustmentScript()
20-
21-
this.registerMarkdownCodeBlockProcessor("gist", async (sourceString: string, el, ctx) => {
22-
const gists = sourceString.trim().split("\n")
23-
24-
return Promise.all(
25-
gists.map(async (gist) => {
26-
return this._processGist(el, gist)
27-
})
28-
)
29-
});
30-
}
31-
32-
// private
33-
34-
async _processGist(el: HTMLElement, gistString: string) {
35-
const pattern = /(?<protocol>https?:\/\/)?(?<host>gist\.github\.com\/)?((?<username>\w+)\/)?(?<gistID>\w+)(\#(?<filename>.+))?/
36-
37-
const matchResult = gistString.match(pattern).groups
38-
39-
const gistID = matchResult.gistID
40-
41-
if (gistID === undefined) {
42-
return this._showError(el, gistString, `Could not found a valid Gist ID, please make sure your content and format is correct.`)
43-
}
44-
45-
let gistURL = `https://gist.github.com/${gistID}.json`
46-
47-
if (matchResult.filename !== undefined) {
48-
gistURL = `${gistURL}?file=${matchResult.filename}`
49-
}
50-
51-
try {
52-
const response = await fetch(gistURL)
53-
54-
if (response.ok) {
55-
const gistJSON = await response.json() as GistJSON
56-
return this._insertGistElement(el, gistID, gistJSON)
57-
} else {
58-
return this._showError(el, gistString, `Could not fetch the Gist info from GitHub server. (Code: ${response.status})`)
59-
}
60-
} catch (error) {
61-
return this._showError(el, gistString, `Could not fetch the Gist from GitHub server. (Error: ${error})`)
62-
}
63-
}
64-
65-
async _insertGistElement(el: HTMLElement, gistID: string, gistJSON: GistJSON) {
66-
// generate an uuid for each gist element
67-
const gistUUID = `${pluginName}-${gistID}-${nanoid()}`
68-
69-
// container
70-
const container = document.createElement('iframe');
71-
container.id = gistUUID
72-
container.classList.add(`${pluginName}-container`)
73-
container.setAttribute('sandbox', 'allow-scripts allow-top-navigation-by-user-activation')
74-
container.setAttribute('loading', 'lazy')
75-
76-
// reset the default things on HTML
77-
const resetStylesheet = `
78-
<style>
79-
html, body {
80-
margin: 0;
81-
padding: 0;
82-
height: 100%;
83-
}
84-
</style>
85-
`
86-
87-
// height adjustment script
88-
const heightAdjustmentScript = `
89-
<script>
90-
deliverHeightMessage = () => {
91-
const contentHeight = document.body.scrollHeight;
92-
93-
top.postMessage({
94-
sender: '${pluginName}',
95-
gistUUID: '${gistUUID}',
96-
contentHeight: contentHeight
97-
}, '${obsidianAppOrigin}');
98-
}
99-
100-
window.addEventListener('load', () => {
101-
deliverHeightMessage();
102-
})
103-
</script>
104-
`
105-
106-
// build stylesheet link
107-
const stylesheetLink = document.createElement('link');
108-
stylesheetLink.rel = "stylesheet";
109-
stylesheetLink.href = gistJSON.stylesheet
110-
111-
// hack to make links open in the parent
112-
const parentLinkHack = document.createElement('base')
113-
parentLinkHack.target = "_parent"
114-
115-
// Inject content into the iframe
116-
container.srcdoc = `
117-
<html>
118-
<head>
119-
<!-- hack -->
120-
${resetStylesheet}
121-
${parentLinkHack.outerHTML}
122-
${heightAdjustmentScript}
123-
124-
<!-- gist style -->
125-
${stylesheetLink.outerHTML}
126-
</head>
127-
128-
<body>
129-
${gistJSON.div}
130-
</body>
131-
</html>
132-
`
133-
134-
// insert container into the DOM
135-
el.appendChild(container)
136-
}
137-
138-
async _showError(el: HTMLElement, gistIDAndFilename: String, errorMessage: String = '') {
139-
const errorText = `
140-
Failed to load the Gist (${gistIDAndFilename}).
141-
142-
Error:
143-
144-
${errorMessage}
145-
`.trim()
146-
147-
el.createEl('pre', { text: errorText })
148-
}
149-
150-
_injectContainerHeightAdjustmentScript() {
151-
const containerHeightAdjustmentScript = document.createElement('script')
152-
containerHeightAdjustmentScript.id = `${pluginName}-container-height-adjustment`
153-
containerHeightAdjustmentScript.textContent = `
154-
window.addEventListener("message", (messageEvent) => {
155-
const sender = messageEvent.data.sender
156-
157-
if (messageEvent.origin !== 'null') {
158-
// a message received from the iFrame with \`srcdoc\` attribute, the \`origin\` will be \`null\`.
159-
return;
160-
}
161-
162-
// only process message coming from this plugin
163-
if (sender === '${pluginName}') {
164-
const gistUUID = messageEvent.data.gistUUID
165-
const contentHeight = messageEvent.data.contentHeight
166-
167-
const gistContainer = document.querySelector('iframe#' + gistUUID)
168-
gistContainer.height = contentHeight
169-
}
170-
}, false)
171-
`
172-
173-
document.head.appendChild(containerHeightAdjustmentScript)
174-
}
175-
}
1+
import { nanoid } from 'nanoid';
2+
3+
type GistJSON = {
4+
description: string,
5+
public: Boolean,
6+
created_at: string,
7+
files: [string],
8+
owner: string,
9+
div: string,
10+
stylesheet: string
11+
}
12+
13+
const pluginName = "obsidian-gist"
14+
const obsidianAppOrigin = 'app://obsidian.md'
15+
16+
class GistProcessor {
17+
constructor() {
18+
}
19+
20+
injectContainerHeightAdjustmentScript = () => {
21+
const containerHeightAdjustmentScript = document.createElement('script')
22+
containerHeightAdjustmentScript.id = `${pluginName}-container-height-adjustment`
23+
containerHeightAdjustmentScript.textContent = `
24+
window.addEventListener("message", (messageEvent) => {
25+
const sender = messageEvent.data.sender
26+
27+
if (messageEvent.origin !== 'null') {
28+
// a message received from the iFrame with \`srcdoc\` attribute, the \`origin\` will be \`null\`.
29+
return;
30+
}
31+
32+
// only process message coming from this plugin
33+
if (sender === '${pluginName}') {
34+
const gistUUID = messageEvent.data.gistUUID
35+
const contentHeight = messageEvent.data.contentHeight
36+
37+
const gistContainer = document.querySelector('iframe#' + gistUUID)
38+
gistContainer.height = contentHeight
39+
}
40+
}, false)
41+
`
42+
43+
document.head.appendChild(containerHeightAdjustmentScript)
44+
}
45+
46+
processor = async (sourceString: string, el: HTMLElement) => {
47+
const gists = sourceString.trim().split("\n")
48+
49+
return Promise.all(
50+
gists.map(async (gist) => {
51+
return this._processGist(el, gist)
52+
})
53+
)
54+
};
55+
56+
// private
57+
58+
async _processGist(el: HTMLElement, gistString: string) {
59+
const pattern = /(?<protocol>https?:\/\/)?(?<host>gist\.github\.com\/)?((?<username>\w+)\/)?(?<gistID>\w+)(\#(?<filename>.+))?/
60+
61+
const matchResult = gistString.match(pattern).groups
62+
63+
const gistID = matchResult.gistID
64+
65+
if (gistID === undefined) {
66+
return this._showError(el, gistString, `Could not found a valid Gist ID, please make sure your content and format is correct.`)
67+
}
68+
69+
let gistURL = `https://gist.github.com/${gistID}.json`
70+
71+
if (matchResult.filename !== undefined) {
72+
gistURL = `${gistURL}?file=${matchResult.filename}`
73+
}
74+
75+
try {
76+
const response = await fetch(gistURL)
77+
78+
if (response.ok) {
79+
const gistJSON = await response.json() as GistJSON
80+
return this._insertGistElement(el, gistID, gistJSON)
81+
} else {
82+
return this._showError(el, gistString, `Could not fetch the Gist info from GitHub server. (Code: ${response.status})`)
83+
}
84+
} catch (error) {
85+
return this._showError(el, gistString, `Could not fetch the Gist from GitHub server. (Error: ${error})`)
86+
}
87+
}
88+
89+
async _insertGistElement(el: HTMLElement, gistID: string, gistJSON: GistJSON) {
90+
// generate an uuid for each gist element
91+
const gistUUID = `${pluginName}-${gistID}-${nanoid()}`
92+
93+
// container
94+
const container = document.createElement('iframe');
95+
container.id = gistUUID
96+
container.classList.add(`${pluginName}-container`)
97+
container.setAttribute('sandbox', 'allow-scripts allow-top-navigation-by-user-activation')
98+
container.setAttribute('loading', 'lazy')
99+
100+
// reset the default things on HTML
101+
const resetStylesheet = `
102+
<style>
103+
html, body {
104+
margin: 0;
105+
padding: 0;
106+
height: 100%;
107+
}
108+
</style>
109+
`
110+
111+
// height adjustment script
112+
const heightAdjustmentScript = `
113+
<script>
114+
deliverHeightMessage = () => {
115+
const contentHeight = document.body.scrollHeight;
116+
117+
top.postMessage({
118+
sender: '${pluginName}',
119+
gistUUID: '${gistUUID}',
120+
contentHeight: contentHeight
121+
}, '${obsidianAppOrigin}');
122+
}
123+
124+
window.addEventListener('load', () => {
125+
deliverHeightMessage();
126+
})
127+
</script>
128+
`
129+
130+
// build stylesheet link
131+
const stylesheetLink = document.createElement('link');
132+
stylesheetLink.rel = "stylesheet";
133+
stylesheetLink.href = gistJSON.stylesheet
134+
135+
// hack to make links open in the parent
136+
const parentLinkHack = document.createElement('base')
137+
parentLinkHack.target = "_parent"
138+
139+
// Inject content into the iframe
140+
container.srcdoc = `
141+
<html>
142+
<head>
143+
<!-- hack -->
144+
${resetStylesheet}
145+
${parentLinkHack.outerHTML}
146+
${heightAdjustmentScript}
147+
148+
<!-- gist style -->
149+
${stylesheetLink.outerHTML}
150+
</head>
151+
152+
<body>
153+
${gistJSON.div}
154+
</body>
155+
</html>
156+
`
157+
158+
// insert container into the DOM
159+
el.appendChild(container)
160+
}
161+
162+
async _showError(el: HTMLElement, gistIDAndFilename: String, errorMessage: String = '') {
163+
const errorText = `
164+
Failed to load the Gist (${gistIDAndFilename}).
165+
166+
Error:
167+
168+
${errorMessage}
169+
`.trim()
170+
171+
el.createEl('pre', { text: errorText })
172+
}
173+
174+
175+
}
176+
177+
export { GistProcessor }

0 commit comments

Comments
 (0)