summaryrefslogtreecommitdiff
path: root/src/gempub.c
diff options
context:
space:
mode:
authorJaakko Keränen <jaakko.keranen@iki.fi>2021-05-05 13:30:00 +0300
committerJaakko Keränen <jaakko.keranen@iki.fi>2021-05-05 13:30:00 +0300
commit14e64fde73a25d5758fe70d5425b70399c3705db (patch)
treef3765626b7a2bdc1e7324a1d308f5b27e22b93cc /src/gempub.c
parent93f7e8712057bc04bd6123a8aa8db0e1e3bdcec8 (diff)
Gempub: Parse links on index page for navigation
Diffstat (limited to 'src/gempub.c')
-rw-r--r--src/gempub.c84
1 files changed, 80 insertions, 4 deletions
diff --git a/src/gempub.c b/src/gempub.c
index c9b1c242..e1f246ac 100644
--- a/src/gempub.c
+++ b/src/gempub.c
@@ -25,31 +25,92 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
25#include "lang.h" 25#include "lang.h"
26#include "defs.h" 26#include "defs.h"
27#include "gmdocument.h" 27#include "gmdocument.h"
28#include "gmrequest.h"
28#include "ui/util.h" 29#include "ui/util.h"
30#include "app.h"
29 31
30#include <the_Foundation/archive.h> 32#include <the_Foundation/archive.h>
31#include <the_Foundation/file.h> 33#include <the_Foundation/file.h>
32#include <the_Foundation/path.h> 34#include <the_Foundation/path.h>
35#include <the_Foundation/regexp.h>
33 36
34const char *mimeType_Gempub = "application/gpub+zip"; 37const char *mimeType_Gempub = "application/gpub+zip";
35 38
39/*----------------------------------------------------------------------------------------------*/
40
41iDeclareType(GempubNavLink)
42
43struct Impl_GempubNavLink {
44 iString url;
45 iString label;
46};
47
48static void init_GempubNavLink(iGempubNavLink *d) {
49 init_String(&d->url);
50 init_String(&d->label);
51}
52
53static void deinit_GempubNavLink(iGempubNavLink *d) {
54 deinit_String(&d->url);
55 deinit_String(&d->label);
56}
57
58iDefineTypeConstruction(GempubNavLink)
59
60/*----------------------------------------------------------------------------------------------*/
61
36struct Impl_Gempub { 62struct Impl_Gempub {
37 iArchive *arch; 63 iArchive *arch;
38 iString baseUrl; 64 iString baseUrl;
39 iString props[max_GempubProperty]; 65 iString props[max_GempubProperty];
66 iArray *navLinks; /* from index page */
40}; 67};
41 68
42iDefineTypeConstruction(Gempub) 69iDefineTypeConstruction(Gempub)
43 70
71static void parseNavigationLinks_Gempub_(const iGempub *d) {
72 if (!isEmpty_Array(d->navLinks)) {
73 return;
74 }
75 iGmRequest *index = iClob(new_GmRequest(certs_App()));
76 setUrl_GmRequest(index, indexPageUrl_Gempub(d));
77 submit_GmRequest(index); /* this is just a local file read */
78 iAssert(isFinished_GmRequest(index));
79 iRangecc src = iNullRange;
80 iRegExp *linkPattern = iClob(newGemtextLink_RegExp());
81 while (nextSplit_Rangecc(range_Block(body_GmRequest(index)), "\n", &src)) {
82 iRangecc line = src;
83 trim_Rangecc(&line);
84 iRegExpMatch m;
85 init_RegExpMatch(&m);
86 if (matchRange_RegExp(linkPattern, line, &m)) {
87 iBeginCollect();
88 iGempubNavLink link;
89 init_GempubNavLink(&link);
90 const iRangecc url = capturedRange_RegExpMatch(&m, 1);
91 set_String(&link.url, absoluteUrl_String(url_GmRequest(index), collectNewRange_String(url)));
92 setRange_String(&link.label, capturedRange_RegExpMatch(&m, 2));
93 trim_String(&link.label);
94 pushBack_Array(d->navLinks, &link);
95 iEndCollect();
96 }
97 }
98}
99
44void init_Gempub(iGempub *d) { 100void init_Gempub(iGempub *d) {
45 d->arch = NULL; 101 d->arch = NULL;
46 init_String(&d->baseUrl); 102 init_String(&d->baseUrl);
47 iForIndices(i, d->props) { 103 iForIndices(i, d->props) {
48 init_String(&d->props[i]); 104 init_String(&d->props[i]);
49 } 105 }
106 d->navLinks = new_Array(sizeof(iGempubNavLink));
50} 107}
51 108
52void deinit_Gempub(iGempub *d) { 109void deinit_Gempub(iGempub *d) {
110 iForEach(Array, n, d->navLinks) {
111 deinit_GempubNavLink(n.value);
112 }
113 delete_Array(d->navLinks);
53 iForIndices(i, d->props) { 114 iForIndices(i, d->props) {
54 deinit_String(&d->props[i]); 115 deinit_String(&d->props[i]);
55 } 116 }
@@ -140,12 +201,27 @@ void close_Gempub(iGempub *d) {
140 } 201 }
141} 202}
142 203
204void setBaseUrl_Gempub(iGempub *d, const iString *url) {
205 set_String(&d->baseUrl, url);
206}
207
143iBool isOpen_Gempub(const iGempub *d) { 208iBool isOpen_Gempub(const iGempub *d) {
144 return d->arch != NULL; 209 return d->arch != NULL;
145} 210}
146 211
147void setBaseUrl_Gempub(iGempub *d, const iString *url) { 212const iString *indexPageUrl_Gempub(const iGempub *d) {
148 set_String(&d->baseUrl, url); 213 iAssert(!isEmpty_String(&d->baseUrl));
214 iString *dir = collect_String(copy_String(&d->baseUrl));
215 appendCStr_String(dir, "/");
216 return absoluteUrl_String(dir, &d->props[index_GempubProperty]);
217}
218
219const iString *navStartLinkUrl_Gempub(const iGempub *d) {
220 parseNavigationLinks_Gempub_(d);
221 if (isEmpty_Array(d->navLinks)) {
222 return NULL; /* has no navigation structure */
223 }
224 return &((const iGempubNavLink *) constFront_Array(d->navLinks))->url;
149} 225}
150 226
151static iBool hasProperty_Gempub_(const iGempub *d, enum iGempubProperty prop) { 227static iBool hasProperty_Gempub_(const iGempub *d, enum iGempubProperty prop) {
@@ -176,7 +252,7 @@ iString *coverPageSource_Gempub(const iGempub *d) {
176 appendProperty_Gempub_(d, "${gempub.meta.author}:", author_GempubProperty, out); 252 appendProperty_Gempub_(d, "${gempub.meta.author}:", author_GempubProperty, out);
177 if (!isRemote_Gempub_(d)) { 253 if (!isRemote_Gempub_(d)) {
178 appendFormat_String(out, "\n=> %s " book_Icon " ${gempub.cover.view}\n", 254 appendFormat_String(out, "\n=> %s " book_Icon " ${gempub.cover.view}\n",
179 cstrCollect_String(concat_Path(baseUrl, &d->props[index_GempubProperty]))); 255 cstr_String(indexPageUrl_Gempub(d)));
180 if (hasProperty_Gempub_(d, cover_GempubProperty)) { 256 if (hasProperty_Gempub_(d, cover_GempubProperty)) {
181 appendFormat_String(out, "\n=> %s ${gempub.cover.image}\n", 257 appendFormat_String(out, "\n=> %s ${gempub.cover.image}\n",
182 cstrCollect_String(concat_Path(baseUrl, &d->props[cover_GempubProperty]))); 258 cstrCollect_String(concat_Path(baseUrl, &d->props[cover_GempubProperty])));