Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/icewind1991/files_markdown.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/js
diff options
context:
space:
mode:
authorRobin Appelman <robin@icewind.nl>2017-08-29 12:49:34 +0300
committerRobin Appelman <robin@icewind.nl>2017-08-29 12:49:34 +0300
commitee7fd7148c9b0fb40e91640057dfe42238faf094 (patch)
tree05baa8875225ce0fb254cfe4220f198e411b9ecc /js
parent8322441915a9baa85d99b663714ba65ba414f782 (diff)
Make checkboxes clickable
Signed-off-by: Robin Appelman <robin@icewind.nl>
Diffstat (limited to 'js')
-rw-r--r--js/CheckboxPlugin.ts9
-rw-r--r--js/PreviewPlugin.ts23
-rw-r--r--js/Renderer.ts29
-rw-r--r--js/SidebarPreview.ts23
-rw-r--r--js/VideoPlugin.ts2
-rw-r--r--js/editor.ts2
6 files changed, 67 insertions, 21 deletions
diff --git a/js/CheckboxPlugin.ts b/js/CheckboxPlugin.ts
index 055ceeb..0bb6800 100644
--- a/js/CheckboxPlugin.ts
+++ b/js/CheckboxPlugin.ts
@@ -31,7 +31,7 @@ export function CheckBoxReplacer(md: MarkdownIt.MarkdownIt, userOptions: Partial
};
const options = $.extend(defaults, userOptions);
const pattern = /\[(X|\s|\_|\-)\]\s(.*)/i;
- const createTokens = function (checked: boolean, label: string, Token: TokenConstructor): Token[] {
+ const createTokens = function (checked: boolean, label: string, Token: TokenConstructor, line: number): Token[] {
const nodes: Token[] = [];
let token: Token;
@@ -60,6 +60,7 @@ export function CheckBoxReplacer(md: MarkdownIt.MarkdownIt, userOptions: Partial
if (options.checkboxClass) {
token.attrs.push(["class", options.checkboxClass]);
}
+ token.attrs.push(["data-line", String(line)]);
nodes.push(token);
/**
@@ -86,7 +87,7 @@ export function CheckBoxReplacer(md: MarkdownIt.MarkdownIt, userOptions: Partial
return nodes;
};
- const splitTextToken = function (original: Token, Token: TokenConstructor): Token[] {
+ const splitTextToken = function (original: Token, Token: TokenConstructor, line: number): Token[] {
const text = original.content;
const matches = text.match(pattern);
if (matches === null) {
@@ -95,14 +96,14 @@ export function CheckBoxReplacer(md: MarkdownIt.MarkdownIt, userOptions: Partial
const value = matches[1];
const label = matches[2];
const checked = (value === "X" || value === "x");
- return createTokens(checked, label, Token);
+ return createTokens(checked, label, Token, line);
};
return function (state: CheckboxReplacerState) {
for (const token of state.tokens) {
if (token.type === "inline") {
token.children = ([] as Token[]).concat.apply([],
- token.children.map(childToken => splitTextToken(childToken, state.Token))
+ token.children.map(childToken => splitTextToken(childToken, state.Token, token.map ? token.map[0] : 0))
);
}
}
diff --git a/js/PreviewPlugin.ts b/js/PreviewPlugin.ts
index 5323499..2a07095 100644
--- a/js/PreviewPlugin.ts
+++ b/js/PreviewPlugin.ts
@@ -3,10 +3,13 @@ import {UnderscoreStatic} from "underscore";
declare const _: UnderscoreStatic;
+declare const aceEditor: AceAjax.Editor;
+
type onPopstate = (this: Window, ev: PopStateEvent) => any;
export class PreviewPlugin {
private renderer: Renderer;
+ private Range: new (startRow: number, startColumn: number, endRow: number, endColumn: number) => AceAjax.Range;
private initPromise: JQueryPromise<void> | null = null;
private textEditorOnHashChange: onPopstate | null;
@@ -20,11 +23,15 @@ export class PreviewPlugin {
deferred.resolve();
});
this.initPromise = deferred.promise();
- const onHashChange = window.onpopstate;
if (!this.textEditorOnHashChange) {
this.textEditorOnHashChange = window.onpopstate;
}
+
+ this.Range = window['ace'].require("ace/range").Range;
+
+ aceEditor.$blockScrolling = Infinity;
}
+
return this.initPromise;
}
@@ -37,6 +44,18 @@ export class PreviewPlugin {
preview = _.throttle((text: string, element) => {
window.onpopstate = this.onHashChange;
- this.renderer.renderText(text, element);
+ const Range = this.Range;
+ this.renderer.renderText(text, element).then(() => {
+ element.find('input[type=checkbox]').change(function () {
+ const checked = this.checked;
+ const row = this.dataset.line;
+ const session = aceEditor.getSession();
+ const oldText = session.getLine(row);
+ const newText = checked ?
+ oldText.replace('[ ]', '[x]') :
+ oldText.replace(/\[(x|X)\]/, '[ ]');
+ session.replace(new Range(row, 0, row, Number.MAX_VALUE), newText);
+ });
+ });
}, 500);
} \ No newline at end of file
diff --git a/js/Renderer.ts b/js/Renderer.ts
index 1b60d57..1f77c98 100644
--- a/js/Renderer.ts
+++ b/js/Renderer.ts
@@ -9,6 +9,7 @@ import VideoPlugin from './VideoPlugin';
import 'katex/dist/katex.min.css';
import 'highlight.js/styles/github.css';
import 'mermaid/dist/mermaid.forest.min.css';
+import Thenable = JQuery.Thenable;
const slugifyHeading = name => 'editor/' + slugify(name).toLowerCase();
@@ -74,7 +75,8 @@ export class Renderer {
constructor() {
this.md = new MarkdownIt();
this.md.use(CheckboxPlugin, {
- checkboxClass: 'checkbox'
+ checkboxClass: 'checkbox',
+ readonly: false
});
this.md.use(AnchorPlugin, {
slugify: slugifyHeading
@@ -94,6 +96,20 @@ export class Renderer {
this.md.use(iterator, 'internal_image_link', 'image', (tokens: MarkdownIt.Token[], idx: number) => {
tokens[idx].attrSet('src', this.getImageUrl(tokens[idx].attrGet('src') as string));
});
+
+ function injectLineNumbers(tokens, idx, options, env, slf) {
+ if (tokens[idx].map && tokens[idx].level === 0) {
+ const line = tokens[idx].map[0];
+ tokens[idx].attrJoin('class', 'line');
+ tokens[idx].attrSet('data-line', String(line));
+ }
+ return slf.renderToken(tokens, idx, options, env, slf);
+ }
+
+ this.md.renderer.rules.paragraph_open =
+ this.md.renderer.rules.heading_open =
+ this.md.renderer.rules.heading_open =
+ injectLineNumbers;
}
prepareText(text: string): string {
@@ -130,11 +146,12 @@ export class Renderer {
}
}
- renderText(text: string, element): void {
- this.loadPlugins(text).then(() => {
- const html = this.md.render(this.prepareText(text));
- element.html(html);
- });
+ renderText(text: string, element): Thenable<void> {
+ return this.loadPlugins(text).then(() => {
+ const html = this.md.render(this.prepareText(text));
+ element.html(html);
+ }
+ );
}
loadPlugins(text: string) {
diff --git a/js/SidebarPreview.ts b/js/SidebarPreview.ts
index 64fef07..6c7bf62 100644
--- a/js/SidebarPreview.ts
+++ b/js/SidebarPreview.ts
@@ -1,10 +1,21 @@
-import {PreviewPlugin} from "./PreviewPlugin";
+import {Renderer} from "./Renderer";
export class SidebarPreview implements SidebarPreviewPlugin {
- private previewPlugin: PreviewPlugin;
+ private renderer: Renderer;
- constructor(previewPlugin: PreviewPlugin) {
- this.previewPlugin = previewPlugin;
+ private initPromise: JQueryPromise<void> | null = null;
+
+ init() {
+ if (!this.initPromise) {
+ const deferred = $.Deferred();
+ require.ensure(['./Renderer'], () => {
+ const {Renderer} = require('./Renderer');
+ this.renderer = new Renderer();
+ deferred.resolve();
+ });
+ this.initPromise = deferred.promise();
+ }
+ return this.initPromise;
}
attach(manager) {
@@ -17,13 +28,13 @@ export class SidebarPreview implements SidebarPreviewPlugin {
$.when(
this.getFileContent(model.getFullPath()),
- this.previewPlugin.init()
+ this.init()
).then(([content]) => {
$thumbnailDiv.removeClass('icon-loading icon-32');
$thumbnailContainer.addClass('large');
$thumbnailContainer.addClass('text');
const $textPreview = $('<div id="preview" class="text-markdown"/>');
- this.previewPlugin.preview(content, $textPreview);
+ this.renderer.renderText(content, $textPreview);
$thumbnailDiv.children('.stretcher').remove();
$thumbnailDiv.append($textPreview);
$thumbnailContainer.css("max-height", previewHeight);
diff --git a/js/VideoPlugin.ts b/js/VideoPlugin.ts
index 3a72e4f..2382f8b 100644
--- a/js/VideoPlugin.ts
+++ b/js/VideoPlugin.ts
@@ -85,7 +85,6 @@ function renderVideo(md: MarkdownIt.MarkdownIt, options: VideoOptions) {
if (alt && isVideoService(alt)) {
return renderVideoService(md, options, alt, url);
}
- console.log(url, isEmbeddedVideo(url));
if (isEmbeddedVideo(url)) {
return renderEmbededVideo(md, options, url);
}
@@ -141,7 +140,6 @@ export default function VideoPlugin(md: MarkdownIt.MarkdownIt, options: VideoOpt
const originalRenderer = md.renderer.rules.image;
md.renderer.rules.image = (tokens: Token[], idx: number, options: VideoOptions, env, slf) => {
options = $.extend(defaults, options);
- console.log(JSON.stringify(tokens[idx]));
const videoResult = renderVideo(md, options)(tokens, idx, env);
return videoResult || originalRenderer(tokens, idx, options, env, slf)
};
diff --git a/js/editor.ts b/js/editor.ts
index ce6022a..18b27e7 100644
--- a/js/editor.ts
+++ b/js/editor.ts
@@ -13,4 +13,4 @@ $(document).ready(function () {
__webpack_require__.p = OC.filePath('files_markdown', 'js', '../build/');
__webpack_require__.nc = $('script[nonce]')[0].getAttribute('nonce');
-OC.Plugins.register('OCA.Files.SidebarPreviewManager', new SidebarPreview(previewPlugin));
+OC.Plugins.register('OCA.Files.SidebarPreviewManager', new SidebarPreview());