| | @@ -742,24 +742,31 @@ |
| 742 | 742 | ** mimetype: "mime type", |
| 743 | 743 | ** version: UUID string or null for a sandbox page, |
| 744 | 744 | ** parent: "parent uuid" or null if no parent, |
| 745 | 745 | ** content: "page content" |
| 746 | 746 | ** } |
| 747 | +** |
| 748 | +** If includeContent is false then the content member is elided. |
| 747 | 749 | */ |
| 748 | | -static int wiki_ajax_emit_page_object(const char *zPageName){ |
| 750 | +static int wiki_ajax_emit_page_object(const char *zPageName, |
| 751 | + int includeContent){ |
| 749 | 752 | Manifest * pWiki = 0; |
| 750 | 753 | char * zUuid; |
| 751 | 754 | |
| 752 | 755 | cgi_set_content_type("application/json"); |
| 753 | 756 | if( is_sandbox(zPageName) ){ |
| 754 | 757 | char * zMimetype = |
| 755 | 758 | db_get("sandbox-mimetype","text/x-fossil-wiki"); |
| 756 | 759 | char * zBody = db_get("sandbox",""); |
| 757 | 760 | CX("{\"name\": %!j, \"type\": \"sandbox\", " |
| 758 | | - "\"mimetype\": %!j, \"version\": null, \"parent\": null, " |
| 759 | | - "\"content\": %!j}", |
| 760 | | - zPageName, zMimetype, zBody); |
| 761 | + "\"mimetype\": %!j, \"version\": null, \"parent\": null", |
| 762 | + zPageName, zMimetype); |
| 763 | + if(includeContent){ |
| 764 | + CX(", \"content\": %!j", |
| 765 | + zBody); |
| 766 | + } |
| 767 | + CX("}"); |
| 761 | 768 | fossil_free(zMimetype); |
| 762 | 769 | fossil_free(zBody); |
| 763 | 770 | return 1; |
| 764 | 771 | }else if( !wiki_fetch_by_name(zPageName, 0, 0, &pWiki) ){ |
| 765 | 772 | ajax_route_error(404, "Wiki page could not be loaded: %s", |
| | @@ -774,18 +781,21 @@ |
| 774 | 781 | wiki_page_type_name(pWiki->zWikiTitle), |
| 775 | 782 | zUuid, |
| 776 | 783 | pWiki->zMimetype ? pWiki->zMimetype : "text/x-fossil-wiki"); |
| 777 | 784 | CX("\"parent\": "); |
| 778 | 785 | if(pWiki->nParent){ |
| 779 | | - CX("%!j, ", pWiki->azParent[0]); |
| 786 | + CX("%!j", pWiki->azParent[0]); |
| 780 | 787 | }else{ |
| 781 | | - CX("null, "); |
| 788 | + CX("null"); |
| 789 | + } |
| 790 | + if(includeContent){ |
| 791 | + CX(", \"content\": %!j", pWiki->zWiki); |
| 782 | 792 | } |
| 783 | | - CX("\"content\": %!j}", pWiki->zWiki); |
| 793 | + CX("}"); |
| 784 | 794 | fossil_free(zUuid); |
| 785 | 795 | manifest_destroy(pWiki); |
| 786 | | - return 1; |
| 796 | + return 2; |
| 787 | 797 | } |
| 788 | 798 | } |
| 789 | 799 | |
| 790 | 800 | /* |
| 791 | 801 | ** Ajax route handler for /wikiajax/save. |
| | @@ -847,11 +857,11 @@ |
| 847 | 857 | } |
| 848 | 858 | |
| 849 | 859 | blob_init(&content, zContent ? zContent : "", -1); |
| 850 | 860 | db_begin_transaction(); |
| 851 | 861 | wiki_cmd_commit(zPageName, parentRid, &content, zMimetype, 0); |
| 852 | | - rollback = wiki_ajax_emit_page_object(zPageName) ? 0 : 1; |
| 862 | + rollback = wiki_ajax_emit_page_object(zPageName, 1) ? 0 : 1; |
| 853 | 863 | db_end_transaction(rollback); |
| 854 | 864 | } |
| 855 | 865 | |
| 856 | 866 | /* |
| 857 | 867 | ** Ajax route handler for /wikiajax/fetch. |
| | @@ -869,11 +879,11 @@ |
| 869 | 879 | |
| 870 | 880 | if( zPageName==0 || zPageName[0]==0 ){ |
| 871 | 881 | ajax_route_error(400,"Missing page name."); |
| 872 | 882 | return; |
| 873 | 883 | } |
| 874 | | - wiki_ajax_emit_page_object(zPageName); |
| 884 | + wiki_ajax_emit_page_object(zPageName, 1); |
| 875 | 885 | } |
| 876 | 886 | |
| 877 | 887 | /* |
| 878 | 888 | ** Ajax route handler for /wikiajax/diff. |
| 879 | 889 | ** |
| | @@ -951,34 +961,52 @@ |
| 951 | 961 | } |
| 952 | 962 | } |
| 953 | 963 | |
| 954 | 964 | /* |
| 955 | 965 | ** Ajax route handler for /wikiajax/list. |
| 966 | +** |
| 967 | +** Optional parameters: verbose, includeContent (see below). |
| 956 | 968 | ** |
| 957 | 969 | ** Responds with JSON. On error, an object in the form documented by |
| 958 | | -** ajax_route_error(). On success, an array of strings (page names) |
| 959 | | -** sorted case-insensitively. The result list contains an entry |
| 970 | +** ajax_route_error(). |
| 971 | +** |
| 972 | +** On success, it emits an array of strings (page names) sorted |
| 973 | +** case-insensitively. If the "verbose" parameter is passed in then |
| 974 | +** the result list contains objects in the format documented for |
| 975 | +** wiki_ajax_emit_page_object(). The content of each object is elided |
| 976 | +** unless the "includeContent" parameter is passed on. |
| 977 | +** |
| 978 | +** The result list always contains an entry |
| 960 | 979 | ** named "sandbox" which represents the sandbox pseudo-page. |
| 961 | 980 | */ |
| 962 | 981 | static void wiki_ajax_route_list(void){ |
| 963 | 982 | Stmt q = empty_Stmt; |
| 964 | 983 | int n = 0; |
| 984 | + const int verbose = ajax_p_bool("verbose"); |
| 985 | + const int includeContent = ajax_p_bool("includeContent"); |
| 965 | 986 | |
| 966 | 987 | cgi_set_content_type("application/json"); |
| 988 | + db_begin_transaction(); |
| 967 | 989 | db_prepare(&q, "SELECT" |
| 968 | 990 | " substr(tagname,6) AS name" |
| 969 | 991 | " FROM tag WHERE tagname GLOB 'wiki-*'" |
| 970 | 992 | " UNION SELECT 'sandbox' AS name" |
| 971 | 993 | " ORDER BY name COLLATE NOCASE"); |
| 972 | 994 | CX("["); |
| 973 | 995 | while( SQLITE_ROW==db_step(&q) ){ |
| 996 | + char const * zName = db_column_text(&q,0); |
| 974 | 997 | if(n++){ |
| 975 | 998 | CX(","); |
| 976 | 999 | } |
| 977 | | - CX("%!j", db_column_text(&q,0)); |
| 1000 | + if(verbose==0){ |
| 1001 | + CX("%!j", zName); |
| 1002 | + }else{ |
| 1003 | + wiki_ajax_emit_page_object(zName, includeContent); |
| 1004 | + } |
| 978 | 1005 | } |
| 979 | 1006 | db_finalize(&q); |
| 1007 | + db_end_transaction(0); |
| 980 | 1008 | CX("]"); |
| 981 | 1009 | } |
| 982 | 1010 | |
| 983 | 1011 | |
| 984 | 1012 | /* |
| | @@ -1090,21 +1118,21 @@ |
| 1090 | 1118 | |
| 1091 | 1119 | /******* Page list *******/ |
| 1092 | 1120 | { |
| 1093 | 1121 | CX("<div id='wikiedit-tab-pages' " |
| 1094 | 1122 | "data-tab-parent='wikiedit-tabs' " |
| 1095 | | - "data-tab-label='Page List'" |
| 1123 | + "data-tab-label='Wiki Page List'" |
| 1096 | 1124 | ">"); |
| 1097 | 1125 | CX("<div>Loading wiki pages list...</div>"); |
| 1098 | 1126 | CX("</div>"/*#wikiedit-tab-pages*/); |
| 1099 | 1127 | } |
| 1100 | 1128 | |
| 1101 | 1129 | /******* Content tab *******/ |
| 1102 | 1130 | { |
| 1103 | 1131 | CX("<div id='wikiedit-tab-content' " |
| 1104 | 1132 | "data-tab-parent='wikiedit-tabs' " |
| 1105 | | - "data-tab-label='Page Editor'" |
| 1133 | + "data-tab-label='Wiki Editor'" |
| 1106 | 1134 | ">"); |
| 1107 | 1135 | CX("<div class='flex-container flex-row child-gap-small'>"); |
| 1108 | 1136 | mimetype_option_menu(0); |
| 1109 | 1137 | CX("<button class='wikiedit-content-reload' " |
| 1110 | 1138 | "title='Reload the file from the server, discarding " |
| | @@ -1121,11 +1149,11 @@ |
| 1121 | 1149 | "200%", 200, NULL); |
| 1122 | 1150 | CX("</div>"); |
| 1123 | 1151 | CX("<div class='flex-container flex-column stretch'>"); |
| 1124 | 1152 | CX("<textarea name='content' id='wikiedit-content-editor' " |
| 1125 | 1153 | "class='wikiedit' " |
| 1126 | | - "rows='20' cols='80'>"); |
| 1154 | + "rows='25' cols='80'>"); |
| 1127 | 1155 | CX("</textarea>"); |
| 1128 | 1156 | CX("</div>"/*textarea wrapper*/); |
| 1129 | 1157 | CX("</div>"/*#tab-file-content*/); |
| 1130 | 1158 | } |
| 1131 | 1159 | /****** Preview tab ******/ |
| | @@ -1191,15 +1219,15 @@ |
| 1191 | 1219 | } |
| 1192 | 1220 | |
| 1193 | 1221 | { |
| 1194 | 1222 | CX("<div id='wikiedit-tab-save' " |
| 1195 | 1223 | "data-tab-parent='wikiedit-tabs' " |
| 1196 | | - "data-tab-label='Save & Help'" |
| 1224 | + "data-tab-label='Save, etc.'" |
| 1197 | 1225 | ">"); |
| 1198 | 1226 | CX("<button class='wikiedit-save'>Save</button>"); |
| 1199 | 1227 | CX("<hr>"); |
| 1200 | | - CX("The wiki formatting rules can be found at:"); |
| 1228 | + CX("Wiki formatting rules:"); |
| 1201 | 1229 | CX("<ul>"); |
| 1202 | 1230 | CX("<li><a href='%R/wiki_rules'>Fossil wiki format</a></li>"); |
| 1203 | 1231 | CX("<li><a href='%R/md_rules'>Markdown format</a></li>"); |
| 1204 | 1232 | CX("</ul>"); |
| 1205 | 1233 | CX("<hr>Attachments:"); |
| 1206 | 1234 | |