aboutsummaryrefslogtreecommitdiff
path: root/src/new_fields/RichTextUtils.ts
diff options
context:
space:
mode:
Diffstat (limited to 'src/new_fields/RichTextUtils.ts')
-rw-r--r--src/new_fields/RichTextUtils.ts153
1 files changed, 80 insertions, 73 deletions
diff --git a/src/new_fields/RichTextUtils.ts b/src/new_fields/RichTextUtils.ts
index 6afe4ddfd..178cce839 100644
--- a/src/new_fields/RichTextUtils.ts
+++ b/src/new_fields/RichTextUtils.ts
@@ -5,7 +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";
+import Color from "color";
import { sinkListItem } from "prosemirror-schema-list";
import { Utils, PostToServer } from "../Utils";
import { RouteStore } from "../server/RouteStore";
@@ -91,27 +91,11 @@ export namespace RichTextUtils {
export namespace GoogleDocs {
export const Export = async (state: EditorState): Promise<GoogleApiClientUtils.Docs.Content> => {
- let nodes: { [type: string]: Node<any>[] } = {
- text: [],
- image: []
- };
+ const nodes: Node<any>[] = [];
let text = ToPlainText(state);
- let content = state.doc.content;
- content.forEach(node => node.content.forEach(node => {
- const type = node.type.name;
- let existing = nodes[type];
- if (existing) {
- existing.push(node);
- } else {
- nodes[type] = [node];
- }
- }));
- let linkRequests = ExtractLinks(nodes.text);
- let imageRequests = await ExtractImages(nodes.image);
- return {
- text,
- requests: [...linkRequests, ...imageRequests]
- };
+ state.doc.content.forEach(node => node.content.forEach(child => nodes.push(child)));
+ const requests = await marksToStyle(nodes);
+ return { text, requests };
};
type BulletPosition = { value: number, sinks: number };
@@ -186,8 +170,10 @@ export namespace RichTextUtils {
const uploads = await PostToServer(RouteStore.googlePhotosMediaDownload, { mediaItems: inlineUrls });
for (let i = 0; i < uploads.length; i++) {
- const src = Utils.prepend(`/files/${uploads[i].fileNames.clean}`);
- state = state.apply(state.tr.insert(0, schema.nodes.image.create({ src, width: inlineUrls[i].width })));
+ const src = Utils.fileUrl(uploads[i].fileNames.clean);
+ const width = inlineUrls[i].width;
+ const imageNode = schema.nodes.image.create({ src, width });
+ state = state.apply(state.tr.insert(0, imageNode));
}
return { title, text, state };
@@ -265,71 +251,92 @@ export namespace RichTextUtils {
return marks;
};
- interface LinkInformation {
- startIndex: number;
- endIndex: number;
- bold: boolean;
- url: string;
- }
-
- const ExtractLinks = (nodes: Node<any>[]) => {
- let links: docs_v1.Schema$Request[] = [];
+ const marksToStyle = async (nodes: Node<any>[]) => {
+ let requests: docs_v1.Schema$Request[] = [];
let position = 1;
for (let node of nodes) {
- let link, length = node.nodeSize;
- let marks = node.marks;
- if (marks.length && (link = marks.find(mark => mark.type.name === "link"))) {
- links.push(Encode({
- startIndex: position,
- endIndex: position + length,
- url: link.attrs.href,
- bold: false
+ const length = node.nodeSize;
+ const marks = node.marks;
+ const attrs = node.attrs;
+ const textStyle: docs_v1.Schema$TextStyle = {};
+ const information: LinkInformation = {
+ startIndex: position,
+ endIndex: position + length,
+ textStyle
+ };
+ if (marks.length) {
+
+ const link = marks.find(mark => mark.type.name === "link");
+ if (link) {
+ textStyle.link = { url: link.attrs.href };
+ textStyle.foregroundColor = fromRgb(0, 0, 1);
+ textStyle.bold = true;
+ }
+ const bold = marks.find(mark => mark.type.name === "strong");
+ bold && (textStyle.bold = true);
+ const foregroundColor = marks.find(mark => mark.type.name === "pFontColor");
+ foregroundColor && (textStyle.foregroundColor = fromHex(foregroundColor.attrs.color));
+ }
+ requests.push(EncodeStyleUpdate(information));
+ if (node.type.name === "image") {
+ requests.push(await EncodeImage({
+ startIndex: position + length,
+ uri: attrs.src,
+ width: attrs.width
}));
}
position += length;
}
- return links;
+ return requests;
};
- const ExtractImages = async (nodes: Node<any>[]) => {
- const images: docs_v1.Schema$Request[] = [];
- let position = 1;
- for (let node of nodes) {
- const length = node.nodeSize;
- const attrs = node.attrs;
- const uri = attrs.src;
- const baseUrls = await GooglePhotos.Transactions.UploadThenFetch([Docs.Create.ImageDocument(uri)]);
- if (!baseUrls) {
- continue;
- }
- images.push({
- insertInlineImage: {
- uri: baseUrls[0],
- objectSize: { width: { magnitude: parseFloat(attrs.width.replace("px", "")), unit: "PT" } },
- location: { index: position + length }
- }
- });
- position += length;
- }
- return images;
+ interface LinkInformation {
+ startIndex: number;
+ endIndex: number;
+ textStyle: docs_v1.Schema$TextStyle;
+ }
+
+ interface ImageInformation {
+ startIndex: number;
+ width: number;
+ uri: string;
+ }
+
+ const fromRgb = (red: number, green: number, blue: number): docs_v1.Schema$OptionalColor => {
+ return { color: { rgbColor: { red, green, blue } } };
+ };
+
+ const fromHex = (color: string): docs_v1.Schema$OptionalColor => {
+ const converted = new Color().hex(color).rgb();
+ const { red, blue, green } = converted;
+ return fromRgb(red(), blue(), green());
};
- const Encode = (information: LinkInformation) => {
+ const EncodeStyleUpdate = (information: LinkInformation): docs_v1.Schema$Request => {
+ const { startIndex, endIndex, textStyle } = information;
return {
updateTextStyle: {
fields: "*",
- range: {
- startIndex: information.startIndex,
- endIndex: information.endIndex
- },
- textStyle: {
- bold: true,
- link: { url: information.url },
- foregroundColor: { color: { rgbColor: { red: 0.0, green: 0.0, blue: 1.0 } } }
- }
- }
+ range: { startIndex, endIndex },
+ textStyle
+ } as docs_v1.Schema$UpdateTextStyleRequest
};
};
+
+ const EncodeImage = async (information: ImageInformation) => {
+ const source = [Docs.Create.ImageDocument(information.uri)];
+ const baseUrls = await GooglePhotos.Transactions.UploadThenFetch(source);
+ if (baseUrls) {
+ return {
+ insertInlineImage: {
+ uri: baseUrls[0],
+ objectSize: { width: { magnitude: information.width, unit: "PT" } },
+ location: { index: information.startIndex }
+ }
+ };
+ }
+ return {};
+ };
}
} \ No newline at end of file