diff options
author | Sam Wilkins <samwilkins333@gmail.com> | 2019-09-14 13:49:34 -0400 |
---|---|---|
committer | Sam Wilkins <samwilkins333@gmail.com> | 2019-09-14 13:49:34 -0400 |
commit | 42500ed737e17c2f973a653d59491eb33d6ba66b (patch) | |
tree | 5d5787b51d8c41709045330bf174ea69a7536f0e | |
parent | b91adad6b1a7112bb18dcd5332376175a65dedf5 (diff) |
beginnings of formatting conversion on push
-rw-r--r-- | src/client/views/nodes/FormattedTextBox.tsx | 3 | ||||
-rw-r--r-- | src/new_fields/RichTextUtils.ts | 153 | ||||
-rw-r--r-- | src/server/credentials/google_docs_token.json | 2 |
3 files changed, 83 insertions, 75 deletions
diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx index 8a623e648..23f615f32 100644 --- a/src/client/views/nodes/FormattedTextBox.tsx +++ b/src/client/views/nodes/FormattedTextBox.tsx @@ -284,10 +284,11 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe let target = de.data.embeddableSourceDoc; // We're dealing with an internal document drop let url = de.data.urlField.url.href; - let model: NodeType = (url.includes(".mov") || url.includes(".mp4")) ? schema.nodes.video : schema.nodes.image; + let model: NodeType = [".mov", ".mp4"].includes(url) ? schema.nodes.video : schema.nodes.image; let pos = this._editorView!.posAtCoords({ left: de.x, top: de.y }); this._editorView!.dispatch(this._editorView!.state.tr.insert(pos!.pos, model.create({ src: url, docid: target[Id] }))); DocUtils.MakeLink(this.dataDoc, target, undefined, "ImgRef:" + target.title, undefined, undefined, target[Id]); + this.tryUpdateHeight(); e.stopPropagation(); } else if (de.data instanceof DragManager.DocumentDragData) { const draggedDoc = de.data.draggedDocuments.length && de.data.draggedDocuments[0]; 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 diff --git a/src/server/credentials/google_docs_token.json b/src/server/credentials/google_docs_token.json index 293404853..c8fd3bbf5 100644 --- a/src/server/credentials/google_docs_token.json +++ b/src/server/credentials/google_docs_token.json @@ -1 +1 @@ -{"access_token":"ya29.ImCDB68jWP3W09KYIKQwzO_9eizRTpSx9UhP4tIPbSeMvjDsDyNOOl2hmffWHBrRFqz8kgaDxl_6lp-rlfbArI0x1Wm13J2h7wm5kBvOlCToqR-5qoINHetlWisCb11ig9A","refresh_token":"1/HTv_xFHszu2Nf3iiFrUTaeKzC_Vp2-6bpIB06xW_WHI","scope":"https://www.googleapis.com/auth/presentations.readonly https://www.googleapis.com/auth/documents.readonly https://www.googleapis.com/auth/drive.file https://www.googleapis.com/auth/documents https://www.googleapis.com/auth/photoslibrary https://www.googleapis.com/auth/photoslibrary.appendonly https://www.googleapis.com/auth/drive https://www.googleapis.com/auth/presentations https://www.googleapis.com/auth/photoslibrary.sharing","token_type":"Bearer","expiry_date":1568480323588}
\ No newline at end of file +{"access_token":"ya29.GlyDBwCmpO9R1fAOMIzpdZiCWhEeaDHiJOPy7sNRAo-vAIqzIk7zy1DLdOhSFWaBQrbmewSOJZPvbBUAxqdDELc_aW_BsjwXFbxiTd4Us_N8IWkPDCtUeBmLAZjodA","refresh_token":"1/HTv_xFHszu2Nf3iiFrUTaeKzC_Vp2-6bpIB06xW_WHI","scope":"https://www.googleapis.com/auth/presentations.readonly https://www.googleapis.com/auth/documents.readonly https://www.googleapis.com/auth/drive.file https://www.googleapis.com/auth/documents https://www.googleapis.com/auth/photoslibrary https://www.googleapis.com/auth/photoslibrary.appendonly https://www.googleapis.com/auth/drive https://www.googleapis.com/auth/presentations https://www.googleapis.com/auth/photoslibrary.sharing","token_type":"Bearer","expiry_date":1568484185591}
\ No newline at end of file |