mirror of
https://github.com/laurent22/joplin.git
synced 2025-04-11 11:12:03 +02:00
Plugins: Add support for content script asset files, for Markdown-it plugins
This commit is contained in:
parent
5cafc8cea5
commit
3ed0083e94
@ -170,7 +170,9 @@ describe('services_PluginService', function() {
|
|||||||
const tempDir = await createTempDir();
|
const tempDir = await createTempDir();
|
||||||
|
|
||||||
const contentScriptPath = `${tempDir}/markdownItTestPlugin.js`;
|
const contentScriptPath = `${tempDir}/markdownItTestPlugin.js`;
|
||||||
|
const contentScriptCssPath = `${tempDir}/markdownItTestPlugin.css`;
|
||||||
await shim.fsDriver().copy(`${testPluginDir}/content_script/src/markdownItTestPlugin.js`, contentScriptPath);
|
await shim.fsDriver().copy(`${testPluginDir}/content_script/src/markdownItTestPlugin.js`, contentScriptPath);
|
||||||
|
await shim.fsDriver().copy(`${testPluginDir}/content_script/src/markdownItTestPlugin.css`, contentScriptCssPath);
|
||||||
|
|
||||||
const service = newPluginService();
|
const service = newPluginService();
|
||||||
|
|
||||||
@ -205,7 +207,7 @@ describe('services_PluginService', function() {
|
|||||||
|
|
||||||
const mdToHtml = new MdToHtml();
|
const mdToHtml = new MdToHtml();
|
||||||
const module = require(contentScript.path).default;
|
const module = require(contentScript.path).default;
|
||||||
mdToHtml.loadExtraRendererRule(contentScript.id, module({}));
|
mdToHtml.loadExtraRendererRule(contentScript.id, tempDir, module({}));
|
||||||
|
|
||||||
const result = await mdToHtml.render([
|
const result = await mdToHtml.render([
|
||||||
'```justtesting',
|
'```justtesting',
|
||||||
@ -213,6 +215,11 @@ describe('services_PluginService', function() {
|
|||||||
'```',
|
'```',
|
||||||
].join('\n'));
|
].join('\n'));
|
||||||
|
|
||||||
|
const asset = result.pluginAssets.find(a => a.name === 'justtesting/markdownItTestPlugin.css');
|
||||||
|
const assetContent: string = await shim.fsDriver().readFile(asset.path, 'utf8');
|
||||||
|
|
||||||
|
expect(assetContent.includes('.just-testing')).toBe(true);
|
||||||
|
expect(assetContent.includes('background-color: red;')).toBe(true);
|
||||||
expect(result.html.includes('JUST TESTING: something')).toBe(true);
|
expect(result.html.includes('JUST TESTING: something')).toBe(true);
|
||||||
|
|
||||||
await shim.fsDriver().remove(tempDir);
|
await shim.fsDriver().remove(tempDir);
|
||||||
|
@ -20,4 +20,4 @@
|
|||||||
"webpack": "^4.43.0",
|
"webpack": "^4.43.0",
|
||||||
"webpack-cli": "^3.3.11"
|
"webpack-cli": "^3.3.11"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,4 @@
|
|||||||
|
.just-testing {
|
||||||
|
background-color: red;
|
||||||
|
color: yellow;
|
||||||
|
}
|
@ -6,7 +6,7 @@ function plugin(markdownIt, _options) {
|
|||||||
markdownIt.renderer.rules.fence = function(tokens, idx, options, env, self) {
|
markdownIt.renderer.rules.fence = function(tokens, idx, options, env, self) {
|
||||||
const token = tokens[idx];
|
const token = tokens[idx];
|
||||||
if (token.info !== 'justtesting') return defaultRender(tokens, idx, options, env, self);
|
if (token.info !== 'justtesting') return defaultRender(tokens, idx, options, env, self);
|
||||||
return `JUST TESTING: ${token.content}`;
|
return `<div class="just-testing">JUST TESTING: ${token.content}</div>`;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -14,6 +14,11 @@ module.exports = {
|
|||||||
default: function(_context) {
|
default: function(_context) {
|
||||||
return {
|
return {
|
||||||
plugin: plugin,
|
plugin: plugin,
|
||||||
|
assets: function() {
|
||||||
|
return [
|
||||||
|
{ name: 'markdownItTestPlugin.css' }
|
||||||
|
];
|
||||||
|
},
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -9,6 +9,7 @@ interface RendererRule {
|
|||||||
install(context: any, ruleOptions: any): any;
|
install(context: any, ruleOptions: any): any;
|
||||||
assets?(theme: any): any;
|
assets?(theme: any): any;
|
||||||
plugin?: any;
|
plugin?: any;
|
||||||
|
assetPath?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface RendererRules {
|
interface RendererRules {
|
||||||
@ -197,7 +198,7 @@ export default class MdToHtml {
|
|||||||
|
|
||||||
if (options.extraRendererRules) {
|
if (options.extraRendererRules) {
|
||||||
for (const rule of options.extraRendererRules) {
|
for (const rule of options.extraRendererRules) {
|
||||||
this.loadExtraRendererRule(rule.id, rule.module);
|
this.loadExtraRendererRule(rule.id, rule.assetPath, rule.module);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -232,15 +233,28 @@ export default class MdToHtml {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// `module` is a file that has already been `required()`
|
// `module` is a file that has already been `required()`
|
||||||
public loadExtraRendererRule(id: string, module: any) {
|
public loadExtraRendererRule(id: string, assetPath: string, module: any) {
|
||||||
if (this.extraRendererRules_[id]) throw new Error(`A renderer rule with this ID has already been loaded: ${id}`);
|
if (this.extraRendererRules_[id]) throw new Error(`A renderer rule with this ID has already been loaded: ${id}`);
|
||||||
this.extraRendererRules_[id] = module;
|
this.extraRendererRules_[id] = {
|
||||||
|
...module,
|
||||||
|
assetPath,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private ruleByKey(key: string): RendererRule {
|
||||||
|
if (rules[key]) return rules[key];
|
||||||
|
if (this.extraRendererRules_[key]) return this.extraRendererRules_[key];
|
||||||
|
if (key === 'highlight.js') return null;
|
||||||
|
throw new Error(`No such rule: ${key}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
private processPluginAssets(pluginAssets: PluginAssets): RenderResult {
|
private processPluginAssets(pluginAssets: PluginAssets): RenderResult {
|
||||||
const files: RenderResultPluginAsset[] = [];
|
const files: RenderResultPluginAsset[] = [];
|
||||||
const cssStrings = [];
|
const cssStrings = [];
|
||||||
for (const pluginName in pluginAssets) {
|
for (const pluginName in pluginAssets) {
|
||||||
|
|
||||||
|
const rule = this.ruleByKey(pluginName);
|
||||||
|
|
||||||
for (const asset of pluginAssets[pluginName]) {
|
for (const asset of pluginAssets[pluginName]) {
|
||||||
let mime = asset.mime;
|
let mime = asset.mime;
|
||||||
|
|
||||||
@ -263,10 +277,18 @@ export default class MdToHtml {
|
|||||||
throw new Error(`Unsupported inline mime type: ${mime}`);
|
throw new Error(`Unsupported inline mime type: ${mime}`);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
// TODO: we should resolve the path using
|
||||||
|
// resolveRelativePathWithinDir() for increased
|
||||||
|
// security, but the shim is not accessible from the
|
||||||
|
// renderer, and React Native doesn't have this
|
||||||
|
// function, so for now use the provided path as-is.
|
||||||
|
|
||||||
const name = `${pluginName}/${asset.name}`;
|
const name = `${pluginName}/${asset.name}`;
|
||||||
|
const assetPath = rule?.assetPath ? `${rule.assetPath}/${asset.name}` : `pluginAssets/${name}`;
|
||||||
|
|
||||||
files.push(Object.assign({}, asset, {
|
files.push(Object.assign({}, asset, {
|
||||||
name: name,
|
name: name,
|
||||||
path: `pluginAssets/${name}`,
|
path: assetPath,
|
||||||
mime: mime,
|
mime: mime,
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
@ -282,7 +304,7 @@ export default class MdToHtml {
|
|||||||
|
|
||||||
// This return all the assets for all the plugins. Since it is called
|
// This return all the assets for all the plugins. Since it is called
|
||||||
// on each render, the result is cached.
|
// on each render, the result is cached.
|
||||||
private allProcessedAssets(theme: any, codeTheme: string) {
|
private allProcessedAssets(rules: RendererRules, theme: any, codeTheme: string) {
|
||||||
const cacheKey: string = theme.cacheKey + codeTheme;
|
const cacheKey: string = theme.cacheKey + codeTheme;
|
||||||
|
|
||||||
if (this.allProcessedAssets_[cacheKey]) return this.allProcessedAssets_[cacheKey];
|
if (this.allProcessedAssets_[cacheKey]) return this.allProcessedAssets_[cacheKey];
|
||||||
@ -501,7 +523,7 @@ export default class MdToHtml {
|
|||||||
|
|
||||||
let cssStrings = noteStyle(options.theme);
|
let cssStrings = noteStyle(options.theme);
|
||||||
|
|
||||||
let output = { ...this.allProcessedAssets(options.theme, options.codeTheme) };
|
let output = { ...this.allProcessedAssets(allRules, options.theme, options.codeTheme) };
|
||||||
cssStrings = cssStrings.concat(output.cssStrings);
|
cssStrings = cssStrings.concat(output.cssStrings);
|
||||||
|
|
||||||
if (options.userCss) cssStrings.push(options.userCss);
|
if (options.userCss) cssStrings.push(options.userCss);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user