From 34b0ab500103737f7efe7f9f8df2477d3cc15141 Mon Sep 17 00:00:00 2001 From: Nokome Bentley Date: Sat, 5 Dec 2020 19:06:39 +1300 Subject: [PATCH] feat(GDoc): Fetch node content from Hub if possible --- .../__file_snapshots__/test-fixture-2.yaml | 140 + .../nock-record-decode-fixtures.json | 173 ++ .../gdoc/__fixtures__/test-fixture-2.gdoc | 2556 +++++++++++++++++ src/codecs/gdoc/gdoc.test.ts | 18 +- src/codecs/gdoc/index.ts | 222 +- 5 files changed, 3008 insertions(+), 101 deletions(-) create mode 100644 src/codecs/gdoc/__file_snapshots__/test-fixture-2.yaml create mode 100644 src/codecs/gdoc/__fixtures__/nock-record-decode-fixtures.json create mode 100644 src/codecs/gdoc/__fixtures__/test-fixture-2.gdoc diff --git a/src/codecs/gdoc/__file_snapshots__/test-fixture-2.yaml b/src/codecs/gdoc/__file_snapshots__/test-fixture-2.yaml new file mode 100644 index 000000000..2363bcbd0 --- /dev/null +++ b/src/codecs/gdoc/__file_snapshots__/test-fixture-2.yaml @@ -0,0 +1,140 @@ +type: Article +description: + - type: Paragraph + content: + - This is a test fixture… + - type: Paragraph + content: + - '' +title: A Google Doc test fixture for Stencila +content: + - type: Paragraph + content: + - '' + - type: Paragraph + content: + - Nokome Bentley + - type: Superscript + content: + - '1' + - type: Paragraph + content: + - '1. ' + - 'Stencila, Kaikoura, New Zealand' + - type: Paragraph + content: + - '' + - type: Heading + depth: 1 + content: + - Tables + - type: Table + caption: + - type: Paragraph + content: + - '' + - type: Emphasis + content: + - >- + Italicized (or bolded) captions before or after a table should + be decoded as table with caption (and label if any). + - '' + label: Table 1 + rows: + - type: TableRow + cells: + - type: TableCell + content: + - Species + - type: TableCell + content: + - Height + - type: TableCell + content: + - Weight + - type: TableRow + cells: + - type: TableCell + content: + - A + - type: TableCell + content: + - '2' + - type: TableCell + content: + - '3' + - type: TableRow + cells: + - type: TableCell + content: + - B + - type: TableCell + content: + - '5' + - type: TableCell + content: + - '6' + - type: Heading + depth: 1 + content: + - Figures + - type: Paragraph + content: + - '' + - type: Paragraph + content: + - type: ImageObject + contentUrl: >- + data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGQAAABkCAMAAABHPGVmAAAAA3NCSVQICAjb4U/gAAAAElBMVEXMzMyysrKdnZ2WlpbExMSqqqq6fF5GAAAAgElEQVRoge3S3QqAIAyA0f3o+79yQw0ceFMZdfEdVGSDDaYiAAAAAAAAwC9Y7Gp1HDm+TFxXzEVUY7Ujx1eJW000ilmJou1odePW4ynxiLcl7v1eTOsZT4mdTUS9vNIkTWVusnNc8/umcW16+F5s+qm1P/yY0J4vDAAAAAAAgM8dUgYBkQqGEcgAAAAASUVORK5CYII= + - '' + - type: Paragraph + content: + - type: Emphasis + content: + - >- + Figure 1. Italicized (or bolded) captions before or after an image + should be decoded as figure caption (and label if any). + - '' + - type: Heading + depth: 1 + content: + - Code Chunks + - type: Paragraph + content: + - '' + - type: Paragraph + content: + - 'Here is a code chunk which has no output:' + - type: Paragraph + content: + - '' + - type: CodeChunk + programmingLanguage: r + text: '# Some R code' + - type: Paragraph + content: + - '' + - type: Paragraph + content: + - 'And here is one that has a some output and a caption:' + - type: Paragraph + content: + - '' + - type: CodeChunk + id: de6c884d-5892-4c4f-88c2-ba51be893eb3 + caption: + - type: Paragraph + content: + - Code chunk caption. + - '' + duration: 0.007 + label: Figure 2 + outputs: + - type: ImageObject + contentUrl: >- + data:image/png;base64,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 + programmingLanguage: r + text: 'hist(rnorm(1000), breaks=100,col="blue")' + - type: Paragraph + content: + - '' diff --git a/src/codecs/gdoc/__fixtures__/nock-record-decode-fixtures.json b/src/codecs/gdoc/__fixtures__/nock-record-decode-fixtures.json new file mode 100644 index 000000000..3954fb435 --- /dev/null +++ b/src/codecs/gdoc/__fixtures__/nock-record-decode-fixtures.json @@ -0,0 +1,173 @@ +[ + { + "scope": "https://hub.stenci.la:443", + "method": "GET", + "path": "/api/nodes/aExdDDo6twFHCekMfHNFbKsFrCRhKFnv", + "body": "", + "status": 200, + "response": { + "creator": 1, + "created": "2020-12-05T02:34:02.850023Z", + "project": null, + "app": "Encoda", + "host": null, + "key": "aExdDDo6twFHCekMfHNFbKsFrCRhKFnv", + "url": "https://hub.stenci.la/api/nodes/aExdDDo6twFHCekMfHNFbKsFrCRhKFnv", + "node": { + "text": "# Some R code", + "type": "CodeChunk", + "programmingLanguage": "r" + } + }, + "rawHeaders": [ + "Server", + "nginx/1.19.5", + "Date", + "Sat, 05 Dec 2020 05:54:48 GMT", + "Content-Type", + "application/json", + "Content-Length", + "286", + "Vary", + "Accept, Cookie, Origin", + "Allow", + "GET, HEAD, OPTIONS", + "X-Frame-Options", + "DENY", + "X-Content-Type-Options", + "nosniff", + "Referrer-Policy", + "same-origin", + "Via", + "1.1 google", + "Alt-Svc", + "clear", + "Connection", + "close" + ], + "responseIsBinary": false + }, + { + "scope": "https://hub.stenci.la:443", + "method": "GET", + "path": "/api/nodes/8cd620395bf1fbb43c3298275defda2b9705cb1c037b4fa2eeb6ffe588a4bedd", + "body": "", + "status": 200, + "response": [ + "1f", + "8b", + "08", + "00", + "00", + "00", + "00", + "00", + "04", + "03", + "e4", + "bc", + "57", + "af", + "ac", + "dc", + "d6", + "26f657ac73658bef6b723a962fa0c850400145b26fc845ceb1ffbce73a6d77db9225774b962cd9afb4f75b7b55154c6618633c61acfff88f6c29926d5cfef14ff4dffed3eb22ffc73fff812118f2ef28faef28e2a1ec3f49ec9f38f31f188cc01124fec7bffd635ac6a6c8b67ffc73d8bbeedffe914c13f88aeceef59680777fe3fa9fdf6a8b1bbcc564398521384ba6255aa629816738c632184de645992758cad20899a56886e0744a9409561429559605c930099116790e2eba2f1db8d06fdba6f59f30fcdbd3ffb06ec590d5ffa14be064aae161cc8b15fe7fe0467f17fac73fffe33feabf69c80b2a631822ff779261b17f2732a2fc7786c9b07f4f13124d0b86c58b140783db8a0b3cf13f7ef5bafdf7cb302efd7f8f2208f23ffcdb7f9782c96dd7ff09fcebdfb2b1fb9ffe977fa4dd5efc2ffff81ffebe734fe03eff7881dbbd7efbd0821f8dfb36eddbfa8f7ffecffff17f7f5bed93aab0d27fcd36589f71000fbd7dff351779b225ffacffde87a7a1fa1fd3642d28e2df6a9fb79c13d1e56ae4c07fa6fbfd89df0abc6a09f09766bdb808fc9fe783a841c10bee15f26a10bec18f3207fc33143f8aae1d6f18bcae38b1133fbe430cd693176995f9f14030056c7e7ebadbaadf2e724433602bb1f5fd8f243abcc8cbfec7e950478c1154637415d2555d18c7ba19a965e7b046d5759998d5455df47735d69fadd2e69ba37f2ff7d32ac2411310de6f", + "3b9e0e6149ed73070d316c33b0e7dd2c3aefcb46edcbbc21506e5559ebc6eaffe7ff24ee837388e96f2cae0bdf8ca539a15277de89f8f094158e7debf87b143c3d8b4e469b2e276d7e39f529deb8982add6fb72691b8335f1d9437adc2c94399b32dee82e74a2ba7ff1a28fd1112ea8ed868518861bf8d331f461d339e6ffd72cdf6a0aee26b59454825fd5e228da0e7ee74625c4baae9b2e38983cfe1919d59c3a6427eea0697f4dd5587ce31faea030d2cfb9dac0b276c5b8afd157e0eed59820a263c48b09d17de228c7751d2532d99201a1d2c7fa38bc1b1b20bb4a215fa2924b6cfa450904e10efee9a15ab67ec112ef32efe24ad67ac0fd3581447feb211ba972a5d23381d7a2f7e307ea2c677087779dd9e33b187eb273e736a598d232c36ddb3e41dd210489f2df1cea0f5081af3b43b324a9b7e2178f70d4f703e7466cf2159e13b3f6be033e17ec7b1b3c7b847662b6175e11ec361b9cf8e25afe05ac8e6667145b071bec9e540dae8b55beff9b46bd3de3d445a34df31067486a1e26d37119b12173a45ac51de8115e3eba7fe5654eff5554d66574f4adbd94502c3c4044caad42461da972430afb2b984e8970423c071bf02710bbfddf91e5a163999c37defa68507edf0ad327e72843dd2328fa77cba1277ae718c5d5cd3b3b07896786b039cefc272be528d15aca9c4f8ccf7fccd2d8d846f3f74fb2af88b5086987a70291360aec91c0c1b7d2416108119e8a79cf87929ad57c6d155b2f371c6b3eee799905357b829737c6add54765a0f63b0f6dfe490b64de8b209c3addda6d7535056e1f80e599510c7441b74d07c0987c59b9d84e009e90804f1747b417dd23ee6d2497be0198c840939b9c48a98f8582df872476ba68874e9c6514337e5ab9567ebad0f54a077c511c6752bd4e392f97368bd3318053b46df79610e7b4313699b2fa96f4493dd696ccb61313c616c283960d9cc05b46587d48dda46e08f68eabc22aebbd218df37d7b9b28b5858a3170c7991070cdddef361167ea51e5e91d29f0947079f6fc2106c69bc47ac419a59db545366d7ce57395f8a7864e5dca3f9fef34b19cf5088784be1be78a16e7f7fccd25973d8ee0781b72859f944404dabdfe8773e2fef7af3a8bdffc6d2b768ef094bbfdfd87de5aa322144e7edc530d58c008ff0d84005d5184df16dc283f97a2efb7dcd0f8f6b1499bd52ea9c0f54926dd114c741ccb372acec022fdf2ce941fd1caa89aac39fb49ea7f647bca93764e76fa3287fa8ede1b17be3c5b0e7ddb460a62d0bb994cae6524bb49ae00215ea876b36431ee0c7256a218ddc332198ef2d42bb3e821b3a730758f1e552ca8221343082f54692558a6e87de89c94047929afdadf86b582e03fae366d3761f6450718a133cb37029b829bcb0ff254d3cdf245daae84d45e960e1e9ef5d8fc1f41e994f79912deadeec5b99524b730965c67bd47e4c6d24d23849f2ba736654db242485de2895ad11ed7dd77dcac365af3a97c4ae8e7cf56a3fc2ec6533b88a4dfb24bc72a5cb57d45151fe4a14d1863dc41cd04b9f6864ebba372cfea0ae6c1ce8f684094602d1f8aa6811e2b3bf048618953f0ed6302e9d728f1461d5ceeba6ca8b4e9271251b6e9c0065cef26bafae6b563051e82f61c28ea3d891304b8d8c351f1c959f458b3bf2617b0389614d35c030166cc32adabc36682f03f1f78408d4b88e1553a5ae7472835bc1946d3e2c195b27e7dfc223c3741223d275b0afdd54feee05896561617f2431d8c3ac5056e737b34e81b269db6bb72dbed74bee8746f995bd24eddc24aa7e5cd2c9162215d808fc286def297da8e8419bf84b2c1fade80c71ad5f87627713ea9210f633e5e16b50dfaf9bb0cfb1c67d72f732650669cd6a865bb2233c1bf2a084c8bcd81c0bcea719d2b661e836338cf2646fb28d4030d5cd45bde31fdabe366c03818643e168", + "a4de813f698a4c195280f9b57153e08ef9df3e98a7bc73673c25d03bd95ee25a591ff97022eae8e9da7f7fa8606110a26ea9e1103fe51c73fb4ae976c818cc671a16871f7709dd4a6c56e61cae75a2ff1dbe0a21a4804441f9b53785fca4d5a52fe9ed741ddd326cf8948a754021f4968f423b094aca53de3e2f361f8f2f030f24fa0b373f66951dfdd2b0ad320d2b5a543ca397912ee884aa9084a5632e13181c1e13bf4b363a728f8826fd3243f91bbd67bf5c1e2ac76edc98b5b488bb7e30a580ab635beea95d65dbca7f83a35f2999375d3d245c972698f66751bcb44ae1af1e6e2678f65e10b2d35bcad2d58a2d783fe3a570ab04452383cc75bcb301d1163bd4b1a3350d3a426d173ac42a0c37b0f92de2454c3636f56606ab075b63952d03b15221076a18d0061be90db11a26cd9790acbd62a34796529da204c93e5fd5a5a05f314877296d2366e7f35a4bced3d7520d3c604184cd570f15062355ad25b85fa144325427eee098703a3b471d3e61534e4db8754f3396e37a4e430ad69e45f8cdb0224f624b756c8d213448e375c2afd8b2e8602511c1c04a8675a64d91e719a76c73999e2a3570146f58379848364ce7096c918ca0105a4712945535d4d83ced718718dabf8909ea005d9bbc6fd1d1fd3bd9bbad9b69e7db8abdf79beda5569371a0c45904d7727df16483e64591836e070c5eb12c3ae4d3fa8e19aa08ac2dbea8611e1fdaf9c9ecf47e5eca2d51363b7b9841973aceb35f652be9c6e7d76c47163e281d7af32df8b90d7d3e8525d91d2469523687108dda0b8c51f7e7426d3b36b3c5f43cecf0da9b8a9dc13fd479f7be77664a042b4c97386846daeb3f070a205966cc00baaf0b0a9346694f76614b487bd0a4c00381805d98c217189256921a768a2609af76f7ae6c41de4afb2f7b505e4afb7fe36a428f5d7ff8c74532daf384a21bb67c7e91ceee8007166634ed3a713b3224f1a2c9af88de2b56913d39480d071f57453a86936e866a47ce6f37be483077cfe1ebe9f650475bff2af64b15c4679bf7ab7961a30dff06158a4eab1bdef2b6ce33595ee916cc0f663114516ead488f091b409ba853829f06ec76736d34bc23e25a13b6dd6eaa0ef03e6da82febfa8f792143fdc8308f8d4b3a214fa8e35cc7bce130610539e8c9e09c5e9053567253125585fdce6c18e66ddfcad2a68a9efe3a98c1e2c7cce75505125d38e7254678ce879ede492fbe973cf92fe3b229c723a12299c3470ebb8e1048b1ea8c2d048ba62356929beb3d83c43098aac974c1e75fe718b2d41b8e60c13e95ece3e758f554abe92c289514d309bff9071c612381c510eb7d7b75546c7fa3550cddef7a81b4e85c1728cb88ae685f6bafd9ef755616c804a17501458237239e7344a03aa69d1a5e456789792c36f6d4399c79659bc3da153a7eed4ed62639add5c91a6de9779a8b2114282a147badf46f78353347d15d10240e814dcc105377eed5054bb68ee844f52cea4ed4dd0a6d87bfb74253c123c4bbc38d88cdd944c57b212bb0a2ec1dbb07b1d7b014522ec3e2ae55cc3af945d88b68264dd9513887eb752ad999b942583b2636f297f9908f3c13679837b6c3e10edaa72275becf843386ba512f141ec5c84e69778679ade14988e460f17c5be6625bcbeca9433c79b18606bdbf64efff14c37e214f36a83db2f23d978a6f5f6732cccbd6be69a287a5a379f14426d13a5dacf938a6ef704c49a3efb0cbda6ea8f9816499271dfa415cdca84c4958eafb57c0cca7f18ec0927b66773442c4a5cf12ff6cf865a7cd537f7c94bd61f4a8586730acc854777d31559beafc12ccbfc7c6f13279a78869911bf5533643fd7e16eb976d737e6f5e20acafbf4114e022d5f3d8896fa48c060f05f3a7628b1f3b2a2e5e57933b996354369aca62b66cc5f2c8164b95defa7e035ae649f1643728a592b20ff1940173da15", + "ec6390c0d7ec5292aa26f133e7bc87e69bc19aa36704d1889444d683910f209f47d24f6972037313de2dfc783f3bb1fa942dd17e45c6f3ef030c54cec142e798868f6bd92163178f962723970969fd4ce362c326241ba8206cdf30bd6b248884eb78a795cdd4f2e2977751614ebd2d29115df87743baa342c70d0f7590dec2566d0722eb161c2bf69771", + "d9", + "bd", + "9a", + "e2", + "ad", + "89", + "c3", + "4c8d11873df2290629b97a4decd16cf9885efc8fbc2e7b137fccd054072eae45e65f5248b3e952cd52da4d0a443cefc2c6594ddededc49959bbe64525e149f622b2947d13e904b3077f1c36a7edaa4da565ee8292d523e3b9af11db94104c366ebdcbc94dba0f585ce65ad45ecc8dbc4cd2b9fde68734863c9287a8cdf63de320e582e4368134ff6021e19d9093029863e8c9896a5d07ce377b762921e0639ee0cc440f702d2bedec956455723c2a8b9ed1daa56ed9c08f8fb98e79e2bb8175343e2211ca771b9ea145037059d68dd1fe355934b161b078ab99dd57b8e652fab4b3cc794ae42a377e5f29154f6586dd160a320a5d07411b7b95b27aa187118f2351531824b0b571f95f2b74ef6fb2f893ce58c20fe63f35f80de70e5169830663f073ee5d0f9fe6db97c93c4b77635b1ffffd59f629b38ec23bf396c05e0d9c4f834e2c94a7ddabe33aaa8e02842302a8979ddc8ac7e012f35fb9e57b9cccb3b4dc10a60a35219ae05eff9a4da6e718b7a5bdf03be4d286ecf964e09e6f948104e756901b9c715abf022e490fbec2eca30afb065da2f69c80d347087be0ccd69d9ddcf35c0faa5d7c56b0f8973ee3547f4e38b51f3151593a6d6978b6269ff5e441fb02d6ce56e7ab4d491d52f6bd02b65199b2458fbd999448ae07e1188b09db08a4c57c4d327efc0972d2c101f5f713ce465c89d036e4691e712a59f5afeedfc28deb936e200b2c9d859875d189de6e5c61ad58c9db7adbec881b2f1b5deb4487345a698860a9edb4dbe4f962d180379d08fe1022103456ef912e6a1ed5c5fb599d071b79ae17ea796724fc649a71e8a82ef0897928b9f93fb120a795a2917b66ec87336e767afd0baee47133b37292207f6948e2eafbb96ab3077c67386ed9fdb8fbc4ce4c6bcaec9c48e05c7811abf6b49c9ac624c1da3acf7a96f1f918cc09f76c801b41c9f0593359deb684aa0d42628dbab08f295af57cb2f5dd331b5c838f48cace3d5baee74a09564a704d2428dc5a5f1e1bb2f57b3bf4d423eb37cf316ea2295b5ba8c34d473724c2bf1fa552664207819721b212ed8e5d96ed66ff56b4be4a86a5d5f47a5eba57d87b0a1e19d43efd4234f0e6f739483ad9fc5938720c515e306d695a575bbcfd7752f1194f1f2991f06932406968478e5305cf147107e763e20f699ee336ea9de18f79c605f85f09c982e38bf6d67690331e1adb20a85138984d8d4aefc85db297b41e74baa976421a75386dc2285c3336c1e50e76af2b4a2dea47dcf97515746175ecbc7ab3fc4f923383c169f12608a20cd11b7177e5a046a31b0ba214f38eb8b68bc0c80a25e89e4f7cb2761737f535ee60a5913a6083bb6b53b19afd8c2dcc8d9beb320e7efd9fcf64bf5cd9ea9cb925adcdd09247362f236653636a48f00c91cbd9a8b636b2c8f3f8a63660a0bf89877eb06df2bcb262c0a0d580bd40aa71db452913bfc3115d6727c68cef2fe72b4efd8bd0743639bbe1e724e00ccb55594535738b793fd2e79a068bad8f6bf7551274fbb6ffc43645c7d82ed5362cfa3d831f10a3582b52f9037357198ad30e1827c3faa04e354a29689de221580cc202e3dd72795b56fefbabd51fb26c49eaffce906c4cfa2c96a6b0fd545d8df22526b6f47b3335afce3b77537f334a47727ed7a0f60bceda0ded91fef9d2ddaf517835fedf07716dbf9ef8327e0c3b5fb3dc8606d07fdcec0e7ebcfbfbeeac6fadf07b3bfb89d35dad5d68e76f79d8b8114f15d3b8b33624be9d922faddee5589e09e039b72c609784ddde3de85f1b4999be3d6170fdccb000434a14cf127abe76c8fadbf71587e4b80", + "6bb693ebd531987f5fb3b496fadb63240051601c5e07e01b189ffe6d0156f83bb3e083e0b91dcd8a5be2ef59c9c0abffc6d7fd7d15ccc1bf3e3881ef78fdffed3d3c7704d478d8c69680f240511295bafda51208b60e0e709edc913b7f5c6e965fc9398ec1e582dc9e2377764de5a11959bd80a8a06a6acbba76faffe6f3b4cc687d34431ed3800ffcd0a64f29e81cd79838eabedade951bcb70b54fe0b318e4f793d8368bfcb70fe4e62df45c4a7324c3c720e27cb1fff2de6b68e3ec75360ffbd3a8e1db7bff9573fa9fd7ed0dffdacdfd5ea782712ff21d2e950ea9b07bfe5a4c849b9234e85a6784988c3e0dfb89c0dee9e67bd02a76984f0a442f1e16c66d70943fd2281338a6b9aa1f39c31cc16391257626e3bbb926f85b4ae93515fb1d4f1abf08715604cc85638d9ae3584319cfd15fee4cfc73ee8f2b7b99a756724b34f620698075cb53b9ae73db3b158b6b40bc04915ca0ef4f4cfbbaabe96d287db18cac14983b4e3de07ae6255412c495a70af1fef97602fe05f6e8f6d9ea8ef4d9a7398fe283894ff52938eb54707ecc8e55c900d0b68a07f5be79322c018f9e32cd6d2b9711627ca76e778a3697677c77be203e76435107eb62cd9c8f3be2ca87d407d723013acd83e708ae69bbbd3c254bbdf44d43e7f369a948984ef5e08a28d4cbecb30bd269300e7afbb0dc547160e20082f9207c14e8fe830632e36dc0da258ea92186c137607c48fbe5597ea98f0b44acc91d38e8eb0e79f5322a8179d584a8544ea851acc5b1d1d05241c871b3c1c320415384fc6bdaefaa171879be48ffb918c1e897439f18b1e7c6ac5dee9307a19e78abbd88b39c8ec3d96fac8c8c8c103179b5c6f201b37d9d462949caa9cab53f0f5d363c401bf8c59f203a1f491c94ec65605d756cd9a7cebf9f4c6996135b7429eb4cea97c1d15145bed16fdd3d3eaa4fc04505ea8c5e9045eb0e6c804cdf2d4419452d33e5a2b969a77d60c0c0d8ca83ec6bca35d12cdbd0f29e62d4e3ec27bde0a7140a2d2dc70ff3c65eebf7a76ffa784ccbc0ed445b92ddce79a761f310f1f3867c73b70f917e34a67e2a336f16c79cc7f4707bd226dd31c99625b5b8ed2ede4df0fbab9762f37774224930e56cdc98336ca1f5ad909a3e75487e3d14f2f41611fe10ff4994146a57cf79e69e30c7df422e5f9706402884fabe6e4b07afdd653e9389a4abc002458a60577bf691ee18c500a73c62108c3a157e5820d60ee2d7d727b416a015c6f60adab3417f9ef507b0fbb955d8156d2eaa3f3588a721500d22280e8e30da5af7ce85e6bcafe32e3982aa7782912bec1dce418b2219c9ffe59c56d73584663a16d939e5523584fc9a0f40ef8d1a913975bf34bf7ba3fc6f736e576cf25a4bc4f242d148f9cb6377f745b27414218e3edfd06baad69538d401ddd8c3ae018efd81a20a684f9b6d441dd030aade2f406d147cc67130c21a8d5806d9023101bcbe4848698b669cedbc8fb73bd6e90c3409baaa943fd8c510ed02b26bb5bf3e89dacd52490fc2fbaf5678e27963f25e9315a0a088319e1a2d9c85616212f545bf136ffa7edc9c5bce60d614d646ef47c84556f320b0700b0fc68f8a5642457fb3afcf2b9cdd7bcf7c6b3b36d23bda0daf87ea32f8921f50039a18762acc8b3c255cfc0e3e78fad45d3cdf1ab38851aa8790f1e81323204f6153621988381b380d50f3e7905a676a97ba8c204020c080519d779dbac30fcb346a03175fd7a678cbc3d049c4d18fc2d519bfd119d89eccbdb716731879dea2759736016ff16881057928d201741454dad8f78eb7de026d6011654df2589f3581886ac02f54ee7d90ec8818e2c0e409ab0e898077740746ec7e7e665242fd96e329205039af5a6b790aa96c4847f91114a935d4f8270d135777d46515ac41d40214bf6573df341b28b4deac95215dcfb8045d6ea1c2038662ac8ac5483be347", + "318a011e15ee7c5dc359a1c02d8d2cb525ab3770ac55c9a06931ff263624951284870b7765794308d02b697bcbf145d8a1f6d774da782b330ea6bf5a7a295ed4bda80608f6d77d488af336ee9c321e500c368fb28edf7cedff30876b2a22e553f591415f450e0179f2c5d8cb073c405fb8b8c3af02a89a276764044c925561feee1c097215f8aea17f1be7829aefc9c1558d7c6baa5b0255f56b009ce8c4bc50003d0803d4679711f01873d436d0480efbe4d28e0faabf7aefd0b56d10084311a3f791aac7db178ef4eb990fef023941ddea4faaad440b0d800737b7ca2a7aff2e9fc6e98350f2bf8ed2b1cc0f9a194ac1ab2b6f980ad44da50eb4ab3f5e24b3db86f81938cb6613849760b11ce830eb88928d5f3d5ed373f28af81e7e40f3b56b19bbf6de76feeabc6fe379195c9775a964c0173212d86f51a736e279a293bba4043bb1ebccd006682c55649b7a335c5a07521402005b5375fe5793d9c913ab7e11882c6296c65b5a43d7b3889f98f1459dc39fd53b81f4972470e35539f451ee3068473d3b81aa9094ce8163edb27ecc14f16fa281488d90bdda833629c85ee58d6d811cd0f920dcad24365e2376293d743fdd42df45e201fe1c4d20f5b2faf4e494afbda2848d2a69de28a7dd1b635fe688dabe260702b9528076336edfb6942c3890ac54e85de349a1c1d8c3d4fc0f8118ebd43699c9aaf6dcf988ed9e9fbfad3b3204cafcac038d739c070aa2a66fb14cabcc54ccf182dc87895dce1e05731edefcdca65103dc08f03b05cc618e70b4282121cccb63af90ac9d28400310abb4a287b4d9a32ec9c7c952fd8a8355abed410947c02de3792e8203beec4234f27303ea34f3c67d0f101e37678146edb96cbfde742a95887c3697469a308f19829104c72ea5f852583f4050e718d22ac778185398666d07b077e5afe05cd66f248e7d215bc6056523383bbb86e0ce0152a88d708a84e2c1cee5973208604dbf1533f54dcddae90073b9c431041dfc4c131d403987033d3ebe331c5cf71b1123a811575eb88cad9cc83d040a01d8eb3920f33f3ad0b4833af134508ba242a1037d073e7125f9abe787bba3e69d6ca35928b7d32e531f21da61517fab00025f898b03566eb9f8881ac2d2dffaddb2edcc211eae69960a6f63cb263da8e1cca316a5fd407844b7d58d7811d982e0eefa5e631a28352017f84a3ed3779b011156a349a79264fa7b64f9ed01e8a6036a97b67359411e9b5b41383d01ec653c696f8f4511ccdaa30418fb81da24ffadedde79f4db57c029571f0222e02a83906ce9dd6bea6bf34bd231a850da2ca24ed2fb3224a1289cc608744d7da023b3a461e0d9f9a40d8c9b033402e4f335fe4dae34557ea83d5f69fbab27c3bf9c7c60d724811ad52d4cf0b8ff09f39460ab343e30c6c81ab30d0097472de6d5d00c2c281d38f8c48860bb03eadd39f44ce05b48b920736f5fdc80a1e0e03a4209cd47dcfff0563b85ace4e545fba9b757e88c3962d721952175f44a2e398f5d62dd5f0053ceeefeb75fa0dfeb143aa5d9840ed003fce02c9d50038fd0046289e4dfe1a428473e0a0337ee1e8641da17066b65a77a85007216ac34610f2849f71db37332617e5e3a8bf8fbab8bf1a795c88ee1c2f77192f847c8f298fbcec638a7a350bd42aecd5ef73b1b0b50265a876e547bed9a05c1700942c9b807ce2c5ae3e95737808b61b58fac65f195d1f069873c531489724956f609711d66094d3d2c72cdf5efc1f360f628c1a8f97b54fdf5f5108c85f79903c2241dcdf0842c968e36bf4d789daf61fd396c3d54456f647adbb109e0c43fbb06fb024cda87e0f37b464af8cf13a183310ec1d1f6087e953f49844de300e648a27179883b7c501583b3d0e513d6d439973bddb33e0e3b007906013267b6fe9d1f0fa0126f617a6fe4e174bcba547c90f742c89733ce2ec05e7984d54d66", + "c1", + "9c", + "0d", + "2a", + "7c", + "91", + "aa", + "4f", + "662fc50f127126613caf6257b6de76b5b170adc401f839d9fecee391796e2ed9750268e7794fd8c9ff62feaea6555b184bb5ffc5fd65e3df0f24851cbaf2e99d52505e07bb7111b5d100f27fa959f3b22b2d347f0061034e068ad7620ece8ed1e84ea37a463805e08e98d82919926b8abf0a7c42110aff66a06732c56b3f0f5b211974728b92fb1123f4d3842007f8cdbd92b4a5769ca2d659a87e8819fa26c96864cd4025ba31b3d0b233adb443e3e68a38e7121c5e965a922c0cc60db9397a44dbc52a4345af4a6246adadc12e2ef62049cadd63825a0b06679466ad5126196811f75238df05bfd0fe044a35b9a574e08f427e1c3426ba50979322355ea99b53a3a63d08e9459fbafd7779accc397bd2f8f6896d65b3e67c2e90ad4111a9197e8964ceb4189096fc918b01d352c089c0bd88f1ff786e82469181a8ef6110a4495302706404d82f88b0411c9c4cd55742bd1393ecd5b01af14281ec0dce1b02cc36c9a7265e6c3d71d0feb76fe61e21106102095774b2cf6cf7de4bdd3577a4e8e7bd3562d8a0885301d26dd0a966f6538d164465dd288c596424c840ba01b9da33fca917fd779cd647422b12c11d32a4bec8c9d0b55b2edcb7d57ffb898ae03a315f3307a1162e27fc710eeb4b3a13f208d10f6cf1121d5ef66d6ff5f86982a3d4c2255fbadf8bb5843cf6a0577d8bb218c07c79ece13d9ad25d221f800a411848c2109474170feb7e536b948931b39d71218302c5f8aa686a19b6534e4d5a2afe85d59b6a93975545884a38af45632e2608b5422e63a51ea21aeaa91964192f2457933a4d8573325e5a89e648c8acf3e61d50e4c067e6c20e2e34bfcec76195e19b53c8645d00c42173bc1bf23955eb254af5b57805784f366ac1fe00532bc7b95f87076e8e91ea5a76c13e006718aa7a43eb4ad2a08adadbf28c332b852f609ab816709e371111e24fc1d3a738481da00a3b546742585d30b453f90550bdb2a565f427f49ddbb0bfcc8f681efe71434b0a1899ae3c488c8c6e0b56251a70741c9d3089fa1b1e53ded1874b924485f9a28082ab5b0f0b00394cad3b4f4db6bc259686142a01bc53bc52abf2a4d437a1fced2b9d74fe4adb25f6f93f8ea3f91439a592dc1ff6d12e77cbf239044c1c6a66a650f3c0568de0007d80bccc839b51e513fc1ae1c3ede11f56438518fc2ca3eb0f1dc67312bc4111e2e8d5bd6c785bed7f7b73985f6d985a2f84b3db09690eb58b38a88ee197e6a82aa2b0b5bdab31a1957ca1ae8abe83f1fde947809b092b423eb88491cb094bb6df44008b2a0ceca229236335cb42cf6b26edbf31e722d0c155a2bf5a13004d34068cba9cdbbfea0c7dc00f3ac00905b0286c694b6f3f806b771731a66412f87c8b91fae380ee2f50e0e967c1782efd21800b56e4fd6fee549a9332fe41f7cb8a38e5d665d1bbc9d158feea58aa9a24c0ffc3525995d12e14e5ad50793a9bc97b45005fecad7c7f9638d01ede58af4edf3f4a3f7e63b66fb8fc3c08b19d2edf37e733a07ec508e35f6b427f3c81d5953307764a12e0210bd17371222bc139d83728b5b8393e0510648bfeaf2682e265ab6cc0408f8093b5837e8924a132425d68bd993fd2ccf80e3ab87a77ba8ae63986b450f3d27367c603df48f2e2212758a86e15326dcb7e6e31137e36b06dc6fb986ebd256d9eb27cb42ccd549b7e24b9b0f21961a9883a0d00793a5fe5c2358d07dbe8310bdf007e15ab53e7af00602c4e2064fabd4ea6f6a60cf89aa20060b9bff90a130914949f5fc463f5d5770f210815700fddbf932f393de21c80", + "abba3f6eb6cb40b953e5600eb1c275cf54bd6f90da6d6e66fe4f7113fb814b09b7334297070416b15082bfbdd6f81bf0737e0ca1436f64a4016fed83498901eef928eb47bd34934c414ec5b5b47a77801b46d29f630e0a690a3a7cef9e1cac40a774319031b51b1041c67757024d479112d83dc82a8a939857b81c48c74bbaab654215cfc3df257d6bbbc2ab7257e8ec6e237cc197c047f5324e0de2fbfbe329ebf1061e597be1cad6fbb0edfb6c66cfeeb9eb105ca22f3e36a104866feeae3ce54048010e5bee844a20550907790940f836d17818a1471b05a061c17c42651ff2460313184cf56fa04f7fb88e691d8fe9acd500a5e692f8a8d6a5b74c69614d10c6d84a6514105c5dcf4f90cac9ec4f953e701bc39713fb0cc3a0d9afece5d3d164cc3ddbefa0f896c12720c1742cb8c24eeda95e0047fcc9918797793057fe808e45558a291c3add1e35cdc44800e425509b7a7edd00158b408830cdb51766815a639893169c5139723e14f1de3c2ef8575dd125c8b5b703c8016970f9aa84ae6901b853f0974efc74b720edd4cbb8b24a8017f57cdefaab93ffea20ee0bae25909cc6d187564eb3355ac43138640d1933bf01b3e603171c72ef5f8cf831b251e14483c3d850c5328feea7f5055a40ee7bceb5fff8a8bdea85ee70507270129b40558fa267192318ef0121e66592c7080ca1fef8b6c59af108e0817ec3e3ffa6a102ae0f909c09ac7c49800e380ce01a939d00f764c5d1ee1f0395d59f5cc61f86ca66613b4dfabbdc984d8bdf718618a039e6affaaa6c48a8485bb29ecc77d167e7a53bb1370c6f8a7961f5474a9c2c3c2a87451213079806e0b9075d0e8140f708c5e9db72a765579b41807ac582d0eb35b01c608dda14b1ea1f7a1fa468a402686f08ef4883ad25342f32538a3b41b50611beec8f8d811aaa20640f609e5bf7e464599332be7560c405bef3390a000ea30e0d265fcb47077917ac69619a77099c4d1a93f416bbaa9b4835d00f45de8e36c4de3702c80807a609cf0fd306c00924bc0f43e9befac4da1a3909c2e254fd5f4caffcd501ae333c7e01d3c88b6af65f0e57cc56eb65506c2450181760aacaa8f71693b229bf481910eb141e6126e0237fc4556eb4ab1b8bfd01d8bd1213771a97a70ee568d860b7fed3dff6e11efab2fc91f1d72098a542f0f74e2e16ac623ea87df34ec8c1fa8362ec4d23f5d7bd91d716b635d23f93749868ca0bc2eae4b98a6fcfa7065cd077af9383569a80d3805925781c60390a2c27243fd8cbe0f714f4de48722db06bf205faa7de21434beb6c15d451d9048e78a42f42326a6d1e416e5ffa4fa1ea6733702450472f2917ab93f3cfff03ff08fc776b8d74ed0c76a199b9654caf1d66416ac1c355997bc7c32c7fb14b985a022d232e73f1c56cbd0d6168ce6f3da5da2cef0d8a801fa12c55b6f36f4249b1abf11475b417e1cc5bba85cc0a54aabb6b9dd228490b6731e6d332ce2216dad7d63228e4960c9113415e829286722c015ef94084910c35c0b0b74ec3404c1699a2770244ffca2390fb8beb8f7f5cacb31237d041d133d3bc2b56b87d96ae7a0336fed62190220a029d3e8c37254700c49cd52e3b0f25a6cd7d00c8a68ba11be731c4d8f9d7999f596be9e6061c3fd37922c8fe4370d5c63561c033233b4d5ddd0c0a38f57cb84e509638c581d709e89eb8182eae341b98ebdf8d67f927b30c75b10bcda88f6d7237df63609540e77e2ddcf762390b0047d3a12867c1b202b2bba05b5c5ba2ba09ae5ebde6b774be14b1301de9118f1e7e7e4e018c448717ec1bb93cee6f815daf053eacc85cbfcd1641c657a9caeaf8d34d0740d81083c709caf8d5d2199ef9b9fb88c41229e89f2699c7be2cce9946f23bf07e53310272e5f0affc576afdd3a00162c922396725701a5613d7ba39e84c805464a45027d720bbbb30b0158719f47d580f1c", + "9d48a19421d0625ecc0367db8dfd71f08a0267eb85f2b9dde09aa9fcc83fac8333d9424d1e84df85cceb23d12d15eda211bda622613adedc11b4d0d4305b3fb8cfd34c658cac936c8c7e4bf207af7e61eeffa8ccf27918963219872f0254aa67a7c8a3a57de9e4a902e6a3e424f36a6a0c575eadf8a1c43c4d38e9e2720c669b2f3a83461944a23982e60c8bc74f9097735ca412ba2d970240d2925c6e44fd40d8256fbf53c97fb352fe582c93beb3eb95065badcee25180bc35dea1e476e478e6930cb1052c2eac7a9d36d15db7ded19c96bdac27fdf53e5ccfbf33cd3ed3a997a9a86e0975f2f54176715e73b15df5d917d0ecc8f403f2f644bf86aa6144b406465cfccfab5166a49797df4dad80f96dfb04bdfca7e7390fd07e9391a97de0526ce76c8bf51be4beff0b8d1acb0091fc23524ecd7891b40797100eae85c361ff6a35472ccde96369b021c854cb7a05639a370a3daad38bf081fe7452bc30f3d3962714235ec6dcb237fee51020e96cafb69f3fb22f00c9c8323aa0ebe75eee1bb82bcf895429e50c38a66b825235e0b608487e5fe3a8db419f1b637ad445b285e913d5eca7003c9b8ba22df7c85005734e2562bc5c30ba232f11107b591d3498fc57fb05205c7679538aa33cee0adfe2adcf85df353039f601dc231eb297d29b3966ef7ccf7735199c5c17209da17911720a63da3ff0d2577ea76073c00892c9156ae4817f1199535c38f030d95ac494c075b26a373981d60a0f350bc0651030675d311b2e9d07e3fb2557bbdf528b78cfcd8bc654a2447702f22ea102dcfacf0acdf723ba0ef01f041ab1a6404ca52cb217eaa985c1742c87e6884532dcb2ab2780bff86ff519141ff4ea0cfaf9bc20aebd8f0278f5094bcf989369190a0a6d0982f344d2caa0c51813e6409826f39567cf37309fc3164703f1a063225ebc8b0976a2574aec4c7ca68e5b969f1372ecc18a5e34d13aba15b5a0cc98cf05d00a9858acaff41a402b806846002efa413ad65a8b2da7afe15f601f57a4ca5c24ed8167d9836e17335c6bf2385cc1cd2856b2b05598120716a25b35650ae8e67f9e8bb09dd3a98e2b50ecda2bff00cc1e18a369712521666fe15f788527eb3fbf0c686723b130004296096c20a60d8870de523f5153ea55cc836be9bd02fc3a1d463aea606ac07698bde4bf2516181e6eb5f52231a0776ba988e6edc1f1113a761500016e4c568459a4b9631ac84b9056d8645d84ce94b28dda7067badfe106208fb3e79afe9abcc581253841bead7707bb027c33254acaea1f4ebad0a641b59f7e11a0d3e61e1e07e2ae485db1c58680264d4824891aecde296640e2d1db0675100f9c4c3c3cafe757dde482eb1f177acdff3a9bb1e2d0d6dcda4be4112bceaacc6a08a705cf0ffd7e8dbb1ddfcd05f314390267c8acdcb1d58069dc7de6025ca8ef8890b494311ad94c4f0e1003c43e644d076ef29e54384f2e3eb5c3d37cfa05bf3662dec8ad351ec8328c56f9ebf27bc1810781ae2c2905202261eef3151839e0cf9476f7dd08987e9aa54e9377801a4c8d5beb8b769cd26153bf812da29149c467fa42113dc63739d07712121260b41ed036d3c6646c84f0548e910e3b644ff94a8d02eb56326ccfb79873c71bea3fc48f84a0dd8f308487b693157f9ea7ca5f1a0e6d110724b5e0d598d7dc33948ab04719d9045faed588ad91de926fba668fcff3e05feffc05aca17f8c4fbc72b0f041717f6dd6738d06f4e0051b059dbe22e067700fd495720e6034eca751a7c2592913a96f6af40868980904c1da77b5bbd07460db6f297f81bd2397bd1be6f7fce55b2e30d7e9e6978ebbe6cdb407da461adefa3db6a1b6054280e55dc091576e3b46fdd588f59f47cb305503d04ac28ccba0bfcbe0a29d134152dba768fa8bed81f9971752cf7f7668102ca6cf5af38f0bd1cd9500f9faff1cf3e9590b32be41d37c", + "5fdc0d73676e7bde1949", + "e7", + "06", + "e8", + "b1", + "4d", + "70", + "2c", + "72fc070d8f9641ada566e6d2a8f85d0895e867d8d922ba29dac6ecef0fe4dd1a44c77b71736b85bc7a84d22c701838e8fae6ade75a46b4affcb0b6ca83f36772d7a82f3b40e991f6f35c519b9fcb22b2f44139d4665401d70cfc54f7afcbdc2c00b9ace6dd06af005ec3e6d6cb580af5aa1ae84d234976ffcd3eab91f4352c4ce5e1b7a0a535549a991ee4040072a4d895bd62e5028c60cb6b0301aa6572af7232cebfa4a6ff106e452f65f825478533d600f44d81128dd6b2d0f581776a92af8323480d780daed5a8d199066a99805798097015aa1a0a2731aa1d262eb516f6094af1d0fe350ae7aef2e033677665c5a802dd5ac362ad60a588b7a99d4181f5e2be844bc32315031d3c35597e9b3f7f0077f234c216fb74cfee1c0128fa5608c1175399d92d328188310171e6bfc2f3b60eff5b9e2ce9ccd71badb2530e68f0c0cff1cac94f28ac408f6de557fdc26c2fe2c8bbb07d07d03a336ebfb7eb159987de7d222176c41c494e50f7ebbe166a4692dc5b15e41d2fbe0bcf4be6023f09c61f78e06cfb35a915e2854b6a1e3d707f3dcfc92254ebf67dfdf546a1a0df564033f68fcd18ad6ffe81923b5f8c02141fdea52a5831d1db74f600c372030a88fa1d70ec2941156c05a9c201f8af9a93dd2f464e875e05cfc40051c1b9f14612bedefd655c4006c07e5f9287a3c29d3ef603b5816eef581e80c093098b683fee38753f8015808f9e909c9b5e29e07a9208e731ec8f15a01628775926e3140435e5fb43adc2eddf96d96b238b3b924efb06e581c25ee99c4ebd828b50fdb0843dd9d28337e8e305566985d65c98b14a9db8cb8c1aaddc01871140d697760232e36e776b2c78d179183e", + "e2", + "93", + "9d", + "b1", + "b5", + "7e", + "10", + "3f", + "d9", + "6b", + "61", + "58", + "02", + "54", + "5f", + "dada476e0ceb562cbbdb91789805d0520ee65913a2df71ec69d37dcf0967a4ad650ae5ac99e91b1a7e0a62c17fab5712f857bb2cd304097e765c36dffdfa8a817e26fb2163b2128f031e29c156a039528903bbab75baaba653cfe1008d935442e62044e80548a19d6fee60f36a9f22e99b878985591839a815229caca27050addc815bd5a24c17bbaa8af3d00cc8293c2132562391dc7b0228f57db048a4e0352424d1a35404f04fcfc0d0fb828139ed90248f88184486abf8c4f1cdfeb0d139bc0e12dcc5dee8175b7e25f12e3bc69fa33d4411119c92b680de6bad9cf75a2f681542fcfc141d5267802ef4f2f1b6f200d893ab1756604aeb09b9c0be78528081bfcc3737de3c454362794d240e1e4fdecd0e28e71ff1dada93b28c76f2e00be08383634813c5d930dac179752e4288d79bfb79c7abc978c0d67d0b772770ac6afaf4e3843e82d10a5931729aa6ef4f84fd759cc31575d6bb43b05f4dd6104239a791be564e361f253b83d2332b056b866b029c13e88398960b5728a917a61810eae0144c1610d445585492f9b6140ffa82d6343c5db61fa8638d762f87f6e95faf8035ef1ecb8b017d31c798b610f0dae7b02686059a819e1a86ce5a20abcd039f58df821a27e901bd882e4bda40b25859d871ee87da5aaa4fcad17de128d0137edf442a86e729f60fbe501fa0f9fdcb5bd991734fae404f3a5476014593056c210878f80448a2160b285a60970af3b7afe37f9a10775903364782761a87fa4dd025004de1b2565fd6d29d7ac1b784e2d31ff2f3c791777ffefaba1355f264dbbdf8f3f6b9468914bc14b50bc234cbf48b5cf522f653202453ac283bfc26e277037c9cac81fba416d380e612ba168f0e267f0ff0e371f89dc8b442a480bd031db4c0b3ab85c2b52b313e7999822cd0c40d55fa321caea9ebc99180b6e5b99e7bd2d58b4643c41be48b19df165b8f6b0c521af72c9f13d8e4e511cde7eb94f132e6875237842267e42f947272c6d30e3c20c0470fdaf033d0f600ecfef8a6d8586d8b645a0022407719b4e42e7b702476971ce5a08097b1543ba0b8020fb60adcff9bb1c1fad4c194bbd49bd514a76a00529491800c13a8e548ef9f2bd2d141b4be1edcbf5c5bb9a6b7b6833bf1ef2b2443e0d42c0907d52d3203569f3ba41a7304ee78d0fb24c42abe9775ac6138a7b02abaf42225b0bb7ba85889d888970223a924dfb01d70c70d4a858c136e6f1e441cff0df1215a1746a85c8783c6dbf278fc18dd718e264028b1bf2a79bdca2b71807963578fe5bdf33b692a1d941e6619df650a49b9a450c5d40e11c01935a9da330cfa1d42cd9c50c3376220283871b73cf69d0d9bc9b47d4f162b4392e0f33b703dca8c0048e8e18d149e15959e1ee71febbc194280557894fbf36086bc860156b0b5c37cc776f3065045db8e363fe1836bbe03f8cd16bc32b311d9bd5d523ffad5b83d6b5d81a2001a4449f227e40ac83c98472f485578481d643e7dcb7e8955f9eee539959502b98851a165a41af1570d9a002f9be6cc9063b396a2ef920801a59f1a16f74d0f0e071a68bb07b9bfba2773b516ea6155049af24e7b01bf86c45eb462a56f58b40fbe7aaf20297a1169b2c0be047a1bbe6085f7d74596185001bcae00560f28e3888625c401407606707c2c614e2dc490babddb3a098b6ff0", + "8c79503d0768a200f01418ca04f2f4602d7e6e015b43e03f094ffd648a02fa1b2ab20485875d0a166ee0ca2e843f1d26d9310f833a5987fcb210b2d85ee1abe42113ac710cfb507e9602c4bcbadb1b978ba4751b584d991c2b7a0a14e1c962138f3edbfb0be7ccd5932e7c7b018ee1daf3874ba5722a0b1e23ed0e784563a624ce3cc3a31007485be0d5d25630555862a0d844425e3d785ffea7b1dc04a70c2d0726138d7561e58ce59bf5c63048ec095705503ea8a5a05a487eeab32edbc501763f380224cced039e03832fcca44f50c3ad1d40ef82c59620418bdeea007325e41e9f0f862c600ba5c407fc2a854278916630ca27f2d63d007a81c6583c770891f3b77c6e0fe413a68647a0251dc42efc00e374d1462f671853e6fb5bedf0daae0c0b74ade03b40b90c6838fbb13a318cd49e600e6e18c1ee81df0c42ddf73387620869939bb7838c3e8005314054342e130f27d9dc7aff67846f64205f608db487cf1a5f3a86dcd20e5604b00a6e923b4d8d122fe63d2fc1d957a8decd45a2855fb2b565e7200cc009c6c4438f7fca406d28f86e8853f7410746885568037a421110d3ff16034abfb561520a5a3d4580ad65c0efe2c052077580f7e66dc5c77236e9a30641b625cdced6c4cbc3e7fcbe8682a7161c347603477b82cd25c1e8c7c6150bb46c27fb6597bd86905703a1185b264261cd075ef98b32eccbe1d368f35cae0cf63043618f6477c28249effc7fade64c7a5d55b333fc5fee9452e8bb923200838de9311830520de80da66f0dd2fdef59be2545ca20b3a4a43ad29eeeed639b0fd67a9ff749e1bb25a257f625a64cdc7fbc4a24cfbcd5d24f7240a1906d244151168902ee447daaed9ace80817bbd0a53b7d75e4f3dc5ace79b5a50435095f7b9a784ca4ff206d70eea8e55c2e47ee7e0c92f9b556c4b80dc3dee59a8b804aad0376d7dfded470109812ed36d29c9879e2ad6d794fcf4dbacbc4ea4e01102de4f77bb1ab29c2ff7bfbb9832f23e22e33382604f334dedddcd37b6cecfea4ac3b1b0d3757d5fee1a1587de10ec0fb6b1570131ee5b4f15eb3a97c6703897dd282ec5ae663a50119377295941091a8045b6833a0ee1e81ede4debcb8ee5d3f3f66094a18e96566cb4ea90506782f7f485c07761ee8d1ea2990a4d9092952f1f506a658c299d5ffd0e6623a5ab6ed83ee65fc1ad352fb791429756079835115c1e3c5266a7b929887794f07a55becaebd77a454db588c59a7e66ae540cf86e5d7ebb8cdf75f53f7a36ff3d73fc1f76792e71a0bc2e0cd60e80ad09e16e61cd17d70217743d08e87bcae8f1b926308015eca6496d307ff66a998ded28990f4423bf7e6121847970c386412de5a9d46d5d1a9dcfef7c1d383153d314f2945f5fe7ffe347fba48123722210a7ad00bcf1f7252a7bd05ef92a548903a20b3795c83d5234562ea045a9ee2e75c0d0948ad22e8abb03659dc5040dc646f27556170df427058fba7b17a0fcae3a76803c8ede60b866f9e7a101ec9b3ec4747fbf040832f28d2a67051fb0242c2e94c4de423807a88f145b21fde2440be687d0829de8742adcd66df4837472ce31a33ce26cd95e68ba689bdd86b6d1baa605dcc431f4849bc6115e96d641f4bb017b33a13d82cddb1fb9b41cbe0763f3ed5202b312272250339b514c2578d658d2b8cc976c8f4f1d1a9fd389fad9eca227cccc50b56798762179b9c0186efbaea2120f394991efa26074f03af96e418218a0387304f986c734bf3837a4be4905eeac18ce208467af8b88d863a3a70e8be0eacbb20c269977d4a649f626a65df8d20c01e8fca1943bb9d8d0febd3a70dd4794b0184c0c5fea0e317591f8fd8e456199d304334eb7cd27e15fa003db6b0c0601f99c3eaeb0e5b0397ebe0cf4a6899e13864e6681d5004a35eb69b5e8b779b5f599eb37134ec5ea155bd921e910d75feb988d1017d95758", + "db692d4a337d1c9586621e432f439990e6e976e1d91ac55d02db3f68f7b185640d1479016aa8c851ecda8850e7663c3ed8fc93e5c4adda1e7832703bf9a9f582f9bc653aafba933deec556e73862c1bd7c4d7d637f7c257443a8e6240bbc05494f8005d2c10d6a1dc7853897760ff63317b67ef8b11c0179433dbaa9355c468a3cb6193a5c0a8fe50a8492a9f74136b393eca176cf7639bf175f7283b5d76830a5eb091ea2911d67e6ea91004197d2360b9be2ae849a85ce66dfe71421e842b3b048d172b57e439b76aab415444114de77aa21c2820daed50a1e60dd1e69b9b0a6176effd61d49530eaeb7644fcbb888338867db238d80b988658dbff6a748fb51b0218e83ad9ec0da27030f9e82a3e0178e41514f6917afb6c82763cf4a20da949c5d77be6561dd7651978f17de9e01e124e8c9ad1b82115b8160094e4c57f0679d5b0dc9f704e296e475d2781523261477e880bb4453ba9d7a04a93169df19a6bf39ea2a48c9e8dccfc56f9d828142e4fbc8811d8d0fab0df3631321d2e2e1b51b05589b1096dac6263051972fa9f08e53a2547954ca96d752859d0260de040620050f28349ebc94b4627c71cbbd8aee7018bbe029b1f0103c411a90b1f10a33c3618061c04ae203780731079d8802a889e27ba734f2c3f9b08033b98945dfbf6eb16dc38339c4fc595a2f3b348f30259f491c164b41960ecfa12143ba7983669145c83a9b361165034e97dde00370284798b885f62c121d21b1d50b864b6ce91040d5c012328e9a30b33c7027b8d4065fb3cce8e686a7731c1ad2fea8fef3f31adc08da99a7b2f5d22c4e5720ac59fa4d895b565f56af1ec35ce1d0af9c88d7044499edd3eb4ba476120d30cad2e43226143c83b95d8b28df3ee7c9eb1b49ae36eaab6293aeeb1bb22b235121f424d4fd8128958844a1d7e761b1f845e514afe48d2a6888000f307ced956da39b845ab4c45b3206dc11c611377f5c52942306843d4902f075dabc58dbd2f4375de31980b98c880f746de318d8132e3764cabc0a1b20dc486a1ef8e14728a149f3dc48fae67a3782a88edbf4ede37b3728d30aa3ff3b93018f85f498fbe7dfc00c783deb4f31f61a750da9cef70e87e4aac2ccc677b0bb97b7fbd638e0ad8918cbbd1164781e09d8b21af1515b181cfe253413b60aa4782356903dbc00ae5daef0bb29980841b78301fb017e1be08efe5d7f805b312ce19e0beeebaad17de26506dc4250e7b33f95fb0c7b81a1333f792e40fa7e85a370f848e024b8bf2d4b568c356d238f85a6e20c4cde15b908fbe06c2d427647583329c5e280c13aa2a13677b38f05930031c83e703a44836b84c1a90377632f0b9a100ae5f08480c430cea97a17ec3c25c2456a2b88c11fa6fa293d01a1ea0f054fd818fbba5eabd0d3776b551bb4f2b5ce5c1fcaabcf279c84680c9c09057bd7e91a5629a10789262d435ffb6e520a55e559d9bd6098d82f10d9c47a8691add179efe5433f6871298f173ae81fa4b105620d2d682f6ac9a93129ecc7d9fdd7896088757e2565c58b9d3c321f402c5a8f71fcd0137c4a45d517b524c6651529aa5a7ab33ad3db0635c6df06420748027c8c11deee1c8a9d4fb4da3befb36642005cd87506fc67d84d528ec1a8b42ba75f4d9e73dfd8ee869ce5c3d2a4318f58998132669b8183cbb70660ef4279cd274b6a231e6aee1cf08ab899e55ef1859ecd27fd9262d2821d127424a1073ab267b47cfbce65805c154453857cf3fa04fb62776f2053e6a30e905c35b2877a9743781154033b46f0d1104965e5fc919b57e8469d9eadc3b2514c2968006ba1e86b4b541b60327a78fa325850c4bf438fe13c548c40c74943e171b78d12fa49855cb01e89d3955e38e932b04a3a83ebe8b506e00dbc99ea2d2a6fbbebe9fc35edb0e22be036013d852e85cf6b53792357bfcbd39f69957ef7efb80776e1086677790c", + "1274ff92d809eb355afa15b7bf1a745388f7e541a8f835bc01cb118e8bbccefc18607bf9acf6777fe10f37b3a9cee996c71afb30483ed7e4f8bd8fb70ba42a8752a580bfba6ec702f1e17114d0186fa43042", + "a2", + "1e", + "d7", + "2e", + "f1", + "13", + "12", + "e9", + "e0", + "6d", + "16", + "b9", + "76", + "dd", + "a2fac73d3c5ff0f773902ef220afc4e857cb3015e1c3c2134a46fcd6853e432c8d2e997a37bb03b7d179301646f07df3d524791c1eb096da20a18a372edc57c31c9bdd20378c82506e31ca775e850b2c381ef28d55e1b1641c861cdec6875f4e254409351284b798056093f6bd7209d751e9b90599beefb9e38d4aa763d5d7f46cd5ac3680fd28dd35d2bb58d25045e3086f2a0557e1527483069d3c70e301f0037c8a56a3a0c18cf9a5cbf60d347a0630ed2cb423856f3f75f12b496c3f9854012771fa73bb63dce4834c29673c0b01f14b7c433328b56ce4fa8001686c068986cebe3b1025588da647dc946006c4eb9cb53c04d09f46abfdcb0ccf71f5c3b78727eeea2ff2a9e8cf298d21386070ab4d476c00fcd96770d7a26b7f8d9327fe9b7dae7e42e47a833f9751ab465ca10cf034f499f7fde4deca76b8db9e45a7a3cf7b7782c740fcc2cc649d44401ac8f0645e070bcea7c81bdfcfc57ab26ff7801b72c7e3dbefba8ab28650e1739970c9f34784f090e187be3d88717a2c635d1044120f73eb0f3e5457d6dc43a330d458354c433ca90af33982a2036c189681f268ae24e64d866db560f34a73adeee630d8f7c7ab22ccf2aea5fe652a7621abe3cbc58e2fef38305fea5593c5c772151731f1dd7d7eae75f30ae4fbb5bcbb3d2cd5f52d25872629e977f2d9be486a9ed939930b017ac12eeac897cc1da9a011182830507f27c2833f75cb48d0fb428ba65b870f91d7ae8bfd003c4cc24daf69d353a91e44f7449bd11e4149415c38840df19c6991d3ad95e2350b47565a277e67839d6dd7473ebea398212f6ee33aca13229b137965a4eaf9b8a5033cd9e10a8a92e9310d349825c09c39af13145f14f644422885c936161fd8c7ca1a0e5d443682b9fbc13e55352896625b921cd7f4cf278d68821ebb27b3845ff80ecdf0941bb621f762281dfd9cd7f40acdd2164851d65d4c24c232aa5d872f725fcc306d83a18a0b9668df084ada23a278eb089083f3acc8ccf83234ba79b074badd3408ba5747e36d5dbe64ef153a72d117125d04fe6bc603f8c458e3f0c45dce75e743027f13fb9a2c160ed96dc54ca0502280efe2f26638725e3d2b976ef3473d969ef11a34d28d298ce637b06c9c273ba4505adac8e0d9e88273717d5bb726e6d3e9f32c7d4f4dfefaae5636b7d1920cc1d190697c2952cbc8d22dbde0b81ea08ad43bc24dec2cf51293efbe59bd07b4ca6110bf8e125f6d3ce38253fb12a7ae098336b640f4cd6634ecfb67e55d3332c8b555b24bdb1efa6953fdc861990e49ebe2b11ae80d2cf1e7ebfe17fc2b8d6883a319c19bb27495e75f7fd17dfad643a32faffbfd3ffff8f31f7ffb235ba7188a22dd1f7fc7fe03c3d8bfe4efd052811a7b57ea7157ae2020078ff9f4c79f7ffe17d3f7f8374d5e0000" + ], + "rawHeaders": [ + "Server", + "nginx/1.19.5", + "Date", + "Sat, 05 Dec 2020 05:54:48 GMT", + "Content-Type", + "application/json", + "Vary", + "Accept, Cookie, Origin", + "Allow", + "GET, HEAD, OPTIONS", + "X-Frame-Options", + "DENY", + "X-Content-Type-Options", + "nosniff", + "Referrer-Policy", + "same-origin", + "Content-Encoding", + "gzip", + "Via", + "1.1 google", + "Alt-Svc", + "clear", + "Connection", + "close", + "Transfer-Encoding", + "chunked" + ], + "responseIsBinary": false + } +] diff --git a/src/codecs/gdoc/__fixtures__/test-fixture-2.gdoc b/src/codecs/gdoc/__fixtures__/test-fixture-2.gdoc new file mode 100644 index 000000000..08b3e2f0e --- /dev/null +++ b/src/codecs/gdoc/__fixtures__/test-fixture-2.gdoc @@ -0,0 +1,2556 @@ +{ + "title": "test-fixture-2.gdoc", + "body": { + "content": [ + { + "endIndex": 1, + "sectionBreak": { + "sectionStyle": { + "columnSeparatorStyle": "NONE", + "contentDirection": "LEFT_TO_RIGHT", + "sectionType": "CONTINUOUS" + } + } + }, + { + "startIndex": 1, + "endIndex": 40, + "paragraph": { + "elements": [ + { + "startIndex": 1, + "endIndex": 40, + "textRun": { + "content": "A Google Doc test fixture for Stencila\n", + "textStyle": {} + } + } + ], + "paragraphStyle": { + "headingId": "h.h8ulruuqfefr", + "namedStyleType": "TITLE", + "direction": "LEFT_TO_RIGHT" + } + } + }, + { + "startIndex": 40, + "endIndex": 41, + "paragraph": { + "elements": [ + { + "startIndex": 40, + "endIndex": 41, + "textRun": { + "content": "\n", + "textStyle": {} + } + } + ], + "paragraphStyle": { + "namedStyleType": "NORMAL_TEXT", + "direction": "LEFT_TO_RIGHT" + } + } + }, + { + "startIndex": 41, + "endIndex": 57, + "paragraph": { + "elements": [ + { + "startIndex": 41, + "endIndex": 55, + "textRun": { + "content": "Nokome Bentley", + "textStyle": {} + } + }, + { + "startIndex": 55, + "endIndex": 57, + "textRun": { + "content": "1\n", + "textStyle": { + "baselineOffset": "SUPERSCRIPT" + } + } + } + ], + "paragraphStyle": { + "namedStyleType": "NORMAL_TEXT", + "direction": "LEFT_TO_RIGHT" + } + } + }, + { + "startIndex": 57, + "endIndex": 92, + "paragraph": { + "elements": [ + { + "startIndex": 57, + "endIndex": 60, + "textRun": { + "content": "1. ", + "textStyle": {} + } + }, + { + "startIndex": 60, + "endIndex": 92, + "textRun": { + "content": "Stencila, Kaikoura, New Zealand\n", + "textStyle": {} + } + } + ], + "paragraphStyle": { + "namedStyleType": "NORMAL_TEXT", + "direction": "LEFT_TO_RIGHT" + } + } + }, + { + "startIndex": 92, + "endIndex": 93, + "paragraph": { + "elements": [ + { + "startIndex": 92, + "endIndex": 93, + "textRun": { + "content": "\n", + "textStyle": {} + } + } + ], + "paragraphStyle": { + "namedStyleType": "NORMAL_TEXT", + "direction": "LEFT_TO_RIGHT" + } + } + }, + { + "startIndex": 93, + "endIndex": 102, + "paragraph": { + "elements": [ + { + "startIndex": 93, + "endIndex": 102, + "textRun": { + "content": "Abstract\n", + "textStyle": { + "bold": true + } + } + } + ], + "paragraphStyle": { + "namedStyleType": "NORMAL_TEXT", + "direction": "LEFT_TO_RIGHT" + } + } + }, + { + "startIndex": 102, + "endIndex": 126, + "paragraph": { + "elements": [ + { + "startIndex": 102, + "endIndex": 126, + "textRun": { + "content": "This is a test fixture…\n", + "textStyle": {} + } + } + ], + "paragraphStyle": { + "namedStyleType": "NORMAL_TEXT", + "direction": "LEFT_TO_RIGHT" + } + } + }, + { + "startIndex": 126, + "endIndex": 127, + "paragraph": { + "elements": [ + { + "startIndex": 126, + "endIndex": 127, + "textRun": { + "content": "\n", + "textStyle": {} + } + } + ], + "paragraphStyle": { + "namedStyleType": "NORMAL_TEXT", + "direction": "LEFT_TO_RIGHT" + } + } + }, + { + "startIndex": 127, + "endIndex": 134, + "paragraph": { + "elements": [ + { + "startIndex": 127, + "endIndex": 134, + "textRun": { + "content": "Tables\n", + "textStyle": {} + } + } + ], + "paragraphStyle": { + "headingId": "h.846ftud7saup", + "namedStyleType": "HEADING_1", + "direction": "LEFT_TO_RIGHT" + } + } + }, + { + "startIndex": 134, + "endIndex": 259, + "paragraph": { + "elements": [ + { + "startIndex": 134, + "endIndex": 143, + "textRun": { + "content": "Table 1. ", + "textStyle": { + "italic": true, + "foregroundColor": { + "color": { + "rgbColor": { + "red": 0.2901961, + "green": 0.2901961, + "blue": 0.2901961 + } + } + }, + "fontSize": { + "magnitude": 12, + "unit": "PT" + } + } + } + }, + { + "startIndex": 143, + "endIndex": 258, + "textRun": { + "content": "Italicized (or bolded) captions before or after a table should be decoded as table with caption (and label if any).", + "textStyle": { + "italic": true, + "foregroundColor": { + "color": { + "rgbColor": { + "red": 0.2, + "green": 0.2, + "blue": 0.2 + } + } + }, + "fontSize": { + "magnitude": 12, + "unit": "PT" + } + } + } + }, + { + "startIndex": 258, + "endIndex": 259, + "textRun": { + "content": "\n", + "textStyle": { + "foregroundColor": { + "color": { + "rgbColor": { + "red": 0.2, + "green": 0.2, + "blue": 0.2 + } + } + }, + "fontSize": { + "magnitude": 12, + "unit": "PT" + } + } + } + } + ], + "paragraphStyle": { + "namedStyleType": "NORMAL_TEXT", + "lineSpacing": 112.91667, + "direction": "LEFT_TO_RIGHT", + "spacingMode": "NEVER_COLLAPSE", + "spaceAbove": { + "magnitude": 28.35, + "unit": "PT" + }, + "spaceBelow": { + "magnitude": 14.15, + "unit": "PT" + }, + "keepWithNext": true + } + } + }, + { + "startIndex": 259, + "endIndex": 307, + "table": { + "rows": 3, + "columns": 3, + "tableRows": [ + { + "startIndex": 260, + "endIndex": 286, + "tableCells": [ + { + "startIndex": 261, + "endIndex": 270, + "content": [ + { + "startIndex": 262, + "endIndex": 270, + "paragraph": { + "elements": [ + { + "startIndex": 262, + "endIndex": 270, + "textRun": { + "content": "Species\n", + "textStyle": { + "foregroundColor": { + "color": { + "rgbColor": { + "red": 0.2, + "green": 0.2, + "blue": 0.2 + } + } + }, + "fontSize": { + "magnitude": 12, + "unit": "PT" + } + } + } + } + ], + "paragraphStyle": { + "namedStyleType": "NORMAL_TEXT", + "alignment": "START", + "lineSpacing": 100, + "direction": "LEFT_TO_RIGHT", + "spacingMode": "COLLAPSE_LISTS", + "spaceAbove": { + "unit": "PT" + }, + "spaceBelow": { + "unit": "PT" + }, + "borderBetween": { + "color": {}, + "width": { + "unit": "PT" + }, + "padding": { + "unit": "PT" + }, + "dashStyle": "SOLID" + }, + "borderTop": { + "color": {}, + "width": { + "unit": "PT" + }, + "padding": { + "unit": "PT" + }, + "dashStyle": "SOLID" + }, + "borderBottom": { + "color": {}, + "width": { + "unit": "PT" + }, + "padding": { + "unit": "PT" + }, + "dashStyle": "SOLID" + }, + "borderLeft": { + "color": {}, + "width": { + "unit": "PT" + }, + "padding": { + "unit": "PT" + }, + "dashStyle": "SOLID" + }, + "borderRight": { + "color": {}, + "width": { + "unit": "PT" + }, + "padding": { + "unit": "PT" + }, + "dashStyle": "SOLID" + }, + "indentFirstLine": { + "unit": "PT" + }, + "indentStart": { + "unit": "PT" + }, + "indentEnd": { + "unit": "PT" + }, + "keepLinesTogether": false, + "keepWithNext": false, + "avoidWidowAndOrphan": false, + "shading": { + "backgroundColor": {} + } + } + } + } + ], + "tableCellStyle": { + "rowSpan": 1, + "columnSpan": 1, + "backgroundColor": {}, + "paddingLeft": { + "magnitude": 5, + "unit": "PT" + }, + "paddingRight": { + "magnitude": 5, + "unit": "PT" + }, + "paddingTop": { + "magnitude": 5, + "unit": "PT" + }, + "paddingBottom": { + "magnitude": 5, + "unit": "PT" + }, + "contentAlignment": "TOP" + } + }, + { + "startIndex": 270, + "endIndex": 278, + "content": [ + { + "startIndex": 271, + "endIndex": 278, + "paragraph": { + "elements": [ + { + "startIndex": 271, + "endIndex": 278, + "textRun": { + "content": "Height\n", + "textStyle": { + "foregroundColor": { + "color": { + "rgbColor": { + "red": 0.2, + "green": 0.2, + "blue": 0.2 + } + } + }, + "fontSize": { + "magnitude": 12, + "unit": "PT" + } + } + } + } + ], + "paragraphStyle": { + "namedStyleType": "NORMAL_TEXT", + "alignment": "START", + "lineSpacing": 100, + "direction": "LEFT_TO_RIGHT", + "spacingMode": "COLLAPSE_LISTS", + "spaceAbove": { + "unit": "PT" + }, + "spaceBelow": { + "unit": "PT" + }, + "borderBetween": { + "color": {}, + "width": { + "unit": "PT" + }, + "padding": { + "unit": "PT" + }, + "dashStyle": "SOLID" + }, + "borderTop": { + "color": {}, + "width": { + "unit": "PT" + }, + "padding": { + "unit": "PT" + }, + "dashStyle": "SOLID" + }, + "borderBottom": { + "color": {}, + "width": { + "unit": "PT" + }, + "padding": { + "unit": "PT" + }, + "dashStyle": "SOLID" + }, + "borderLeft": { + "color": {}, + "width": { + "unit": "PT" + }, + "padding": { + "unit": "PT" + }, + "dashStyle": "SOLID" + }, + "borderRight": { + "color": {}, + "width": { + "unit": "PT" + }, + "padding": { + "unit": "PT" + }, + "dashStyle": "SOLID" + }, + "indentFirstLine": { + "unit": "PT" + }, + "indentStart": { + "unit": "PT" + }, + "indentEnd": { + "unit": "PT" + }, + "keepLinesTogether": false, + "keepWithNext": false, + "avoidWidowAndOrphan": false, + "shading": { + "backgroundColor": {} + } + } + } + } + ], + "tableCellStyle": { + "rowSpan": 1, + "columnSpan": 1, + "backgroundColor": {}, + "paddingLeft": { + "magnitude": 5, + "unit": "PT" + }, + "paddingRight": { + "magnitude": 5, + "unit": "PT" + }, + "paddingTop": { + "magnitude": 5, + "unit": "PT" + }, + "paddingBottom": { + "magnitude": 5, + "unit": "PT" + }, + "contentAlignment": "TOP" + } + }, + { + "startIndex": 278, + "endIndex": 286, + "content": [ + { + "startIndex": 279, + "endIndex": 286, + "paragraph": { + "elements": [ + { + "startIndex": 279, + "endIndex": 286, + "textRun": { + "content": "Weight\n", + "textStyle": { + "foregroundColor": { + "color": { + "rgbColor": { + "red": 0.2, + "green": 0.2, + "blue": 0.2 + } + } + }, + "fontSize": { + "magnitude": 12, + "unit": "PT" + } + } + } + } + ], + "paragraphStyle": { + "namedStyleType": "NORMAL_TEXT", + "alignment": "START", + "lineSpacing": 100, + "direction": "LEFT_TO_RIGHT", + "spacingMode": "COLLAPSE_LISTS", + "spaceAbove": { + "unit": "PT" + }, + "spaceBelow": { + "unit": "PT" + }, + "borderBetween": { + "color": {}, + "width": { + "unit": "PT" + }, + "padding": { + "unit": "PT" + }, + "dashStyle": "SOLID" + }, + "borderTop": { + "color": {}, + "width": { + "unit": "PT" + }, + "padding": { + "unit": "PT" + }, + "dashStyle": "SOLID" + }, + "borderBottom": { + "color": {}, + "width": { + "unit": "PT" + }, + "padding": { + "unit": "PT" + }, + "dashStyle": "SOLID" + }, + "borderLeft": { + "color": {}, + "width": { + "unit": "PT" + }, + "padding": { + "unit": "PT" + }, + "dashStyle": "SOLID" + }, + "borderRight": { + "color": {}, + "width": { + "unit": "PT" + }, + "padding": { + "unit": "PT" + }, + "dashStyle": "SOLID" + }, + "indentFirstLine": { + "unit": "PT" + }, + "indentStart": { + "unit": "PT" + }, + "indentEnd": { + "unit": "PT" + }, + "keepLinesTogether": false, + "keepWithNext": false, + "avoidWidowAndOrphan": false, + "shading": { + "backgroundColor": {} + } + } + } + } + ], + "tableCellStyle": { + "rowSpan": 1, + "columnSpan": 1, + "backgroundColor": {}, + "paddingLeft": { + "magnitude": 5, + "unit": "PT" + }, + "paddingRight": { + "magnitude": 5, + "unit": "PT" + }, + "paddingTop": { + "magnitude": 5, + "unit": "PT" + }, + "paddingBottom": { + "magnitude": 5, + "unit": "PT" + }, + "contentAlignment": "TOP" + } + } + ], + "tableRowStyle": { + "minRowHeight": { + "unit": "PT" + } + } + }, + { + "startIndex": 286, + "endIndex": 296, + "tableCells": [ + { + "startIndex": 287, + "endIndex": 290, + "content": [ + { + "startIndex": 288, + "endIndex": 290, + "paragraph": { + "elements": [ + { + "startIndex": 288, + "endIndex": 290, + "textRun": { + "content": "A\n", + "textStyle": { + "foregroundColor": { + "color": { + "rgbColor": { + "red": 0.2, + "green": 0.2, + "blue": 0.2 + } + } + }, + "fontSize": { + "magnitude": 12, + "unit": "PT" + } + } + } + } + ], + "paragraphStyle": { + "namedStyleType": "NORMAL_TEXT", + "alignment": "START", + "lineSpacing": 100, + "direction": "LEFT_TO_RIGHT", + "spacingMode": "COLLAPSE_LISTS", + "spaceAbove": { + "unit": "PT" + }, + "spaceBelow": { + "unit": "PT" + }, + "borderBetween": { + "color": {}, + "width": { + "unit": "PT" + }, + "padding": { + "unit": "PT" + }, + "dashStyle": "SOLID" + }, + "borderTop": { + "color": {}, + "width": { + "unit": "PT" + }, + "padding": { + "unit": "PT" + }, + "dashStyle": "SOLID" + }, + "borderBottom": { + "color": {}, + "width": { + "unit": "PT" + }, + "padding": { + "unit": "PT" + }, + "dashStyle": "SOLID" + }, + "borderLeft": { + "color": {}, + "width": { + "unit": "PT" + }, + "padding": { + "unit": "PT" + }, + "dashStyle": "SOLID" + }, + "borderRight": { + "color": {}, + "width": { + "unit": "PT" + }, + "padding": { + "unit": "PT" + }, + "dashStyle": "SOLID" + }, + "indentFirstLine": { + "unit": "PT" + }, + "indentStart": { + "unit": "PT" + }, + "indentEnd": { + "unit": "PT" + }, + "keepLinesTogether": false, + "keepWithNext": false, + "avoidWidowAndOrphan": false, + "shading": { + "backgroundColor": {} + } + } + } + } + ], + "tableCellStyle": { + "rowSpan": 1, + "columnSpan": 1, + "backgroundColor": {}, + "paddingLeft": { + "magnitude": 5, + "unit": "PT" + }, + "paddingRight": { + "magnitude": 5, + "unit": "PT" + }, + "paddingTop": { + "magnitude": 5, + "unit": "PT" + }, + "paddingBottom": { + "magnitude": 5, + "unit": "PT" + }, + "contentAlignment": "TOP" + } + }, + { + "startIndex": 290, + "endIndex": 293, + "content": [ + { + "startIndex": 291, + "endIndex": 293, + "paragraph": { + "elements": [ + { + "startIndex": 291, + "endIndex": 293, + "textRun": { + "content": "2\n", + "textStyle": { + "foregroundColor": { + "color": { + "rgbColor": { + "red": 0.2, + "green": 0.2, + "blue": 0.2 + } + } + }, + "fontSize": { + "magnitude": 12, + "unit": "PT" + } + } + } + } + ], + "paragraphStyle": { + "namedStyleType": "NORMAL_TEXT", + "alignment": "START", + "lineSpacing": 100, + "direction": "LEFT_TO_RIGHT", + "spacingMode": "COLLAPSE_LISTS", + "spaceAbove": { + "unit": "PT" + }, + "spaceBelow": { + "unit": "PT" + }, + "borderBetween": { + "color": {}, + "width": { + "unit": "PT" + }, + "padding": { + "unit": "PT" + }, + "dashStyle": "SOLID" + }, + "borderTop": { + "color": {}, + "width": { + "unit": "PT" + }, + "padding": { + "unit": "PT" + }, + "dashStyle": "SOLID" + }, + "borderBottom": { + "color": {}, + "width": { + "unit": "PT" + }, + "padding": { + "unit": "PT" + }, + "dashStyle": "SOLID" + }, + "borderLeft": { + "color": {}, + "width": { + "unit": "PT" + }, + "padding": { + "unit": "PT" + }, + "dashStyle": "SOLID" + }, + "borderRight": { + "color": {}, + "width": { + "unit": "PT" + }, + "padding": { + "unit": "PT" + }, + "dashStyle": "SOLID" + }, + "indentFirstLine": { + "unit": "PT" + }, + "indentStart": { + "unit": "PT" + }, + "indentEnd": { + "unit": "PT" + }, + "keepLinesTogether": false, + "keepWithNext": false, + "avoidWidowAndOrphan": false, + "shading": { + "backgroundColor": {} + } + } + } + } + ], + "tableCellStyle": { + "rowSpan": 1, + "columnSpan": 1, + "backgroundColor": {}, + "paddingLeft": { + "magnitude": 5, + "unit": "PT" + }, + "paddingRight": { + "magnitude": 5, + "unit": "PT" + }, + "paddingTop": { + "magnitude": 5, + "unit": "PT" + }, + "paddingBottom": { + "magnitude": 5, + "unit": "PT" + }, + "contentAlignment": "TOP" + } + }, + { + "startIndex": 293, + "endIndex": 296, + "content": [ + { + "startIndex": 294, + "endIndex": 296, + "paragraph": { + "elements": [ + { + "startIndex": 294, + "endIndex": 296, + "textRun": { + "content": "3\n", + "textStyle": { + "foregroundColor": { + "color": { + "rgbColor": { + "red": 0.2, + "green": 0.2, + "blue": 0.2 + } + } + }, + "fontSize": { + "magnitude": 12, + "unit": "PT" + } + } + } + } + ], + "paragraphStyle": { + "namedStyleType": "NORMAL_TEXT", + "alignment": "START", + "lineSpacing": 100, + "direction": "LEFT_TO_RIGHT", + "spacingMode": "COLLAPSE_LISTS", + "spaceAbove": { + "unit": "PT" + }, + "spaceBelow": { + "unit": "PT" + }, + "borderBetween": { + "color": {}, + "width": { + "unit": "PT" + }, + "padding": { + "unit": "PT" + }, + "dashStyle": "SOLID" + }, + "borderTop": { + "color": {}, + "width": { + "unit": "PT" + }, + "padding": { + "unit": "PT" + }, + "dashStyle": "SOLID" + }, + "borderBottom": { + "color": {}, + "width": { + "unit": "PT" + }, + "padding": { + "unit": "PT" + }, + "dashStyle": "SOLID" + }, + "borderLeft": { + "color": {}, + "width": { + "unit": "PT" + }, + "padding": { + "unit": "PT" + }, + "dashStyle": "SOLID" + }, + "borderRight": { + "color": {}, + "width": { + "unit": "PT" + }, + "padding": { + "unit": "PT" + }, + "dashStyle": "SOLID" + }, + "indentFirstLine": { + "unit": "PT" + }, + "indentStart": { + "unit": "PT" + }, + "indentEnd": { + "unit": "PT" + }, + "keepLinesTogether": false, + "keepWithNext": false, + "avoidWidowAndOrphan": false, + "shading": { + "backgroundColor": {} + } + } + } + } + ], + "tableCellStyle": { + "rowSpan": 1, + "columnSpan": 1, + "backgroundColor": {}, + "paddingLeft": { + "magnitude": 5, + "unit": "PT" + }, + "paddingRight": { + "magnitude": 5, + "unit": "PT" + }, + "paddingTop": { + "magnitude": 5, + "unit": "PT" + }, + "paddingBottom": { + "magnitude": 5, + "unit": "PT" + }, + "contentAlignment": "TOP" + } + } + ], + "tableRowStyle": { + "minRowHeight": { + "unit": "PT" + } + } + }, + { + "startIndex": 296, + "endIndex": 306, + "tableCells": [ + { + "startIndex": 297, + "endIndex": 300, + "content": [ + { + "startIndex": 298, + "endIndex": 300, + "paragraph": { + "elements": [ + { + "startIndex": 298, + "endIndex": 300, + "textRun": { + "content": "B\n", + "textStyle": { + "foregroundColor": { + "color": { + "rgbColor": { + "red": 0.2, + "green": 0.2, + "blue": 0.2 + } + } + }, + "fontSize": { + "magnitude": 12, + "unit": "PT" + } + } + } + } + ], + "paragraphStyle": { + "namedStyleType": "NORMAL_TEXT", + "alignment": "START", + "lineSpacing": 100, + "direction": "LEFT_TO_RIGHT", + "spacingMode": "COLLAPSE_LISTS", + "spaceAbove": { + "unit": "PT" + }, + "spaceBelow": { + "unit": "PT" + }, + "borderBetween": { + "color": {}, + "width": { + "unit": "PT" + }, + "padding": { + "unit": "PT" + }, + "dashStyle": "SOLID" + }, + "borderTop": { + "color": {}, + "width": { + "unit": "PT" + }, + "padding": { + "unit": "PT" + }, + "dashStyle": "SOLID" + }, + "borderBottom": { + "color": {}, + "width": { + "unit": "PT" + }, + "padding": { + "unit": "PT" + }, + "dashStyle": "SOLID" + }, + "borderLeft": { + "color": {}, + "width": { + "unit": "PT" + }, + "padding": { + "unit": "PT" + }, + "dashStyle": "SOLID" + }, + "borderRight": { + "color": {}, + "width": { + "unit": "PT" + }, + "padding": { + "unit": "PT" + }, + "dashStyle": "SOLID" + }, + "indentFirstLine": { + "unit": "PT" + }, + "indentStart": { + "unit": "PT" + }, + "indentEnd": { + "unit": "PT" + }, + "keepLinesTogether": false, + "keepWithNext": false, + "avoidWidowAndOrphan": false, + "shading": { + "backgroundColor": {} + } + } + } + } + ], + "tableCellStyle": { + "rowSpan": 1, + "columnSpan": 1, + "backgroundColor": {}, + "paddingLeft": { + "magnitude": 5, + "unit": "PT" + }, + "paddingRight": { + "magnitude": 5, + "unit": "PT" + }, + "paddingTop": { + "magnitude": 5, + "unit": "PT" + }, + "paddingBottom": { + "magnitude": 5, + "unit": "PT" + }, + "contentAlignment": "TOP" + } + }, + { + "startIndex": 300, + "endIndex": 303, + "content": [ + { + "startIndex": 301, + "endIndex": 303, + "paragraph": { + "elements": [ + { + "startIndex": 301, + "endIndex": 303, + "textRun": { + "content": "5\n", + "textStyle": { + "foregroundColor": { + "color": { + "rgbColor": { + "red": 0.2, + "green": 0.2, + "blue": 0.2 + } + } + }, + "fontSize": { + "magnitude": 12, + "unit": "PT" + } + } + } + } + ], + "paragraphStyle": { + "namedStyleType": "NORMAL_TEXT", + "alignment": "START", + "lineSpacing": 100, + "direction": "LEFT_TO_RIGHT", + "spacingMode": "COLLAPSE_LISTS", + "spaceAbove": { + "unit": "PT" + }, + "spaceBelow": { + "unit": "PT" + }, + "borderBetween": { + "color": {}, + "width": { + "unit": "PT" + }, + "padding": { + "unit": "PT" + }, + "dashStyle": "SOLID" + }, + "borderTop": { + "color": {}, + "width": { + "unit": "PT" + }, + "padding": { + "unit": "PT" + }, + "dashStyle": "SOLID" + }, + "borderBottom": { + "color": {}, + "width": { + "unit": "PT" + }, + "padding": { + "unit": "PT" + }, + "dashStyle": "SOLID" + }, + "borderLeft": { + "color": {}, + "width": { + "unit": "PT" + }, + "padding": { + "unit": "PT" + }, + "dashStyle": "SOLID" + }, + "borderRight": { + "color": {}, + "width": { + "unit": "PT" + }, + "padding": { + "unit": "PT" + }, + "dashStyle": "SOLID" + }, + "indentFirstLine": { + "unit": "PT" + }, + "indentStart": { + "unit": "PT" + }, + "indentEnd": { + "unit": "PT" + }, + "keepLinesTogether": false, + "keepWithNext": false, + "avoidWidowAndOrphan": false, + "shading": { + "backgroundColor": {} + } + } + } + } + ], + "tableCellStyle": { + "rowSpan": 1, + "columnSpan": 1, + "backgroundColor": {}, + "paddingLeft": { + "magnitude": 5, + "unit": "PT" + }, + "paddingRight": { + "magnitude": 5, + "unit": "PT" + }, + "paddingTop": { + "magnitude": 5, + "unit": "PT" + }, + "paddingBottom": { + "magnitude": 5, + "unit": "PT" + }, + "contentAlignment": "TOP" + } + }, + { + "startIndex": 303, + "endIndex": 306, + "content": [ + { + "startIndex": 304, + "endIndex": 306, + "paragraph": { + "elements": [ + { + "startIndex": 304, + "endIndex": 306, + "textRun": { + "content": "6\n", + "textStyle": { + "foregroundColor": { + "color": { + "rgbColor": { + "red": 0.2, + "green": 0.2, + "blue": 0.2 + } + } + }, + "fontSize": { + "magnitude": 12, + "unit": "PT" + } + } + } + } + ], + "paragraphStyle": { + "namedStyleType": "NORMAL_TEXT", + "alignment": "START", + "lineSpacing": 100, + "direction": "LEFT_TO_RIGHT", + "spacingMode": "COLLAPSE_LISTS", + "spaceAbove": { + "unit": "PT" + }, + "spaceBelow": { + "unit": "PT" + }, + "borderBetween": { + "color": {}, + "width": { + "unit": "PT" + }, + "padding": { + "unit": "PT" + }, + "dashStyle": "SOLID" + }, + "borderTop": { + "color": {}, + "width": { + "unit": "PT" + }, + "padding": { + "unit": "PT" + }, + "dashStyle": "SOLID" + }, + "borderBottom": { + "color": {}, + "width": { + "unit": "PT" + }, + "padding": { + "unit": "PT" + }, + "dashStyle": "SOLID" + }, + "borderLeft": { + "color": {}, + "width": { + "unit": "PT" + }, + "padding": { + "unit": "PT" + }, + "dashStyle": "SOLID" + }, + "borderRight": { + "color": {}, + "width": { + "unit": "PT" + }, + "padding": { + "unit": "PT" + }, + "dashStyle": "SOLID" + }, + "indentFirstLine": { + "unit": "PT" + }, + "indentStart": { + "unit": "PT" + }, + "indentEnd": { + "unit": "PT" + }, + "keepLinesTogether": false, + "keepWithNext": false, + "avoidWidowAndOrphan": false, + "shading": { + "backgroundColor": {} + } + } + } + } + ], + "tableCellStyle": { + "rowSpan": 1, + "columnSpan": 1, + "backgroundColor": {}, + "paddingLeft": { + "magnitude": 5, + "unit": "PT" + }, + "paddingRight": { + "magnitude": 5, + "unit": "PT" + }, + "paddingTop": { + "magnitude": 5, + "unit": "PT" + }, + "paddingBottom": { + "magnitude": 5, + "unit": "PT" + }, + "contentAlignment": "TOP" + } + } + ], + "tableRowStyle": { + "minRowHeight": { + "unit": "PT" + } + } + } + ], + "tableStyle": { + "tableColumnProperties": [ + { + "widthType": "EVENLY_DISTRIBUTED" + }, + { + "widthType": "EVENLY_DISTRIBUTED" + }, + { + "widthType": "EVENLY_DISTRIBUTED" + } + ] + } + } + }, + { + "startIndex": 307, + "endIndex": 315, + "paragraph": { + "elements": [ + { + "startIndex": 307, + "endIndex": 315, + "textRun": { + "content": "Figures\n", + "textStyle": {} + } + } + ], + "paragraphStyle": { + "headingId": "h.fd1u9hjhxjbz", + "namedStyleType": "HEADING_1", + "direction": "LEFT_TO_RIGHT" + } + } + }, + { + "startIndex": 315, + "endIndex": 316, + "paragraph": { + "elements": [ + { + "startIndex": 315, + "endIndex": 316, + "textRun": { + "content": "\n", + "textStyle": {} + } + } + ], + "paragraphStyle": { + "namedStyleType": "NORMAL_TEXT", + "direction": "LEFT_TO_RIGHT" + } + } + }, + { + "startIndex": 316, + "endIndex": 318, + "paragraph": { + "elements": [ + { + "startIndex": 316, + "endIndex": 317, + "inlineObjectElement": { + "inlineObjectId": "kix.sllrhni8deea", + "textStyle": { + "fontSize": { + "magnitude": 10, + "unit": "PT" + } + } + } + }, + { + "startIndex": 317, + "endIndex": 318, + "textRun": { + "content": "\n", + "textStyle": { + "fontSize": { + "magnitude": 10, + "unit": "PT" + } + } + } + } + ], + "paragraphStyle": { + "namedStyleType": "NORMAL_TEXT", + "lineSpacing": 100, + "direction": "LEFT_TO_RIGHT", + "spacingMode": "NEVER_COLLAPSE" + } + } + }, + { + "startIndex": 318, + "endIndex": 441, + "paragraph": { + "elements": [ + { + "startIndex": 318, + "endIndex": 440, + "textRun": { + "content": "Figure 1. Italicized (or bolded) captions before or after an image should be decoded as figure caption (and label if any).", + "textStyle": { + "italic": true, + "foregroundColor": { + "color": { + "rgbColor": { + "red": 0.2, + "green": 0.2, + "blue": 0.2 + } + } + }, + "fontSize": { + "magnitude": 12, + "unit": "PT" + } + } + } + }, + { + "startIndex": 440, + "endIndex": 441, + "textRun": { + "content": "\n", + "textStyle": {} + } + } + ], + "paragraphStyle": { + "namedStyleType": "NORMAL_TEXT", + "lineSpacing": 110, + "direction": "LEFT_TO_RIGHT", + "spacingMode": "NEVER_COLLAPSE", + "spaceAbove": { + "magnitude": 14.15, + "unit": "PT" + }, + "spaceBelow": { + "magnitude": 28.35, + "unit": "PT" + } + } + } + }, + { + "startIndex": 441, + "endIndex": 453, + "paragraph": { + "elements": [ + { + "startIndex": 441, + "endIndex": 453, + "textRun": { + "content": "Code Chunks\n", + "textStyle": {} + } + } + ], + "paragraphStyle": { + "headingId": "h.gk1z57d113ai", + "namedStyleType": "HEADING_1", + "direction": "LEFT_TO_RIGHT" + } + } + }, + { + "startIndex": 453, + "endIndex": 454, + "paragraph": { + "elements": [ + { + "startIndex": 453, + "endIndex": 454, + "textRun": { + "content": "\n", + "textStyle": {} + } + } + ], + "paragraphStyle": { + "namedStyleType": "NORMAL_TEXT", + "direction": "LEFT_TO_RIGHT" + } + } + }, + { + "startIndex": 454, + "endIndex": 496, + "paragraph": { + "elements": [ + { + "startIndex": 454, + "endIndex": 496, + "textRun": { + "content": "Here is a code chunk which has no output:\n", + "textStyle": {} + } + } + ], + "paragraphStyle": { + "namedStyleType": "NORMAL_TEXT", + "direction": "LEFT_TO_RIGHT" + } + } + }, + { + "startIndex": 496, + "endIndex": 497, + "paragraph": { + "elements": [ + { + "startIndex": 496, + "endIndex": 497, + "textRun": { + "content": "\n", + "textStyle": {} + } + } + ], + "paragraphStyle": { + "namedStyleType": "NORMAL_TEXT", + "direction": "LEFT_TO_RIGHT" + } + } + }, + { + "startIndex": 497, + "endIndex": 499, + "paragraph": { + "elements": [ + { + "startIndex": 497, + "endIndex": 498, + "inlineObjectElement": { + "inlineObjectId": "kix.hwmkassz48tj", + "textStyle": { + "fontSize": { + "magnitude": 10, + "unit": "PT" + }, + "link": { + "url": "https://hub.stenci.la/api/nodes/aExdDDo6twFHCekMfHNFbKsFrCRhKFnv" + } + } + } + }, + { + "startIndex": 498, + "endIndex": 499, + "textRun": { + "content": "\n", + "textStyle": {} + } + } + ], + "paragraphStyle": { + "namedStyleType": "NORMAL_TEXT", + "lineSpacing": 100, + "direction": "LEFT_TO_RIGHT", + "spacingMode": "NEVER_COLLAPSE" + } + } + }, + { + "startIndex": 499, + "endIndex": 500, + "paragraph": { + "elements": [ + { + "startIndex": 499, + "endIndex": 500, + "textRun": { + "content": "\n", + "textStyle": {} + } + } + ], + "paragraphStyle": { + "namedStyleType": "NORMAL_TEXT", + "lineSpacing": 100, + "direction": "LEFT_TO_RIGHT", + "spacingMode": "NEVER_COLLAPSE" + } + } + }, + { + "startIndex": 500, + "endIndex": 554, + "paragraph": { + "elements": [ + { + "startIndex": 500, + "endIndex": 554, + "textRun": { + "content": "And here is one that has a some output and a caption:\n", + "textStyle": {} + } + } + ], + "paragraphStyle": { + "namedStyleType": "NORMAL_TEXT", + "lineSpacing": 100, + "direction": "LEFT_TO_RIGHT", + "spacingMode": "NEVER_COLLAPSE" + } + } + }, + { + "startIndex": 554, + "endIndex": 555, + "paragraph": { + "elements": [ + { + "startIndex": 554, + "endIndex": 555, + "textRun": { + "content": "\n", + "textStyle": {} + } + } + ], + "paragraphStyle": { + "namedStyleType": "NORMAL_TEXT", + "lineSpacing": 100, + "direction": "LEFT_TO_RIGHT", + "spacingMode": "NEVER_COLLAPSE" + } + } + }, + { + "startIndex": 555, + "endIndex": 557, + "paragraph": { + "elements": [ + { + "startIndex": 555, + "endIndex": 556, + "inlineObjectElement": { + "inlineObjectId": "kix.4ryvs4row2da", + "textStyle": { + "link": { + "url": "https://hub.stenci.la/api/nodes/8cd620395bf1fbb43c3298275defda2b9705cb1c037b4fa2eeb6ffe588a4bedd" + } + } + } + }, + { + "startIndex": 556, + "endIndex": 557, + "textRun": { + "content": "\n", + "textStyle": {} + } + } + ], + "paragraphStyle": { + "namedStyleType": "NORMAL_TEXT", + "direction": "LEFT_TO_RIGHT" + } + } + }, + { + "startIndex": 557, + "endIndex": 587, + "paragraph": { + "elements": [ + { + "startIndex": 557, + "endIndex": 586, + "textRun": { + "content": "Figure 2. Code chunk caption.", + "textStyle": { + "italic": true, + "foregroundColor": { + "color": { + "rgbColor": { + "red": 0.2, + "green": 0.2, + "blue": 0.2 + } + } + }, + "fontSize": { + "magnitude": 12, + "unit": "PT" + } + } + } + }, + { + "startIndex": 586, + "endIndex": 587, + "textRun": { + "content": "\n", + "textStyle": {} + } + } + ], + "paragraphStyle": { + "namedStyleType": "NORMAL_TEXT", + "lineSpacing": 110, + "direction": "LEFT_TO_RIGHT", + "spacingMode": "NEVER_COLLAPSE", + "spaceAbove": { + "magnitude": 14.15, + "unit": "PT" + }, + "spaceBelow": { + "magnitude": 28.35, + "unit": "PT" + } + } + } + }, + { + "startIndex": 587, + "endIndex": 588, + "paragraph": { + "elements": [ + { + "startIndex": 587, + "endIndex": 588, + "textRun": { + "content": "\n", + "textStyle": {} + } + } + ], + "paragraphStyle": { + "namedStyleType": "NORMAL_TEXT", + "direction": "LEFT_TO_RIGHT" + } + } + } + ] + }, + "documentStyle": { + "background": { + "color": { + "color": { + "rgbColor": { + "red": 1, + "green": 1, + "blue": 1 + } + } + } + }, + "pageNumberStart": 1, + "marginTop": { + "magnitude": 72, + "unit": "PT" + }, + "marginBottom": { + "magnitude": 72, + "unit": "PT" + }, + "marginRight": { + "magnitude": 72, + "unit": "PT" + }, + "marginLeft": { + "magnitude": 72, + "unit": "PT" + }, + "pageSize": { + "height": { + "magnitude": 841.8897637795277, + "unit": "PT" + }, + "width": { + "magnitude": 595.2755905511812, + "unit": "PT" + } + }, + "marginHeader": { + "magnitude": 36, + "unit": "PT" + }, + "marginFooter": { + "magnitude": 36, + "unit": "PT" + }, + "useCustomHeaderFooterMargins": true + }, + "namedStyles": { + "styles": [ + { + "namedStyleType": "NORMAL_TEXT", + "textStyle": { + "bold": false, + "italic": false, + "underline": false, + "strikethrough": false, + "smallCaps": false, + "backgroundColor": {}, + "foregroundColor": { + "color": { + "rgbColor": {} + } + }, + "fontSize": { + "magnitude": 11, + "unit": "PT" + }, + "weightedFontFamily": { + "fontFamily": "Lato", + "weight": 400 + }, + "baselineOffset": "NONE" + }, + "paragraphStyle": { + "namedStyleType": "NORMAL_TEXT", + "alignment": "START", + "lineSpacing": 115, + "direction": "LEFT_TO_RIGHT", + "spacingMode": "COLLAPSE_LISTS", + "spaceAbove": { + "unit": "PT" + }, + "spaceBelow": { + "unit": "PT" + }, + "borderBetween": { + "color": {}, + "width": { + "unit": "PT" + }, + "padding": { + "unit": "PT" + }, + "dashStyle": "SOLID" + }, + "borderTop": { + "color": {}, + "width": { + "unit": "PT" + }, + "padding": { + "unit": "PT" + }, + "dashStyle": "SOLID" + }, + "borderBottom": { + "color": {}, + "width": { + "unit": "PT" + }, + "padding": { + "unit": "PT" + }, + "dashStyle": "SOLID" + }, + "borderLeft": { + "color": {}, + "width": { + "unit": "PT" + }, + "padding": { + "unit": "PT" + }, + "dashStyle": "SOLID" + }, + "borderRight": { + "color": {}, + "width": { + "unit": "PT" + }, + "padding": { + "unit": "PT" + }, + "dashStyle": "SOLID" + }, + "indentFirstLine": { + "unit": "PT" + }, + "indentStart": { + "unit": "PT" + }, + "indentEnd": { + "unit": "PT" + }, + "keepLinesTogether": false, + "keepWithNext": false, + "avoidWidowAndOrphan": true, + "shading": { + "backgroundColor": {} + } + } + }, + { + "namedStyleType": "HEADING_1", + "textStyle": { + "fontSize": { + "magnitude": 20, + "unit": "PT" + } + }, + "paragraphStyle": { + "namedStyleType": "NORMAL_TEXT", + "direction": "LEFT_TO_RIGHT", + "spaceAbove": { + "magnitude": 20, + "unit": "PT" + }, + "spaceBelow": { + "magnitude": 6, + "unit": "PT" + }, + "keepLinesTogether": true, + "keepWithNext": true + } + }, + { + "namedStyleType": "HEADING_2", + "textStyle": { + "bold": false, + "fontSize": { + "magnitude": 16, + "unit": "PT" + } + }, + "paragraphStyle": { + "namedStyleType": "NORMAL_TEXT", + "direction": "LEFT_TO_RIGHT", + "spaceAbove": { + "magnitude": 18, + "unit": "PT" + }, + "spaceBelow": { + "magnitude": 6, + "unit": "PT" + }, + "keepLinesTogether": true, + "keepWithNext": true + } + }, + { + "namedStyleType": "HEADING_3", + "textStyle": { + "bold": false, + "foregroundColor": { + "color": { + "rgbColor": { + "red": 0.2627451, + "green": 0.2627451, + "blue": 0.2627451 + } + } + }, + "fontSize": { + "magnitude": 14, + "unit": "PT" + } + }, + "paragraphStyle": { + "namedStyleType": "NORMAL_TEXT", + "direction": "LEFT_TO_RIGHT", + "spaceAbove": { + "magnitude": 16, + "unit": "PT" + }, + "spaceBelow": { + "magnitude": 4, + "unit": "PT" + }, + "keepLinesTogether": true, + "keepWithNext": true + } + }, + { + "namedStyleType": "HEADING_4", + "textStyle": { + "foregroundColor": { + "color": { + "rgbColor": { + "red": 0.4, + "green": 0.4, + "blue": 0.4 + } + } + }, + "fontSize": { + "magnitude": 12, + "unit": "PT" + } + }, + "paragraphStyle": { + "namedStyleType": "NORMAL_TEXT", + "direction": "LEFT_TO_RIGHT", + "spaceAbove": { + "magnitude": 14, + "unit": "PT" + }, + "spaceBelow": { + "magnitude": 4, + "unit": "PT" + }, + "keepLinesTogether": true, + "keepWithNext": true + } + }, + { + "namedStyleType": "HEADING_5", + "textStyle": { + "foregroundColor": { + "color": { + "rgbColor": { + "red": 0.4, + "green": 0.4, + "blue": 0.4 + } + } + }, + "fontSize": { + "magnitude": 11, + "unit": "PT" + } + }, + "paragraphStyle": { + "namedStyleType": "NORMAL_TEXT", + "direction": "LEFT_TO_RIGHT", + "spaceAbove": { + "magnitude": 12, + "unit": "PT" + }, + "spaceBelow": { + "magnitude": 4, + "unit": "PT" + }, + "keepLinesTogether": true, + "keepWithNext": true + } + }, + { + "namedStyleType": "HEADING_6", + "textStyle": { + "italic": true, + "foregroundColor": { + "color": { + "rgbColor": { + "red": 0.4, + "green": 0.4, + "blue": 0.4 + } + } + }, + "fontSize": { + "magnitude": 11, + "unit": "PT" + } + }, + "paragraphStyle": { + "namedStyleType": "NORMAL_TEXT", + "direction": "LEFT_TO_RIGHT", + "spaceAbove": { + "magnitude": 12, + "unit": "PT" + }, + "spaceBelow": { + "magnitude": 4, + "unit": "PT" + }, + "keepLinesTogether": true, + "keepWithNext": true + } + }, + { + "namedStyleType": "TITLE", + "textStyle": { + "fontSize": { + "magnitude": 26, + "unit": "PT" + } + }, + "paragraphStyle": { + "namedStyleType": "NORMAL_TEXT", + "direction": "LEFT_TO_RIGHT", + "spaceAbove": { + "unit": "PT" + }, + "spaceBelow": { + "magnitude": 3, + "unit": "PT" + }, + "keepLinesTogether": true, + "keepWithNext": true + } + }, + { + "namedStyleType": "SUBTITLE", + "textStyle": { + "italic": false, + "foregroundColor": { + "color": { + "rgbColor": { + "red": 0.4, + "green": 0.4, + "blue": 0.4 + } + } + }, + "fontSize": { + "magnitude": 15, + "unit": "PT" + }, + "weightedFontFamily": { + "fontFamily": "Arial", + "weight": 400 + } + }, + "paragraphStyle": { + "namedStyleType": "NORMAL_TEXT", + "direction": "LEFT_TO_RIGHT", + "spaceAbove": { + "unit": "PT" + }, + "spaceBelow": { + "magnitude": 16, + "unit": "PT" + }, + "keepLinesTogether": true, + "keepWithNext": true + } + } + ] + }, + "revisionId": "ALm37BVQuF2miz0zfzs_cf6leWY9pTZsxrXIM8BI9DeAnKuo6wzfYCjUAZrgR1BRHPv51deUccEGwGEBjDC7nA", + "suggestionsViewMode": "SUGGESTIONS_INLINE", + "inlineObjects": { + "kix.4ryvs4row2da": { + "objectId": "kix.4ryvs4row2da", + "inlineObjectProperties": { + "embeddedObject": { + "imageProperties": { + "contentUri": "https://lh4.googleusercontent.com/AwukyJjlG9CV1ar1NAmuqBb3gIeiaE-Q6bOJaMFC6PnrvX6EryNpMaeV5Y-wJD_Ta_Oy5nGS_2V-g7UlEa6nI-n2M7jiIXONgTUiFaRQK_SjxJB-fL9g2MSYZtLtFBlBZstNsI6tpQipm4uVpw", + "cropProperties": {} + }, + "description": "{\"id\":\"de6c884d-5892-4c4f-88c2-ba51be893eb3\",\"type\":\"CodeChunk\",\"outputs\":[],\"programmingLanguage\":\"r\",\"duration\":0.007,\"text\":\"hist(rnorm(1000), breaks=100,col=\\\"blue\\\")\"}", + "embeddedObjectBorder": { + "color": { + "color": { + "rgbColor": {} + } + }, + "width": { + "unit": "PT" + }, + "dashStyle": "SOLID", + "propertyState": "NOT_RENDERED" + }, + "size": { + "height": { + "magnitude": 381.8730043541364, + "unit": "PT" + }, + "width": { + "magnitude": 371.625, + "unit": "PT" + } + }, + "marginTop": { + "magnitude": 1.5, + "unit": "PT" + }, + "marginBottom": { + "magnitude": 1.5, + "unit": "PT" + }, + "marginRight": { + "magnitude": 1.5, + "unit": "PT" + }, + "marginLeft": { + "magnitude": 1.5, + "unit": "PT" + } + } + } + }, + "kix.hwmkassz48tj": { + "objectId": "kix.hwmkassz48tj", + "inlineObjectProperties": { + "embeddedObject": { + "imageProperties": { + "contentUri": "https://lh6.googleusercontent.com/8eVSH_yD7Vw5wokM5YQ9_5RdVwHquCNgS2SR5ph8G4VbZlX7dHHxRrwyHZHecAIUu2xZve6b5WpAFB1q-ck7LrFhySvRunYr8eFVjKsYSxW3DA7hG5_dT56sUhaCg-jz8I45ebdTbZdWeCsfrw", + "cropProperties": {} + }, + "title": "CodeChunk", + "description": "{\"text\":\"# Some R code\",\"programmingLanguage\":\"r\",\"type\":\"CodeChunk\"}", + "embeddedObjectBorder": { + "color": { + "color": { + "rgbColor": {} + } + }, + "width": { + "unit": "PT" + }, + "dashStyle": "SOLID", + "propertyState": "NOT_RENDERED" + }, + "size": { + "height": { + "magnitude": 24, + "unit": "PT" + }, + "width": { + "magnitude": 24, + "unit": "PT" + } + }, + "marginTop": { + "unit": "PT" + }, + "marginBottom": { + "unit": "PT" + }, + "marginRight": { + "magnitude": 9, + "unit": "PT" + }, + "marginLeft": { + "magnitude": 9, + "unit": "PT" + } + } + } + }, + "kix.sllrhni8deea": { + "objectId": "kix.sllrhni8deea", + "inlineObjectProperties": { + "embeddedObject": { + "imageProperties": { + "contentUri": "https://lh3.googleusercontent.com/WhVtttNw60aHwGIOUnUJOPFHPUeoMySIiCdvT2TSczDsYVNXqJN5aFwAmf3R-cSk1w8rTSddfkKjUcGjFqzpcp4eKx3H5ulhIVpGaiYXWX0lwrRK6BYonvcMOgJgWdi-5-c5ZSUTjgPZpc8VRA", + "cropProperties": {} + }, + "embeddedObjectBorder": { + "color": { + "color": { + "rgbColor": {} + } + }, + "width": { + "unit": "PT" + }, + "dashStyle": "SOLID", + "propertyState": "NOT_RENDERED" + }, + "size": { + "height": { + "magnitude": 75, + "unit": "PT" + }, + "width": { + "magnitude": 75, + "unit": "PT" + } + }, + "marginTop": { + "unit": "PT" + }, + "marginBottom": { + "unit": "PT" + }, + "marginRight": { + "magnitude": 9, + "unit": "PT" + }, + "marginLeft": { + "magnitude": 9, + "unit": "PT" + } + } + } + } + }, + "documentId": "1ngLlIJr2SJ15A7Mnb2mg7f8hWePUDzYETjMjTaPoJWM" +} diff --git a/src/codecs/gdoc/gdoc.test.ts b/src/codecs/gdoc/gdoc.test.ts index 9002d2eab..4c003b481 100644 --- a/src/codecs/gdoc/gdoc.test.ts +++ b/src/codecs/gdoc/gdoc.test.ts @@ -1,6 +1,6 @@ import * as stencila from '@stencila/schema' import { GDocCodec } from '.' -import { fixture, snapshot } from '../../__tests__/helpers' +import { fixture, nockRecord, snapshot } from '../../__tests__/helpers' import { YamlCodec } from '../yaml' import * as kitchenSink from './__fixtures__/kitchenSink' import * as nestedList from './__fixtures__/nestedList' @@ -52,11 +52,19 @@ describe('decode', () => { test('nestedList', async () => expect(await gdoc2node(nestedList.gdoc)).toEqual(nestedList.node)) - const gdoc2yaml = async (path: string) => - yamlCodec.dump(await gdocCodec.read(path)) + test('fixtures', async () => { + const gdoc2yaml = async (path: string) => + yamlCodec.dump(await gdocCodec.read(path)) + + const done = await nockRecord('nock-record-decode-fixtures.json') - test('test-fixture-1.gdoc', async () => expect(await gdoc2yaml(fixture('test-fixture-1.gdoc'))).toMatchFile( snapshot('test-fixture-1.yaml') - )) + ) + expect(await gdoc2yaml(fixture('test-fixture-2.gdoc'))).toMatchFile( + snapshot('test-fixture-2.yaml') + ) + + done() + }) }) diff --git a/src/codecs/gdoc/index.ts b/src/codecs/gdoc/index.ts index cd997a47a..702d7d200 100644 --- a/src/codecs/gdoc/index.ts +++ b/src/codecs/gdoc/index.ts @@ -16,7 +16,7 @@ import { getLogger } from '@stencila/logga' import * as stencila from '@stencila/schema' import { docs_v1 as GDocT } from 'googleapis' import tempy from 'tempy' -import * as http from '../../util/http' +import { http, download } from '../../util/http' import * as vfile from '../../util/vfile' import { DocxCodec } from '../docx' import { Codec, CommonDecodeOptions, CommonEncodeOptions } from '../types' @@ -99,7 +99,7 @@ class FetchToFile { public get(url: string, ext = ''): string { const filePath = tempy.file({ extension: ext }) - this.requests.push(http.download(url, filePath)) + this.requests.push(download(url, filePath)) return filePath } @@ -160,37 +160,41 @@ async function decodeDocument( let content: stencila.Node[] = [] const lists: { [key: string]: stencila.List[] } = {} if (doc.body?.content) { - content = doc.body.content - .map((elem: GDocT.Schema$StructuralElement, index: number) => { - if (elem.paragraph) { - const para = elem.paragraph - const block = decodeParagraph(para, lists) - // If this para has the `Title` style then use it's content - // as the title of the article (overrides doc.title) - if (stencila.isParagraph(block) && para.paragraphStyle) { - const styleType = para.paragraphStyle.namedStyleType - if (styleType && styleType === 'TITLE') { - const { content } = block - title = - content.length === 0 - ? undefined - : content.length === 1 && typeof content[0] === 'string' - ? content[0] - : content - return undefined + content = ( + await Promise.all( + doc.body.content.map( + async (elem: GDocT.Schema$StructuralElement, index: number) => { + if (elem.paragraph) { + const para = elem.paragraph + const block = await decodeParagraph(para, lists) + // If this para has the `Title` style then use it's content + // as the title of the article (overrides doc.title) + if (stencila.isParagraph(block) && para.paragraphStyle) { + const styleType = para.paragraphStyle.namedStyleType + if (styleType && styleType === 'TITLE') { + const { content } = block + title = + content.length === 0 + ? undefined + : content.length === 1 && typeof content[0] === 'string' + ? content[0] + : content + return undefined + } + } + return block + } else if (elem.sectionBreak) { + // The first element in the content is always a sectionBreak, so ignore it + return index === 0 ? undefined : decodeSectionBreak() + } else if (elem.table) { + return decodeTable(elem.table) + } else { + log.warn(`Unhandled GDoc element type ${JSON.stringify(elem)}`) } } - return block - } else if (elem.sectionBreak) { - // The first element in the content is always a sectionBreak, so ignore it - return index === 0 ? undefined : decodeSectionBreak() - } else if (elem.table) { - return decodeTable(elem.table) - } else { - log.warn(`Unhandled GDoc element type ${JSON.stringify(elem)}`) - } - }) - .filter((node) => node !== undefined) as stencila.Node[] + ) + ) + ).filter((node) => node !== undefined) as stencila.Node[] } // Resolve the fetched resources @@ -210,13 +214,13 @@ async function decodeDocument( * is a reproducible image, then it will be decoded to the entity in that image * e.g. `CodeChunk`. */ -function decodeParagraph( +async function decodeParagraph( para: GDocT.Schema$Paragraph, lists: { [key: string]: stencila.List[] } -): stencila.Node | undefined { +): Promise { const { elements = [], paragraphStyle, bullet } = para - const content = elements.map(decodeParagraphElement) + const content = await Promise.all(elements.map(decodeParagraphElement)) // See if the content is a single block content node, and if // so return that. Filtering is necessary to remove empty strings that @@ -321,40 +325,50 @@ function decodeListItem( /** * Decode a GDoc `Table` element to a Stencila `Table`. */ -function decodeTable(table: GDocT.Schema$Table): stencila.Table { +async function decodeTable(table: GDocT.Schema$Table): Promise { return { type: 'Table', - rows: (table.tableRows ?? []).map( - (row: GDocT.Schema$TableRow): stencila.TableRow => { - return { - type: 'TableRow', - cells: (row.tableCells ?? []).map( - (cell: GDocT.Schema$TableCell): stencila.TableCell => { - return { - type: 'TableCell', - content: (cell.content ?? []).map( - ( - elem: GDocT.Schema$StructuralElement - ): stencila.InlineContent => { - if (elem.paragraph) { - const { elements } = elem.paragraph - if (elements) { - return elements - .map(decodeParagraphElement) - .filter(stencila.isInlineContent)[0] - } - } - log.warn( - 'Sorry, currently can only handle paragraphs in table cells' - ) - return '' + rows: await Promise.all( + (table.tableRows ?? []).map( + async (row: GDocT.Schema$TableRow): Promise => { + return { + type: 'TableRow', + cells: await Promise.all( + (row.tableCells ?? []).map( + async ( + cell: GDocT.Schema$TableCell + ): Promise => { + return { + type: 'TableCell', + content: await Promise.all( + (cell.content ?? []).map( + async ( + elem: GDocT.Schema$StructuralElement + ): Promise => { + if (elem.paragraph) { + const { elements } = elem.paragraph + if (elements) { + return ( + await Promise.all( + elements.map(decodeParagraphElement) + ) + ).filter(stencila.isInlineContent)[0] + } + } + log.warn( + 'Sorry, currently can only handle paragraphs in table cells' + ) + return '' + } + ) + ), } - ), - } - } - ), + } + ) + ), + } } - } + ) ), } } @@ -372,15 +386,15 @@ function decodeSectionBreak(): stencila.ThematicBreak { * See the [docs](https://developers.google.com/docs/api/reference/rest/v1/documents#paragraphelement) * for a list of the possible union field types. */ -function decodeParagraphElement( +async function decodeParagraphElement( elem: GDocT.Schema$ParagraphElement -): stencila.Entity | stencila.InlineContent { +): Promise { // The paragraph element has one of these union fields if (elem.textRun) { return decodeTextRun(elem.textRun) } if (elem.inlineObjectElement) { - return decodeInlineObjectElement(elem.inlineObjectElement) + return await decodeInlineObjectElement(elem.inlineObjectElement) } if (elem.pageBreak || elem.horizontalRule) { // We can not decode these to a `ThematicBreak` (because that is not `InlineContent`) @@ -406,9 +420,29 @@ function decodeParagraphElement( /** * Decode a GDoc `InlineObjectElement` to a Stencila `Entity`. */ -function decodeInlineObjectElement( +async function decodeInlineObjectElement( elem: GDocT.Schema$InlineObjectElement -): stencila.Entity { +): Promise { + // Check if there is a link to a node + const url = elem.textStyle?.link?.url + if ( + typeof url === 'string' && + url.startsWith('https://hub.stenci.la/api/nodes/') + ) { + try { + const headers = + process.env.STENCILA_API_TOKEN !== undefined + ? { + Authorization: `Token ${process.env.STENCILA_API_TOKEN}`, + } + : {} + const node = await http.get(url, { headers }).json() + return node.node + } catch { + log.warn(`Error fetching node from ${url}`) + } + } + const embeddedObject = assertDefined( assertDefined( assertDefined(decodingGDoc.inlineObjects)[ @@ -416,6 +450,24 @@ function decodeInlineObjectElement( ].inlineObjectProperties ).embeddedObject ) + + // Check if the description text is a JSON representation + // of a node. + const { description } = embeddedObject + if (typeof description === 'string') { + let node + try { + node = JSON.parse(description) + } catch { + // continue + } + if (node !== undefined && stencila.isEntity(node)) { + // If the description contains a Stencila entity then + // return it + return node + } + } + if (embeddedObject.imageProperties) { return decodeImage(embeddedObject, embeddedObject.imageProperties) } else { @@ -464,10 +516,7 @@ function decodeTextRun( } /** - * Decode a GDoc `EmbeddedObject` with `imageProperties` into a Stencila `Entity`. - * - * If the image has a description that can be parsed as JSON into a Stencila `Entity`, - * then that entity will be returned. Otherwise, a `ImageObject` is returned. + * Decode a GDoc `EmbeddedObject` with `imageProperties` into a Stencila `ImageObject`. * * Because the `imageProperties.contentUri` is ephemeral (lasts about ~30mins) this * function fetches the URL before it disappears. @@ -475,34 +524,15 @@ function decodeTextRun( function decodeImage( embeddedObject: GDocT.Schema$EmbeddedObject, imageProperties: GDocT.Schema$ImageProperties -): stencila.Entity { - let { title, description } = embeddedObject - if (title === null) title = undefined - if (description === null) description = undefined - - // Check to see if this is a reproducible images i.e. that the - // description contains JSON that can be parsed into a Stencila node. - if (typeof description === 'string') { - let node - try { - node = JSON.parse(description) - } catch { - // Do nothing - } - if (node !== undefined && stencila.isEntity(node)) { - // If the description contains a Stencila entity then - // return it - return node - } - } - +): stencila.ImageObject { + const { title, description } = embeddedObject const contentUri = imageProperties.contentUri ?? '' const contentUrl = contentUri.startsWith('http') ? decodingFetcher(contentUri) : contentUri return stencila.imageObject({ contentUrl, - title, - text: description, + title: title !== null ? title : undefined, + text: description !== null ? description : undefined, }) }