aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorSam Wilkins <samwilkins333@gmail.com>2019-08-30 15:51:13 -0400
committerSam Wilkins <samwilkins333@gmail.com>2019-08-30 15:51:13 -0400
commitc9a7d747916c31730f71479d8e516ba0ed2c658f (patch)
tree2cd03764a446c81de91638fefac3812fcc2a67f5 /src
parentc53d721dd95bdb4ccddc7a89dbdda72a88d29058 (diff)
complete transfer except for list items
Diffstat (limited to 'src')
-rw-r--r--src/client/apis/google_docs/GoogleApiClientUtils.ts2
-rw-r--r--src/client/views/nodes/FormattedTextBox.tsx11
-rw-r--r--src/new_fields/RichTextUtils.ts89
3 files changed, 57 insertions, 45 deletions
diff --git a/src/client/apis/google_docs/GoogleApiClientUtils.ts b/src/client/apis/google_docs/GoogleApiClientUtils.ts
index 9bf3cae38..fdd708e31 100644
--- a/src/client/apis/google_docs/GoogleApiClientUtils.ts
+++ b/src/client/apis/google_docs/GoogleApiClientUtils.ts
@@ -45,7 +45,7 @@ export namespace GoogleApiClientUtils {
export interface ImportResult {
title: string;
text: string;
- data: RichTextField;
+ state: EditorState;
}
export interface CreateOptions {
diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx
index 83011e590..6af5c8f0b 100644
--- a/src/client/views/nodes/FormattedTextBox.tsx
+++ b/src/client/views/nodes/FormattedTextBox.tsx
@@ -38,6 +38,7 @@ import { DictationManager } from '../../util/DictationManager';
import { ReplaceStep } from 'prosemirror-transform';
import { DocumentType } from '../../documents/DocumentTypes';
import { RichTextUtils } from '../../../new_fields/RichTextUtils';
+import * as _ from "lodash";
library.add(faEdit);
library.add(faSmile, faTextHeight, faUpload);
@@ -481,7 +482,7 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe
let pullSuccess = false;
if (exportState !== undefined) {
pullSuccess = true;
- dataDoc.data = exportState.data;
+ dataDoc.data = new RichTextField(JSON.stringify(exportState.state.toJSON()));
setTimeout(() => {
if (this._editorView) {
let state = this._editorView.state;
@@ -500,11 +501,9 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe
checkState = (exportState: Opt<GoogleApiClientUtils.Docs.ImportResult>, dataDoc: Doc) => {
if (exportState && this._editorView) {
- let storedPlainText = RichTextUtils.ToPlainText(this._editorView.state) + "\n";
- let receivedPlainText = exportState.text;
- let storedTitle = dataDoc.title;
- let receivedTitle = exportState.title;
- let unchanged = storedPlainText === receivedPlainText && storedTitle === receivedTitle;
+ let equalContent = _.isEqual(this._editorView.state.doc, exportState.state.doc);
+ let equalTitles = dataDoc.title === exportState.title;
+ let unchanged = equalContent && equalTitles;
dataDoc.unchanged = unchanged;
DocumentDecorations.Instance.setPullState(unchanged);
}
diff --git a/src/new_fields/RichTextUtils.ts b/src/new_fields/RichTextUtils.ts
index 4ca51d311..bc338e45b 100644
--- a/src/new_fields/RichTextUtils.ts
+++ b/src/new_fields/RichTextUtils.ts
@@ -5,6 +5,7 @@ import { docs_v1 } from "googleapis";
import { GoogleApiClientUtils } from "../client/apis/google_docs/GoogleApiClientUtils";
import { FormattedTextBox } from "../client/views/nodes/FormattedTextBox";
import { Opt } from "./Doc";
+import * as Color from "color";
export namespace RichTextUtils {
@@ -96,73 +97,85 @@ export namespace RichTextUtils {
};
export const Import = async (documentId: GoogleApiClientUtils.Docs.DocumentId): Promise<Opt<GoogleApiClientUtils.Docs.ImportResult>> => {
- let Docs = GoogleApiClientUtils.Docs;
- let document = await Docs.retrieve({ documentId });
-
+ const Docs = GoogleApiClientUtils.Docs;
+ const document = await Docs.retrieve({ documentId });
if (!document) {
return undefined;
}
- let title = document.title!;
-
- let { text, runs } = Docs.Utils.extractText(document);
- let segments = runs[Symbol.iterator]();
+ const title = document.title!;
+ const { text, runs } = Docs.Utils.extractText(document);
+ const segments = runs[Symbol.iterator]();
let state = FormattedTextBox.blankState();
- let breaks: number[] = [];
- let from = 0;
+ const schema = state.schema;
+ const nodes: Node[] = [];
+
let result = segments.next();
while (!result.done) {
let run = result.value;
- let fragment = run.content!;
- if (fragment.hasNewline()) {
- let trimmed = fragment.removeTrailingNewlines();
- if (fragment.length === 1) {
- breaks.push(from);
- } else {
- let content = Fragment.from(state.schema.text(trimmed, styleToMarks(state.schema, run.textStyle)));
- let node = state.schema.node("paragraph", null, content);
- state = state.apply(state.tr.insert(from, node));
- from += node.nodeSize;
- }
+ if (run.content!.hasNewline()) {
+ addParagraph(nodes, schema, textNode(schema, run));
result = segments.next();
} else {
- let nodes: Node[] = [];
- nodes.push(state.schema.text(fragment, styleToMarks(state.schema, run.textStyle)));
+ const inner: Node[] = [];
+ inner.push(textNode(schema, run));
result = segments.next();
while (!result.done) {
run = result.value;
- fragment = run.content!;
- let trimmed = fragment.removeTrailingNewlines();
- nodes.push(state.schema.text(trimmed, styleToMarks(state.schema, run.textStyle)));
- if (fragment.hasNewline()) {
- let node = state.schema.node("paragraph", null, Fragment.fromArray(nodes));
- state = state.apply(state.tr.insert(from, node));
- from += node.nodeSize;
- result = segments.next();
+ inner.push(textNode(schema, run));
+ result = segments.next();
+ if (run.content!.hasNewline()) {
+ addParagraph(nodes, schema, inner);
break;
}
- result = segments.next();
}
if (result.done) {
break;
}
}
}
- breaks.forEach(position => state = state.apply(state.tr.insert(position, state.schema.node("paragraph"))));
- let data = new RichTextField(JSON.stringify(state.toJSON()));
- return { title, text, data };
+ state = state.apply(state.tr.replaceWith(0, 2, nodes));
+ return { title, text, state };
+ };
+
+ const addParagraph = (list: Node[], schema: any, content?: Node[] | Node) => {
+ list.push(schema.node("paragraph", null, content ? Fragment.from(content) : null));
};
+ const textNode = (schema: any, run: docs_v1.Schema$TextRun) => {
+ let text = run.content!.removeTrailingNewlines();
+ return text.length ? schema.text(text, styleToMarks(schema, run.textStyle)) : undefined;
+ };
+
+ const MarkMapping = new Map<keyof docs_v1.Schema$TextStyle, string>([
+ ["bold", "strong"],
+ ["italic", "em"],
+ ["foregroundColor", "pFontColor"]
+ ]);
+
const styleToMarks = (schema: any, textStyle?: docs_v1.Schema$TextStyle) => {
if (!textStyle) {
return undefined;
}
let marks: Mark[] = [];
- if (textStyle.link) {
- let href = textStyle.link.url;
- marks.push(schema.mark(schema.marks.link, { href }));
- }
+ Object.keys(textStyle).forEach(key => {
+ let value: any;
+ let targeted = key as keyof docs_v1.Schema$TextStyle;
+ if (value = textStyle[targeted]) {
+ let attributes: any = {};
+ let converted = MarkMapping.get(targeted) || targeted;
+
+ value.url && (attributes.href = value.url);
+ if (value.color) {
+ let object: { [key: string]: number } = value.color.rgbColor;
+ attributes.color = Color.rgb(Object.values(object).map(value => value * 255)).hex();
+ }
+
+ let mark = schema.mark(schema.marks[converted], attributes);
+ mark && marks.push(mark);
+ }
+ });
return marks;
};