diff options
| -rw-r--r-- | README | 6 | ||||
| -rw-r--r-- | README.md.md | 2 | ||||
| -rwxr-xr-x | SuckIt | 140 | ||||
| -rwxr-xr-x | SuckItClean | 13 | ||||
| -rw-r--r-- | TODO.md | 87 | ||||
| -rw-r--r-- | about/index.md | 2 | ||||
| -rw-r--r-- | default.template | 78 | ||||
| -rwxr-xr-x | feed-icon-14x14.png | bin | 0 -> 689 bytes | |||
| -rwxr-xr-x | feed-icon-28x28.png | bin | 0 -> 1737 bytes | |||
| -rw-r--r-- | help.md | 43 | ||||
| -rwxr-xr-x | notYetAnotherWiki.lua | 408 | ||||
| -rw-r--r-- | testing/index.md | 6 |
12 files changed, 544 insertions, 241 deletions
| @@ -59,13 +59,13 @@ the one system. They can chat about it, on the one system. | |||
| 59 | 59 | ||
| 60 | ## What does it do already? | 60 | ## What does it do already? |
| 61 | 61 | ||
| 62 | Currently it'll scan the current directory and subdirectories looking for | 62 | Currently it'll scan the current folder and sub folders looking for |
| 63 | .md files in CommonMark syntax. This should cover some MarkDown | 63 | .md files in CommonMark syntax. This should cover some MarkDown |
| 64 | variations. Then it produces .HTML files converted from these .md files, | 64 | variations. Then it produces .HTML files converted from these .md files, |
| 65 | and links them all together into a web site. | 65 | and links them all together into a web site. |
| 66 | 66 | ||
| 67 | Any .md file that is just the beginning metadata block doesn't get | 67 | Any .md file that is just the beginning metadata block doesn't get |
| 68 | rendered into HTML, but is global metadata for this directory and subs, | 68 | rendered into HTML, but is global metadata for this folder and subs, |
| 69 | though the subs can override this with their own metadata.md files. | 69 | though the subs can override this with their own metadata.md files. |
| 70 | 70 | ||
| 71 | git is used to store the .md files, and provides edit history. Added on | 71 | git is used to store the .md files, and provides edit history. Added on |
| @@ -73,7 +73,7 @@ the footer is links to cgit, which is used to store the files in git on | |||
| 73 | your server. This provides acces to the source code, history, and ATOM | 73 | your server. This provides acces to the source code, history, and ATOM |
| 74 | feed for the site. | 74 | feed for the site. |
| 75 | 75 | ||
| 76 | It can also scan an external directory and merge that with the current | 76 | It can also scan an external folder and merge that with the current |
| 77 | one, but this isn't tested yet. | 77 | one, but this isn't tested yet. |
| 78 | 78 | ||
| 79 | ## other stuff | 79 | ## other stuff |
diff --git a/README.md.md b/README.md.md index bc85e8c..31ea1e7 100644 --- a/README.md.md +++ b/README.md.md | |||
| @@ -1 +1 @@ | |||
| title=notYetAnotherWiki | title=nYAW | ||
| @@ -4,14 +4,16 @@ TIMEFORMAT=" took %lR using %P%% CPU" | |||
| 4 | time { | 4 | time { |
| 5 | pushd /opt/nyaw | 5 | pushd /opt/nyaw |
| 6 | 6 | ||
| 7 | rm -fr Foswiki/* | 7 | #rm -fr Foswiki/* |
| 8 | cp -r /opt/nyaw_EMPTY/Foswiki . | 8 | cp -r /opt/nyaw_EMPTY/Foswiki . |
| 9 | rm -fr PmWiki/* | 9 | #rm -fr PmWiki/* |
| 10 | cp -r /opt/nyaw_EMPTY/PmWiki . | 10 | cp -r /opt/nyaw_EMPTY/PmWiki . |
| 11 | rm -fr unsorted | 11 | #rm -fr unsorted |
| 12 | mkdir -p unsorted | 12 | mkdir -p unsorted |
| 13 | rm -fr users | 13 | cp -r /opt/nyaw_EMPTY/unsorted . |
| 14 | #rm -fr users/* | ||
| 14 | mkdir -p users | 15 | mkdir -p users |
| 16 | cp -r /opt/nyaw_EMPTY/users . | ||
| 15 | 17 | ||
| 16 | # Copy across things like images that where uploaded. | 18 | # Copy across things like images that where uploaded. |
| 17 | mkdir -p /opt/nyaw/Foswiki/pub/ | 19 | mkdir -p /opt/nyaw/Foswiki/pub/ |
| @@ -32,31 +34,62 @@ do | |||
| 32 | base=`echo "${line}" | cut -d '/' -f 1` | 34 | base=`echo "${line}" | cut -d '/' -f 1` |
| 33 | file=`echo "${line}" | cut -d '/' -f 2- | rev | cut -b 5- | rev` | 35 | file=`echo "${line}" | cut -d '/' -f 2- | rev | cut -b 5- | rev` |
| 34 | if [[ ! ${file} =~ (AdminGroup|AdminUser|AdminUserLeftBar|CommentPluginExamples|EditorGroup|GroupTemplate|GroupViewTemplate|NobodyGroup|PatternSkinUserViewTemplate|ProjectContributor|RegistrationAgent|SitePreferences|UnprocessedRegistrations|UnprocessedRegistrationsLog|UserHomepageHeader|UserList|UserListByDateJoined|UserListByLocation|UserList|UserListHeader|WebAtom|WebChanges|WebCreateNewTopic|WebHome|WebIndex|WebLeftBar|WebLeftBarExample|WebNotify|WebPreferences|WebRss|WebSearch|WebSearchAdvanced|WebTopicList|WikiGroups|WikiUsers)$ ]]; then | 36 | if [[ ! ${file} =~ (AdminGroup|AdminUser|AdminUserLeftBar|CommentPluginExamples|EditorGroup|GroupTemplate|GroupViewTemplate|NobodyGroup|PatternSkinUserViewTemplate|ProjectContributor|RegistrationAgent|SitePreferences|UnprocessedRegistrations|UnprocessedRegistrationsLog|UserHomepageHeader|UserList|UserListByDateJoined|UserListByLocation|UserList|UserListHeader|WebAtom|WebChanges|WebCreateNewTopic|WebHome|WebIndex|WebLeftBar|WebLeftBarExample|WebNotify|WebPreferences|WebRss|WebSearch|WebSearchAdvanced|WebTopicList|WikiGroups|WikiUsers)$ ]]; then |
| 35 | realURL=${ogWiki}/${base}/${file} | 37 | doit='false' |
| 36 | time=`date --rfc-3339=seconds -ur /opt/Foswiki/data/${base}/${file}.txt | cut -d '+' -f 1` | 38 | if [ ! -s ${ogWiki}/${base}/${file}.HTM ]; then |
| 37 | mkdir -p ${ogWiki}/${base} | 39 | echo "NEW /opt/Foswiki/data/${base}/${file}.txt" |
| 38 | mkdir -p ${ogWiki}/${base}/`dirname ${file}` | 40 | doit='true' |
| 39 | echo -e "ogWiki=${ogWiki}\nogURL=${ogURL}\nrealURL=${realURL}\nogBase=${base}\nogFile=${file}\ntimestamp=${time}\n" > ${ogWiki}/${base}/${file}.md.md | 41 | elif [ /opt/Foswiki/data/${base}/${file}.txt -nt ${ogWiki}/${base}/${file}.HTM ]; then |
| 40 | echo "downloading ${ogURL}/${base}/${file}?cover=print" | 42 | echo "NEWER /opt/Foswiki/data/${base}/${file}.txt" |
| 41 | # Doesn't help with redownloads, coz natch a dynamic site isn't cached. But I can at least comment out the curl command during testing to save time. | 43 | date --rfc-3339=seconds -ur /opt/Foswiki/data/${base}/${file}.txt |
| 42 | curl --silent --no-progress-meter ${ogURL}/${base}/${file}?cover=print -o ${ogWiki}/${base}/${file}.HTM | 44 | date --rfc-3339=seconds -ur ${ogWiki}/${base}/${file}.HTM |
| 43 | # Attempt to separate user profiles from user content. Doesn't work when people turn their profiles into content. | 45 | doit='true' |
| 44 | if [[ "${base}" == "Main" ]]; then | 46 | fi |
| 45 | dest="unsorted" | 47 | if [[ ${doit} == "true" ]]; then |
| 46 | mkdir -p `dirname users/${file}` | 48 | realURL=${ogWiki}/${base}/${file} |
| 47 | sed -i -E ${ogWiki}/${base}/${file}.HTM -e "s%<a href=\"/System/UserForm\">UserForm</a>%%w users/${file}_fos.SED" | 49 | time=`date --rfc-3339=seconds -ur /opt/Foswiki/data/${base}/${file}.txt | cut -d '+' -f 1` |
| 48 | if [ -s users/${file}_fos.SED ]; then | 50 | mkdir -p ${ogWiki}/${base} |
| 49 | dest="users" | 51 | mkdir -p ${ogWiki}/${base}/`dirname ${file}` |
| 52 | echo -e "ogWiki=${ogWiki}\nogURL=${ogURL}\nrealURL=${realURL}\nogBase=${base}\nogFile=${file}\ntimestamp=${time}\n" > ${ogWiki}/${base}/${file}.md.md | ||
| 53 | echo "downloading ${ogURL}/${base}/${file}?cover=print" | ||
| 54 | # Doesn't help with redownloads, coz natch a dynamic site isn't cached. But I can at least comment out the curl command during testing to save time. | ||
| 55 | curl --silent --no-progress-meter ${ogURL}/${base}/${file}?cover=print -o ${ogWiki}/${base}/${file}.HTM | ||
| 56 | # Attempt to separate user profiles from user content. Doesn't work when people turn their profiles into content. | ||
| 57 | dest="" | ||
| 58 | if [[ "${base}" == "Main" ]]; then | ||
| 59 | dest="unsorted" | ||
| 60 | if [ -L users/${file}_fos.md ]; then | ||
| 61 | dest='users' | ||
| 62 | fi | ||
| 63 | mkdir -p `dirname users/${file}` | ||
| 64 | sed -i -E ${ogWiki}/${base}/${file}.HTM -e "s%<a href=\"/System/UserForm\">UserForm</a>%%w users/${file}_fos.SED" | ||
| 65 | if [ -s users/${file}_fos.SED ]; then | ||
| 66 | dest="users" | ||
| 67 | fi | ||
| 68 | rm users/${file}_fos.SED >/dev/null 2>&1 | ||
| 69 | rm -d `dirname users/${file}` >/dev/null 2>&1 | ||
| 70 | fi | ||
| 71 | # "Devuan" is only two pages that get sorted. "Sandbox" is a mixture of standard examples, stuff that was copied to PmWiki, and other things that should get unsorted. | ||
| 72 | # Skipping anything with "<a href="/Main/UnknownUser">UnknownUser</a></span></div>". | ||
| 73 | if [[ "${base}" == "Sandbox" ]]; then | ||
| 74 | dest="unsorted" | ||
| 75 | mkdir -p `dirname users/${file}` | ||
| 76 | sed -i -E ${ogWiki}/${base}/${file}.HTM -e "s%<a href=\"/Main/UnknownUser\">UnknownUser</a></span></div>%%w users/${file}_fos.SED" | ||
| 77 | if [ -s users/${file}_fos.SED ]; then | ||
| 78 | dest="" | ||
| 79 | fi | ||
| 80 | rm users/${file}_fos.SED >/dev/null 2>&1 | ||
| 81 | rm -d `dirname users/${file}` >/dev/null 2>&1 | ||
| 82 | fi | ||
| 83 | |||
| 84 | if [[ "${dest}" != "" ]]; then | ||
| 85 | mkdir -p `dirname ${dest}/${file}` | ||
| 86 | realURL=${dest}/${file} | ||
| 87 | echo -e "ogWiki=${ogWiki}\nogURL=${ogURL}\nrealURL=${realURL}_fos\nogBase=${base}\nogFile=${file}\ntimestamp=${time}\n" > ${ogWiki}/${base}/${file}.md.md | ||
| 88 | touch ${ogWiki}/${base}/${file}.md | ||
| 89 | ln -sfr ${ogWiki}/${base}/${file}.md ${dest}/${file}_fos.md | ||
| 90 | ln -sfr ${ogWiki}/${base}/${file}.md.md ${dest}/${file}_fos.md.md | ||
| 91 | rm ${ogWiki}/${base}/${file}.md | ||
| 50 | fi | 92 | fi |
| 51 | rm users/${file}_fos.SED | ||
| 52 | rm -d `dirname users/${file}` >/dev/null 2>&1 | ||
| 53 | mkdir -p `dirname ${dest}/${file}` | ||
| 54 | realURL=${dest}/${file} | ||
| 55 | echo -e "ogWiki=${ogWiki}\nogURL=${ogURL}\nrealURL=${realURL}_fos\nogBase=${base}\nogFile=${file}\ntimestamp=${time}\n" > ${ogWiki}/${base}/${file}.md.md | ||
| 56 | touch ${ogWiki}/${base}/${file}.md | ||
| 57 | ln -sfr ${ogWiki}/${base}/${file}.md ${dest}/${file}_fos.md | ||
| 58 | ln -sfr ${ogWiki}/${base}/${file}.md.md ${dest}/${file}_fos.md.md | ||
| 59 | rm ${ogWiki}/${base}/${file}.md | ||
| 60 | fi | 93 | fi |
| 61 | fi | 94 | fi |
| 62 | done | 95 | done |
| @@ -79,23 +112,38 @@ do | |||
| 79 | base=`echo "${line}" | cut -d '.' -f 1` | 112 | base=`echo "${line}" | cut -d '.' -f 1` |
| 80 | file=`echo "${line}" | cut -d '.' -f 2` | 113 | file=`echo "${line}" | cut -d '.' -f 2` |
| 81 | if [[ "${base}" != "Site" ]]; then | 114 | if [[ "${base}" != "Site" ]]; then |
| 82 | realURL=${ogWiki}/${base}/${file} | 115 | doit='false' |
| 83 | time=`date --rfc-3339=seconds -ur /opt/pmwiki/wiki.d/${base}.${file} | cut -d '+' -f 1` | 116 | if [ ! -s ${ogWiki}/${base}/${file}.HTM ]; then |
| 84 | mkdir -p ${ogWiki}/${base} | 117 | echo "NEW /opt/pmwiki/wiki.d/${base}.${file} ${ogWiki}/${base}/${file}.HTM" |
| 85 | echo -e "ogWiki=${ogWiki}\nogURL=${ogURL}\nrealURL=${realURL}\nogBase=${base}\nogFile=${file}\ntimestamp=${time}\n" > ${ogWiki}/${base}/${file}.md.md | 118 | doit='true' |
| 86 | # echo "downloading ${ogURL}/?n=${base}.${file}?action=markdown" | 119 | elif [ /opt/pmwiki/wiki.d/${base}.${file} -nt ${ogWiki}/${base}/${file}.HTM ]; then |
| 87 | # curl --no-progress-meter ${ogURL}/?n=${base}.${file}?action=markdown -o ${ogWiki}/${base}/${file}.MARKDOWN | 120 | echo "NEWER /opt/pmwiki/wiki.d/${base}.${file}" |
| 88 | echo "downloading ${ogURL}/?n=${base}.${file}?action=print" | 121 | date --rfc-3339=seconds -ur /opt/pmwiki/wiki.d/${base}.${file} |
| 89 | curl --no-progress-meter ${ogURL}/?n=${base}.${file}?action=print -o ${ogWiki}/${base}/${file}.HTM | 122 | date --rfc-3339=seconds -ur ${ogWiki}/${base}/${file}.HTM |
| 90 | # Seems there's no way to tell user profiles apart from user content. Unless I can find a list of users somewhere. Don't think there is one. | 123 | doit='true' |
| 91 | if [[ "${base}" == "Profiles" ]]; then | 124 | fi |
| 92 | dest="unsorted" | 125 | if [[ ${doit} == "true" ]]; then |
| 93 | realURL=${dest}/${file} | 126 | realURL=${ogWiki}/${base}/${file} |
| 94 | echo -e "ogWiki=${ogWiki}\nogURL=${ogURL}\nrealURL=${realURL}_pm\nogBase=${base}\nogFile=${file}\ntimestamp=${time}\n" > ${ogWiki}/${base}/${file}.md.md | 127 | time=`date --rfc-3339=seconds -ur /opt/pmwiki/wiki.d/${base}.${file} | cut -d '+' -f 1` |
| 95 | touch ${ogWiki}/${base}/${file}.md | 128 | mkdir -p ${ogWiki}/${base} |
| 96 | ln -sfr ${ogWiki}/${base}/${file}.md ${dest}/${file}_pm.md | 129 | echo -e "ogWiki=${ogWiki}\nogURL=${ogURL}\nrealURL=${realURL}\nogBase=${base}\nogFile=${file}\ntimestamp=${time}\n" > ${ogWiki}/${base}/${file}.md.md |
| 97 | ln -sfr ${ogWiki}/${base}/${file}.md.md ${dest}/${file}_pm.md.md | 130 | # echo "downloading ${ogURL}/?n=${base}.${file}?action=markdown" |
| 98 | rm ${ogWiki}/${base}/${file}.md | 131 | # curl --no-progress-meter ${ogURL}/?n=${base}.${file}?action=markdown -o ${ogWiki}/${base}/${file}.MARKDOWN |
| 132 | echo "downloading ${ogURL}/?n=${base}.${file}?action=print" | ||
| 133 | curl --no-progress-meter ${ogURL}/?n=${base}.${file}?action=print -o ${ogWiki}/${base}/${file}.HTM | ||
| 134 | # Seems there's no way to tell user profiles apart from user content. Unless I can find a list of users somewhere. Don't think there is one. | ||
| 135 | if [[ "${base}" == "Profiles" ]]; then | ||
| 136 | dest="unsorted" | ||
| 137 | if [ -L users/${file}_pm.md ]; then | ||
| 138 | dest='users' | ||
| 139 | fi | ||
| 140 | realURL=${dest}/${file} | ||
| 141 | echo -e "ogWiki=${ogWiki}\nogURL=${ogURL}\nrealURL=${realURL}_pm\nogBase=${base}\nogFile=${file}\ntimestamp=${time}\n" > ${ogWiki}/${base}/${file}.md.md | ||
| 142 | touch ${ogWiki}/${base}/${file}.md | ||
| 143 | ln -sfr ${ogWiki}/${base}/${file}.md ${dest}/${file}_pm.md | ||
| 144 | ln -sfr ${ogWiki}/${base}/${file}.md.md ${dest}/${file}_pm.md.md | ||
| 145 | rm ${ogWiki}/${base}/${file}.md | ||
| 146 | fi | ||
| 99 | fi | 147 | fi |
| 100 | 148 | ||
| 101 | # TODO - groups are PmWiki/Onefang and PmWiki/Tiki | 149 | # TODO - groups are PmWiki/Onefang and PmWiki/Tiki |
| @@ -107,6 +155,8 @@ done | |||
| 107 | 155 | ||
| 108 | 156 | ||
| 109 | time notYetAnotherWiki.lua | 157 | time notYetAnotherWiki.lua |
| 158 | # No idea why yet, but needs a second run to sort out everything. Shouldn't take long anyway. | ||
| 159 | time notYetAnotherWiki.lua | ||
| 110 | 160 | ||
| 111 | popd | 161 | popd |
| 112 | } | 162 | } |
diff --git a/SuckItClean b/SuckItClean new file mode 100755 index 0000000..1b8a025 --- /dev/null +++ b/SuckItClean | |||
| @@ -0,0 +1,13 @@ | |||
| 1 | #!/bin/bash | ||
| 2 | |||
| 3 | TIMEFORMAT=" took %lR using %P%% CPU" | ||
| 4 | time { | ||
| 5 | pushd /opt/nyaw | ||
| 6 | |||
| 7 | rm -fr Foswiki/* | ||
| 8 | rm -fr PmWiki/* | ||
| 9 | rm -fr unsorted | ||
| 10 | rm -fr users/* | ||
| 11 | popd | ||
| 12 | ./SuckIt | ||
| 13 | } | ||
| @@ -4,53 +4,53 @@ Make it perphekd! | |||
| 4 | 4 | ||
| 5 | ## Do these | 5 | ## Do these |
| 6 | 6 | ||
| 7 | Automate symlinks. | 7 | Convert it to polygLua. |
| 8 | 8 | ||
| 9 | - any .md.md file should be linked along with it's matching .md file if it's outside of Foswiki/ and PmWiki/. | 9 | It's all a bit too fragile, fix what I can. Too many messes colliding. |
| 10 | 10 | ||
| 11 | Other colour shenanigans. | 11 | Flock it. |
| 12 | 12 | ||
| 13 | TOC | 13 | Some sort of search system. |
| 14 | 14 | ||
| 15 | - Maybe have it on the left, as the sub menu of the current page's menu item, automatically generated from the $body$ headings. | 15 | A member system, and edit / manage system for their pages. |
| 16 | - Sub headings get sub menus etc. | ||
| 17 | 16 | ||
| 18 | Check the timestamps on the files, only update if source is newer than destination. Meh, it's already 600 times faster than the pandoc version. | 17 | Fix up linky conversion. DONE, mostly. |
| 19 | 18 | ||
| 20 | - One quirk to watch for is if a URL path changes, the docs that have that URL need to be redone. | 19 | - Need to deal with real file name versus title. Also symlink name not matching what it points to. |
| 21 | - pandoc is a lot slower though, so do this for sure when dealing with that. | ||
| 22 | - When scraping the web sites, they tend to be dynamically generated with no useful timestamp on them. | ||
| 23 | - The web site scrape happens locally anyway, I can compare source file timestamps. | ||
| 24 | 20 | ||
| 25 | Add atom feed for single page. Alas cgit only seems to have ATOM feed on the whole repo, not individual files. | 21 | Use the default.template that comes with nYAW if none is availaable. |
| 26 | 22 | ||
| 27 | - git.devuan.org might have usable per page history. | 23 | "collapsing headings" I guess that means click on a heading to hide / show the content under that heading. |
| 28 | - However, once timestamps are sorted, I can use that code to generate (static?) RSS and ATOM feeds, and create page histories using diffs. | ||
| 29 | 24 | ||
| 30 | Deal with complex directory trees. | 25 | - 🙈 |
| 26 | - Should do that for the main content and the menu TOC. | ||
| 27 | - Also allow editing just a section, a section being the bits between one heading and the next. | ||
| 28 | - + 📝 ✒️✏️🖊️🖋 🖌️🖍️ | ||
| 29 | - + When someone starts editing, create pagename_draft.md and .HTML, and update those when they want to see a preview. | ||
| 30 | - + Or pagename-heading_draft.md | ||
| 31 | - + Use that draft.md file as a lock on editing that file / section. | ||
| 32 | - + Have the hourly cron job remove any stale ones. | ||
| 31 | 33 | ||
| 32 | - /testing/even should display as even/deeper on the testing page, coz even/ has no files, but even/deeper does. | 34 | Add ATOM feed for single page. Alas cgit only seems to have ATOM feed on the whole repo, not individual files. |
| 33 | - On the other hand, I could just create an empty page with the sub directories shown as usual. | ||
| 34 | - Scanning /usr/share/doc on my super desktop with looots of software installed will be fun. | ||
| 35 | - On the gripping hand, this is where we want empty directories to vanish. | ||
| 36 | - SOOOOOOO don't show empty directories, but show their subs that have content, even if that sub is deep, but as per usual stop once we find a sub on that branch. EEEEW branches. | ||
| 37 | 35 | ||
| 38 | FIXTHEM: If there's a single word and period at the beginning of a line, it gets turned into a list, or list item by lunamark at the final Parse stage. | 36 | - However, once timestamps are sorted, I can use that code to generate RSS and ATOM feeds, and create page histories using diffs. |
| 37 | - Instead of an hourly cron job to update everything, see if I can hook | ||
| 38 | into Fos and Pm edit form's save function. So when they save in the | ||
| 39 | original wiki, the nyaw version gets updated, diffed, and ATOMed / RSSed. | ||
| 40 | - + Actually a BFI method might do the trick, stick with doing a full scan | ||
| 41 | and only updating the stuff that needs it, likely that's only the page that just got saved. | ||
| 42 | - git commit can have an arbitrary author / committer, so I can use that to make sure the person that actually made the change gets author / committer. | ||
| 43 | - + There's also the email thing, but I don't want to spread email addresses around, not even sure we have them anyway. | ||
| 44 | - Should also see if gitea can handle that, and if they want wiki content saved to git. | ||
| 39 | 45 | ||
| 46 | Syntax highlighting in code blocks. The highlight package looks promising, already had it installed on my desktop. | ||
| 40 | 47 | ||
| 41 | ## Some ideas | 48 | ## Some ideas |
| 42 | 49 | ||
| 43 | Mostly from something chomwitt deleted. | 50 | Mostly from something chomwitt wrote - |
| 44 | 51 | ||
| 45 | - A toolbar is mentioned, which is what I'm half way through creating with those hamburger / sunglasses icons, they are a bar of tools. | ||
| 46 | - Maybe tabs as well as a toolbar, for the list of sub directories. | ||
| 47 | - Syntax highlighting in code blocks. | ||
| 48 | - Allow default.template files in sub directories. | ||
| 49 | - Might be useful to automatically convert anything looking like a URL into a linky. | ||
| 50 | - "collapsing headings" I guess that means click on a heading to hide / show the content under that heading. | ||
| 51 | - + Should do that for the main content and the menu TOC. | ||
| 52 | - "validation", not sure exactly what that would validate. | 52 | - "validation", not sure exactly what that would validate. |
| 53 | - I'll just quote the entire rest - | 53 | - I'll just quote some of the rest - |
| 54 | 54 | ||
| 55 | ~~~ | 55 | ~~~ |
| 56 | !!! co-editing | 56 | !!! co-editing |
| @@ -59,17 +59,38 @@ Mostly from something chomwitt deleted. | |||
| 59 | ** for example search-completion to other workflows names-tags. | 59 | ** for example search-completion to other workflows names-tags. |
| 60 | ~~~ | 60 | ~~~ |
| 61 | 61 | ||
| 62 | - Allow default.template files in sub folders. | ||
| 63 | - Might be useful to automatically convert anything looking like a URL into a linky. | ||
| 64 | |||
| 65 | Automate symlinks. | ||
| 66 | |||
| 67 | - any .md.md file should be linked along with it's matching .md file if it's outside of Foswiki/ and PmWiki/. | ||
| 68 | |||
| 62 | 69 | ||
| 63 | ## Try out | 70 | ## Try out |
| 64 | 71 | ||
| 72 | lua-lpeg-patterns might be useful | ||
| 73 | |||
| 74 | lua-luxio might be the wheel I'm reinventing? | ||
| 75 | |||
| 76 | lua-wsapi-fcgi | ||
| 77 | |||
| 78 | https://inclusive-components.design/tooltips-toggletips/ has some ideas about the "tooltip" HTML attribute, and what to do about it. A rabbit hole that ends in javascript, but might be useful up to that point. | ||
| 79 | |||
| 65 | htmx | 80 | htmx |
| 66 | 81 | ||
| 67 | cgit has Lua | 82 | cgit has Lua |
| 68 | 83 | ||
| 84 | lua-gall for git stuff | ||
| 85 | |||
| 86 | lua-lace for access control | ||
| 87 | |||
| 88 | lua-unbound | ||
| 89 | |||
| 69 | 90 | ||
| 70 | ## User system | 91 | ## Member system |
| 71 | 92 | ||
| 72 | Reuse the user system from SledjChisl. | 93 | Reuse the member system from SledjChisl. |
| 73 | 94 | ||
| 74 | levels - | 95 | levels - |
| 75 | 96 | ||
| @@ -111,6 +132,6 @@ site, including configuration and modules. Likely this is the person | |||
| 111 | that set the system up in the first place. | 132 | that set the system up in the first place. |
| 112 | 133 | ||
| 113 | Admin should have access to everything that shell level has, but there's always things need tweaking at some lower level. | 134 | Admin should have access to everything that shell level has, but there's always things need tweaking at some lower level. |
| 114 | Built in file browser might do the trick. Would be useful for content creators to to organise the content. Naturally should obey the permissions. | 135 | Built in file browser might do the trick. Would be useful for content creators to organise the content. Naturally should obey the permissions. |
| 115 | 136 | ||
| 116 | root level is whoever controls the server things are running on. They can do anything at all. | 137 | root level is whoever controls the server things are running on. They can do anything at all. |
diff --git a/about/index.md b/about/index.md index 6086d85..3f15be7 100644 --- a/about/index.md +++ b/about/index.md | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | # notYetAnotherWiki is not another wiki, at least not yet. It'll be much more than that, eventually. | 1 | # notYetAnotherWiki is not another wiki, at least not yet. It'll be much more than that, eventually. |
| 2 | 2 | ||
| 3 | This is a new directory, an entire PR department can hang out here. | 3 | This is a new folder, an entire PR department can hang out here. |
| 4 | 4 | ||
| 5 | This would just be a duplicate of README, but for testing purposes. | 5 | This would just be a duplicate of README, but for testing purposes. |
diff --git a/default.template b/default.template index f87666c..baefad1 100644 --- a/default.template +++ b/default.template | |||
| @@ -17,37 +17,32 @@ | |||
| 17 | menu {list-style-type: none;} | 17 | menu {list-style-type: none;} |
| 18 | pre { | 18 | pre { |
| 19 | background-image: linear-gradient(to right, $PinkFloyd$, $onefangPurple$); | 19 | background-image: linear-gradient(to right, $PinkFloyd$, $onefangPurple$); |
| 20 | overflow-x: auto; | 20 | width: fit-content; max-width: 99%; overflow-x: auto; |
| 21 | width: 99%; | 21 | margin: 2px; border: 2px solid grey; |
| 22 | margin: 2px; | ||
| 23 | border: 2px solid grey; | ||
| 24 | } | 22 | } |
| 25 | table, td, th {border-collapse: collapse; border: 2px solid grey;} | 23 | table, td, th {border-collapse: collapse; border: 2px solid grey;} |
| 26 | 24 | ||
| 27 | .toolTip {background: darkcyan;} | 25 | .toolTip {background: darkcyan; font-size: 1.42em;} |
| 28 | 26 | ||
| 29 | .boxWrapper { | 27 | .boxWrapper { |
| 30 | height: 100%; width: 100%; | 28 | height: 100%; width: 100%; |
| 31 | margin: 0; padding: 0; border: none; | 29 | margin: 0; padding: 0; border: none; |
| 32 | display: grid; | 30 | display: grid; |
| 33 | // grid-template-areas: | 31 | // grid-template-areas: |
| 34 | // "logo0 trail" | 32 | // "logo tools tools tools" |
| 35 | // "logo1 head" | 33 | // "logo head head head" |
| 36 | // "menu body" | 34 | // "menu body body body" |
| 37 | // "history foot"; | 35 | // "history foot foot foot" |
| 38 | grid-template-columns: auto 1fr auto auto; | 36 | // "nyaw nyaw nyaw nyaw"; |
| 37 | grid-template-columns: 1.4fr 8fr auto auto; | ||
| 39 | grid-template-rows: auto auto 1fr auto auto; | 38 | grid-template-rows: auto auto 1fr auto auto; |
| 40 | // grid-auto-columns: minmax(auto, auto); | ||
| 41 | // grid-auto-rows: minmax(auto, auto); | ||
| 42 | overflow-x: auto; overflow-y: auto; | 39 | overflow-x: auto; overflow-y: auto; |
| 43 | } | 40 | } |
| 44 | .boxLogo0 {grid-area: logo0; grid-column: 1 / 1; grid-row: 1 / 1; height: min-content;} | 41 | .boxLogo {grid-area: logo; grid-column: 1 / 1; grid-row: 1 / 2; height: min-content;} |
| 45 | .boxLogo1 {grid-area: logo1; grid-column: 1 / 1; grid-row: 2 / 2; height: min-content;} | 42 | .boxTools {grid-area: tools; grid-column: 2 / 4; grid-row: 1 / 1; height: min-content;} |
| 46 | |||
| 47 | .boxTrail {grid-area: trail; grid-column: 2 / 4; grid-row: 1 / 1; height: min-content;} | ||
| 48 | .boxHead {grid-area: head; grid-column: 2 / 4; grid-row: 2 / 2; height: min-content; text-align: right;} | 43 | .boxHead {grid-area: head; grid-column: 2 / 4; grid-row: 2 / 2; height: min-content; text-align: right;} |
| 49 | 44 | ||
| 50 | .boxMenu {grid-area: menu; grid-column: 1 / 1; grid-row: 3 / 3; height: min-content; width: min-content; vertical-align: top; padding: 4px;} | 45 | .boxMenu {grid-area: menu; grid-column: 1 / 1; grid-row: 3 / 3; height: min-content; vertical-align: top; padding: 4px; overflow-x: auto; overflow-y: auto;} |
| 51 | .boxBody {grid-area: body; grid-column: 2 / 4; grid-row: 3 / 3; vertical-align: top; | 46 | .boxBody {grid-area: body; grid-column: 2 / 4; grid-row: 3 / 3; vertical-align: top; |
| 52 | height: 100%; width: 100%; | 47 | height: 100%; width: 100%; |
| 53 | background: black; color: white; | 48 | background: black; color: white; |
| @@ -59,23 +54,26 @@ | |||
| 59 | 54 | ||
| 60 | .boxHistory {grid-area: history; grid-column: 1 / 1; grid-row: 4 / 4; height: min-content;} | 55 | .boxHistory {grid-area: history; grid-column: 1 / 1; grid-row: 4 / 4; height: min-content;} |
| 61 | .boxFoot {grid-area: foot; grid-column: 2 / 4; grid-row: 4 / 4; height: min-content; text-align: right;} | 56 | .boxFoot {grid-area: foot; grid-column: 2 / 4; grid-row: 4 / 4; height: min-content; text-align: right;} |
| 62 | .boxnyaw {grid-area: foot; grid-column: 1 / 4; grid-row: 5 / 5; height: min-content; text-align: right; font-size: 0.55em;} | 57 | .boxnyaw {grid-area: nyaw; grid-column: 1 / 4; grid-row: 5 / 5; height: min-content; text-align: right; font-size: 0.55em;} |
| 63 | 58 | ||
| 64 | #modeToggleBody {display: none;} | 59 | #modeToggleBody {display: none;} |
| 65 | #modeToggleMenu {display: none;} | 60 | #modeToggleMenu {display: none;} |
| 66 | #modeBtn {color: white; display: inline-block;} | 61 | #modeBtn {color: white; display: inline-block;} |
| 67 | #modeToggleBody:checked ~ body background-image: linear-gradient($karenPurple$, $onefangPurple$);{} | ||
| 68 | #modeToggleBody:checked ~ pre {background-image: linear-gradient(to right, $onefangPurple$, $PinkFloyd$);} | ||
| 69 | #modeToggleBody:checked ~ .modeBtn {color: black;} | 62 | #modeToggleBody:checked ~ .modeBtn {color: black;} |
| 63 | // #modeToggleBody:checked ~ body background-image: linear-gradient($karenPurple$, $onefangPurple$);{} | ||
| 64 | // #modeToggleBody:checked ~ pre {background-image: linear-gradient(to right, $onefangPurple$, $PinkFloyd$);} | ||
| 65 | |||
| 66 | #modeToggleMenu:checked ~ .boxLogo {display: none;} | ||
| 67 | #modeToggleMenu:checked ~ .boxHead {display: none;} | ||
| 68 | // #modeToggleMenu:checked ~ .boxTools {display: none;} | ||
| 69 | // #modeToggleMenu:checked ~ .boxMenu {display: none; width: 0px; max-width: 0px; } | ||
| 70 | |||
| 70 | #modeToggleBody:checked ~ .boxBody {background: white; color: black;} | 71 | #modeToggleBody:checked ~ .boxBody {background: white; color: black;} |
| 71 | #modeToggleBody:checked ~ .boxBody a:active {color: $devuanDevuanalink$;} | 72 | #modeToggleBody:checked ~ .boxBody a:active {color: $devuanDevuanalink$;} |
| 72 | #modeToggleBody:checked ~ .boxBody a:link {color: $devuanDevuanlink$;} | 73 | #modeToggleBody:checked ~ .boxBody a:link {color: $devuanDevuanlink$;} |
| 73 | #modeToggleBody:checked ~ .boxBody a:visited {color: $devuanDevuanvlink$;} | 74 | #modeToggleBody:checked ~ .boxBody a:visited {color: $devuanDevuanvlink$;} |
| 74 | #modeToggleBody:checked ~ .boxBody a:hover {color: $devuanDevuanhlink$;} | 75 | #modeToggleBody:checked ~ .boxBody a:hover {color: $devuanDevuanhlink$;} |
| 75 | #modeToggleMenu:checked ~ .boxLogo0 {display: none;} | 76 | |
| 76 | #modeToggleMenu:checked ~ .boxHead {display: none;} | ||
| 77 | #modeToggleMenu:checked ~ .boxTrail {display: none;} | ||
| 78 | #modeToggleMenu:checked ~ .boxMenu {display: none;} | ||
| 79 | #modeToggleMenu:checked ~ .boxHistory {display: none;} | 77 | #modeToggleMenu:checked ~ .boxHistory {display: none;} |
| 80 | #modeToggleMenu:checked ~ .boxFoot {display: none;} | 78 | #modeToggleMenu:checked ~ .boxFoot {display: none;} |
| 81 | #modeToggleMenu:checked ~ .boxnyaw {display: none;} | 79 | #modeToggleMenu:checked ~ .boxnyaw {display: none;} |
| @@ -85,28 +83,36 @@ | |||
| 85 | <div class="boxWrapper"> | 83 | <div class="boxWrapper"> |
| 86 | <input type="checkbox" id="modeToggleMenu"/> | 84 | <input type="checkbox" id="modeToggleMenu"/> |
| 87 | <input type="checkbox" id="modeToggleBody"/> | 85 | <input type="checkbox" id="modeToggleBody"/> |
| 88 | <div class="boxLogo0"><header><nav> | 86 | <div class="boxLogo" id="top"><header><nav> |
| 89 | <a href="$home$"><img src="$logo$" alt="Not (Yet) (Another / A) Wiki." title="Not (Yet) (Another / A) Wiki."/></a> | 87 | <a href="$home$"><img src="$logo$" alt="not (Yet) (Another / A) Wiki."/></a> |
| 90 | </nav></header></div> | 88 | </nav></header></div> |
| 91 | <div class="boxLogo1"><header><nav> | 89 | <div class="boxTools"><header><nav> |
| 92 | <b class="toolTip" title="🍔 hides or shows non content. | 90 | <a href="/help.HTML"><b class="toolTip" title="🍔 hides / shows non content, reverse hamburger menu. |
| 93 | 🕶 switches between dark and light themes. | 91 | 🕶 switches between dark and light themes. |
| 92 | 📚 shows the list of all pages. | ||
| 93 | 🔮 a folder of unsorted pages. | ||
| 94 | 👥 shows the list of users. | ||
| 94 | 🪵 will be for logging in, when I have written that bit. | 95 | 🪵 will be for logging in, when I have written that bit. |
| 95 | 🔍 will be the search, when I have written that bit. | 96 | 🔍 will be the search, when I have written that bit. |
| 96 | 👣 is a trail of the steps to get here.">❓</b> | 97 | 👣 is a trail of the steps to get here.">❓</b></a> |
| 97 | <b class="toolTip"><label for="modeToggleMenu" class='modeBtn'>🍔</label></b> | 98 | <b class="toolTip"><label for="modeToggleMenu" class='modeBtn'>🍔</label></b> |
| 98 | <b class="toolTip"><label for="modeToggleBody" class='modeBtn'>🕶</label></b> | 99 | <b class="toolTip"><label for="modeToggleBody" class='modeBtn'>🕶</label></b> |
| 99 | <b class="toolTip">🪵</b> | 100 | <a href="/everything.HTML"><b class="toolTip">📚</b></a> |
| 100 | <b class="toolTip">🔍</b> | 101 | <a href="/unsorted/" ><b class="toolTip">🔮</b></a> |
| 102 | <a href="/users/" ><b class="toolTip">👥</b></a> | ||
| 103 | <b class="toolTip">🪵</b> | ||
| 104 | <b class="toolTip">🔍</b> | ||
| 105 | <b> 👣 $trail$ </b> | ||
| 101 | </nav></header></div> | 106 | </nav></header></div> |
| 102 | <div class="boxTrail"><header><nav><b> 👣 $trail$ </b></nav></header></div> | ||
| 103 | <div class="boxHead"><header><nav><b>$header$</b> </nav></header></div> | 107 | <div class="boxHead"><header><nav><b>$header$</b> </nav></header></div> |
| 108 | |||
| 104 | <div class="boxMenu"><nav><p><b>$menu$</b></p></nav></div> | 109 | <div class="boxMenu"><nav><p><b>$menu$</b></p></nav></div> |
| 105 | <div class="boxBody"><main>$body$<br/></main></div> | 110 | <div class="boxBody"><main>$body$<br/></main></div> |
| 111 | |||
| 106 | <div class="boxHistory"><footer>$history$</footer></div> | 112 | <div class="boxHistory"><footer>$history$</footer></div> |
| 107 | <div class="boxFoot"><footer>$footer$</footer></div> | 113 | <div class="boxFoot"><footer>$footer$</footer></div> |
| 108 | <div class="boxnyaw"><footer> | 114 | <div class="boxnyaw"><footer> |
| 109 | <p>Powered by <a href="https://sledjhamr.org/cgit/notYetAnotherWiki/about/">notYetAnotherWiki</a> v 0.0 No cookies or scripts where harmed in the making of this web site. May contain low fat CSS.</p> | 115 | <p>Powered by <a href="https://sledjhamr.org/notYetAnotherWiki/">notYetAnotherWiki</a> v 0.0 No cookies or scripts where harmed in the making of this web site. May contain low fat CSS.</p> |
| 110 | </footer></div> | 116 | </footer></div> |
| 111 | </div> | 117 | </div> |
| 112 | </body> | 118 | </body> |
diff --git a/feed-icon-14x14.png b/feed-icon-14x14.png new file mode 100755 index 0000000..b3c949d --- /dev/null +++ b/feed-icon-14x14.png | |||
| Binary files differ | |||
diff --git a/feed-icon-28x28.png b/feed-icon-28x28.png new file mode 100755 index 0000000..d64c669 --- /dev/null +++ b/feed-icon-28x28.png | |||
| Binary files differ | |||
| @@ -0,0 +1,43 @@ | |||
| 1 | # How to use this wiki | ||
| 2 | |||
| 3 | On the top left, is the logo, beside that is a toolbar of icons - | ||
| 4 | |||
| 5 | - ❓ hover over this for help. | ||
| 6 | - 🍔 hides or shows everything but the content and these icons, the reverse hamburger menu. | ||
| 7 | - 🕶 switches between dark and light themes. | ||
| 8 | - 📚 shows the list of all pages. | ||
| 9 | - 🔮 a folder of unsorted pages. | ||
| 10 | - 👥 shows the list of users. | ||
| 11 | - 🪵 will be for logging in, when I have written that bit. | ||
| 12 | - 🔍 will be the search, when I have written that bit. | ||
| 13 | |||
| 14 | 👣 is a trail of breadcrumbs, though I'm using a footsteps icon | ||
| 15 | for this. Showing the footsteps you have followed to get to the current | ||
| 16 | folder. | ||
| 17 | |||
| 18 | On the top right of the pages is links to the sub folders of the current | ||
| 19 | folder the current page is in. | ||
| 20 | |||
| 21 | Down the left side is links to the pages in the current folder. Most of | ||
| 22 | them will be symlinks to the converted pages from the Foswiki and PmWiki | ||
| 23 | sub folders. Some will be links ☝ to external sites. For the | ||
| 24 | current page, links to the headings are also shown, those headings have | ||
| 25 | their own icon 🔼to go back to the top. | ||
| 26 | |||
| 27 | The bit you are reading is the badly converted content of the current | ||
| 28 | page. At the bottom of each converted page is a link to the original, | ||
| 29 | and if you are logged into that other system, you might be able to edit | ||
| 30 | the page. Note that unconverted pages don't have these links to the | ||
| 31 | originals. | ||
| 32 | |||
| 33 | At the bottom is links to things like page history, web site source code, | ||
| 34 | and the software I'm writing to do all of this. Or should be some day. | ||
| 35 | |||
| 36 | |||
| 37 | |||
| 38 | # Under the hood | ||
| 39 | |||
| 40 | Internally this wiki is made of the root folder and it's sub folders | ||
| 41 | representing the structure of the wiki content. Each folder has it's own | ||
| 42 | pages. Symlinks are used to copy or move pages around, with special | ||
| 43 | folders for the original stuff from the other wikis. | ||
diff --git a/notYetAnotherWiki.lua b/notYetAnotherWiki.lua index 8be3850..f53691b 100755 --- a/notYetAnotherWiki.lua +++ b/notYetAnotherWiki.lua | |||
| @@ -15,7 +15,7 @@ local RE = require("re") -- Part of lpeg. https://www.inf.puc-rio.br/~roberto/ | |||
| 15 | -- Some global data. | 15 | -- Some global data. |
| 16 | 16 | ||
| 17 | local GlobalMetaData = { | 17 | local GlobalMetaData = { |
| 18 | dlr = '$', perc = '%', | 18 | dlr = '$', perc = '%', dot = '.', |
| 19 | devuanCinnabarDark = '#310202', devuanCinnabarLight = '#510505', | 19 | devuanCinnabarDark = '#310202', devuanCinnabarLight = '#510505', |
| 20 | devuanDarkPurpyDark = '#33313b', devuanDarkPurpyLight = '#3c3a45', | 20 | devuanDarkPurpyDark = '#33313b', devuanDarkPurpyLight = '#3c3a45', |
| 21 | devuanDeepSeaDark = '#132f40', devuanDeepSeaLight = '#1a4562', | 21 | devuanDeepSeaDark = '#132f40', devuanDeepSeaLight = '#1a4562', |
| @@ -31,6 +31,7 @@ local GlobalMetaData = { | |||
| 31 | } | 31 | } |
| 32 | 32 | ||
| 33 | local Files, Subs, xLinks = {}, {}, {} | 33 | local Files, Subs, xLinks = {}, {}, {} |
| 34 | local Context = {} -- Coz can't otherwise pass context through to the deeper Lunamark functions I'm overriding. | ||
| 34 | 35 | ||
| 35 | local Template = '' | 36 | local Template = '' |
| 36 | local h = io.open("default.template", 'r') | 37 | local h = io.open("default.template", 'r') |
| @@ -87,6 +88,7 @@ local toFile = function(name, key, value) | |||
| 87 | local bits, bit = stringBits(name) | 88 | local bits, bit = stringBits(name) |
| 88 | local path = '' | 89 | local path = '' |
| 89 | Files[name] = {} | 90 | Files[name] = {} |
| 91 | Files[name].headers = {} | ||
| 90 | Files[name].bits = bits | 92 | Files[name].bits = bits |
| 91 | Files[name].bit = bit | 93 | Files[name].bit = bit |
| 92 | for i, d in ipairs(bits) do | 94 | for i, d in ipairs(bits) do |
| @@ -107,6 +109,7 @@ local toFile = function(name, key, value) | |||
| 107 | h = io.open(name .. '.md', 'r') | 109 | h = io.open(name .. '.md', 'r') |
| 108 | if nil ~= h then | 110 | if nil ~= h then |
| 109 | -- print('Parsing ' .. name .. '.md') | 111 | -- print('Parsing ' .. name .. '.md') |
| 112 | Context = Files[name] | ||
| 110 | body = h:read('*a') ; h:close() | 113 | body = h:read('*a') ; h:close() |
| 111 | -- Deal with my typical double spaced sentence endings, and other things. | 114 | -- Deal with my typical double spaced sentence endings, and other things. |
| 112 | local result = RE.compile( [=[{~ | 115 | local result = RE.compile( [=[{~ |
| @@ -119,10 +122,13 @@ local toFile = function(name, key, value) | |||
| 119 | {":::"} -> '' / | 122 | {":::"} -> '' / |
| 120 | {"-noComment-"} -> ' -- ' / | 123 | {"-noComment-"} -> ' -- ' / |
| 121 | {"| bgcolor=#" {([^ ])+} " " } -> "| <span style='background: #%2;'> bgcolor=#%2 </span> " / -- Deal with debdog's color table. | 124 | {"| bgcolor=#" {([^ ])+} " " } -> "| <span style='background: #%2;'> bgcolor=#%2 </span> " / -- Deal with debdog's color table. |
| 125 | {"[" {([^]])+} ']{style="color: ' {([^}])+} "}" } -> "<span style='color: %3;'>%2</span>" / | ||
| 126 | {"[" {([^]])+} "]{style='color: " {([^}])+} "}" } -> "<span style='color: %3;'>%2</span>" / | ||
| 122 | {"{#"[A-Za-z_]+"}"} -> '' / | 127 | {"{#"[A-Za-z_]+"}"} -> '' / |
| 123 | {"### [[edit](/bin/edit/Main/" {([^%nl])+} } -> '' / | 128 | {"### [[edit](/bin/edit/Main/" {([^%nl])+} } -> '' / |
| 129 | {"#"+ " " {([^%nl])+} } -> header / | ||
| 124 | . | 130 | . |
| 125 | )* ~}]=], { } ):match(body) | 131 | )* ~}]=], { header = function(a) table.insert(Context.headers, a); return a end } ):match(body) |
| 126 | body = result | 132 | body = result |
| 127 | -- {"<!--".*"-->"} -> '' / | 133 | -- {"<!--".*"-->"} -> '' / |
| 128 | -- {"[$]"} -> '$dlr$' / -- Replace $, coz otherwise it confuses things later. | 134 | -- {"[$]"} -> '$dlr$' / -- Replace $, coz otherwise it confuses things later. |
| @@ -209,47 +215,116 @@ else | |||
| 209 | print("Can't open everything.md for writing.") | 215 | print("Can't open everything.md for writing.") |
| 210 | end | 216 | end |
| 211 | 217 | ||
| 212 | -- Scan the subdirectories looking for our files. | 218 | -- Scan the sub folders looking for our files. |
| 213 | local Directory = arg[1] | 219 | local Folder = arg[1] |
| 214 | toSub('') | 220 | toSub('') |
| 215 | if nil == Directory then Directory = '.' end | 221 | if nil == Folder then Folder = '.' end |
| 216 | 222 | --GlobalMetaData.root = Folder | |
| 217 | -- Sort out realURL for symlinked .md.md files. | 223 | |
| 218 | for l in io.popen('find -L ' .. Directory .. ' -name "*.md.md" -xtype l -printf "%P\n"'):lines() do | 224 | --[[ Sort out realURL for symlinked .md.md files. |
| 225 | realURL is the generic URL part for this page. By policy it points to whatever is the latest copy / symlink of the original download .md.md. | ||
| 226 | realURL starts out being the path to the downloaded file and friends. | ||
| 227 | If we make a symlink during SuckIt, then that gets updated to point to the place the symlink is in. | ||
| 228 | below we compare timestamps and select the latest version if there's more than one symlink. | ||
| 229 | For the "page symlinked" problem, this should work if realURL is kept updated. | ||
| 230 | For the "page copied" problem, this should work if realURL is kept updated, same as symlinked really, coz that's just another copy. | ||
| 231 | For the "page moved" problem, that'll be the most recent symlink, the old one still has it's symlink pointing to the download .md.md, which gets updated with the current realURL. | ||
| 232 | So when some external old URL points to someplace a page used to be, it's old symlink points to the up to date download .md.md, and we know where to go to find the page now. | ||
| 233 | A left over .md.md file should have a redirect .HTML page created for it. | ||
| 234 | ]] | ||
| 235 | for l in io.popen('find -L ' .. Folder .. ' -name unsorted -prune -o -name "*.md.md" -xtype l -printf "%P\n"'):lines() do | ||
| 219 | local metadata = readMdMd(string.sub(l, 1, -4), {}) | 236 | local metadata = readMdMd(string.sub(l, 1, -4), {}) |
| 220 | -- FIXME - if this already exists, compare the timestamps, most recent wins. | 237 | if nil == metadata.realURL then |
| 221 | metadata.realURL = string.sub(l, 1, -7) | 238 | metadata.realURL = string.sub(l, 1, -7) |
| 222 | local a, e = io.open(l, 'w') | 239 | else |
| 223 | if nil == a then print('Could not open ' .. l .. ' - ' .. e) else | 240 | if metadata.realURL ~= string.sub(l, 1, -7) then |
| 224 | for k, v in pairs(metadata) do | 241 | metadata.realURL = string.sub(l, 1, -7) |
| 225 | a:write(k .. '=' .. v .. '\n') | 242 | -- If this already exists, compare the timestamps, most recent wins. |
| 243 | local time0 = io.popen('ls -l --time-style=+%s "' .. metadata.realURL .. '.md.md" | cut -d \' \' -f 6'):read('l') | ||
| 244 | local time1 = io.popen('ls -l --time-style=+%s "' .. l .. '" | cut -d \' \' -f 6'):read('l') | ||
| 245 | if time0 > time1 then metadata = nil end | ||
| 246 | else metadata = nil end | ||
| 247 | end | ||
| 248 | |||
| 249 | if nil ~= metadata then | ||
| 250 | -- DUNNO if this writes to the original file, or overwrites the symlink. | ||
| 251 | local a, e = io.open(l, 'w') | ||
| 252 | if nil == a then print('Could not open ' .. l .. ' - ' .. e) else | ||
| 253 | for k, v in pairs(metadata) do | ||
| 254 | a:write(k .. '=' .. v .. '\n') | ||
| 255 | end | ||
| 256 | a:close() | ||
| 226 | end | 257 | end |
| 227 | a:close() | ||
| 228 | end | 258 | end |
| 229 | end | 259 | end |
| 230 | 260 | ||
| 231 | for l in io.popen('find -L ' .. Directory .. ' -name "*.HTM" -type f,l -printf "%P\n"'):lines() do | 261 | -- Clean up unsorted. |
| 232 | -- print('pandoc converting ' .. l .. ' -> ' .. string.sub(l, 1, -4) .. 'md') | 262 | for l in io.popen('find -L ' .. Folder .. ' -name unsorted -prune -o -name "*.md" -a -not -name "*.md.md" -xtype l -printf "%P\n"'):lines() do |
| 233 | -- Open the HTM files and do the initial cleanups, then pandoc them. | 263 | local tp = '_fos' |
| 234 | h = io.open(l, 'r') | 264 | local metadata = readMdMd(l, {}) |
| 235 | if nil ~= h then | 265 | if nil ~= metadata then |
| 236 | local body = h:read('*a') ; h:close() | 266 | if "PmWiki" == metadata.ogWiki then tp = '_pm' end |
| 237 | if 'Foswiki' == string.sub(l, 1, 7) then | 267 | if nil ~= metadata.ogFile then |
| 238 | -- Strip out the actual content. | 268 | local unsort = 'unsorted/' .. metadata.ogFile |
| 239 | local beg, en = RE.find(body, [['<div id="patternMainContents">']]) if nil ~= beg then body = string.sub(body, en + 1) end | 269 | local a, e = io.open(unsort .. tp .. '.md' , 'r') |
| 240 | beg, en = RE.find(body, [['<div class="patternContent">']]) if nil ~= beg then body = string.sub(body, en + 1) end | 270 | if nil ~= a then |
| 241 | beg, en = RE.find(body, [['<div class="foswikiTopic">']]) if nil ~= beg then | 271 | a:close() |
| 242 | if ' -- ' == string.sub(body, en + 1, en + 4) then | 272 | -- Keep the .md.md symlink, delete the rest. |
| 243 | beg, en = RE.find(body, '[%nl]', en + 4) | 273 | os.execute('rm ' .. unsort .. tp .. '.HTML') |
| 244 | body = string.sub(body, en + 1) | 274 | os.execute('rm ' .. unsort .. tp .. '.md') |
| 275 | a, e = io.open(unsort .. tp .. '.HTML', 'w') | ||
| 276 | if nil == a then print('Could not open ' .. unsort .. tp .. '.HTML' .. ' - ' .. e) else | ||
| 277 | local dst = string.sub(l, 1, -4) .. '.HTML' | ||
| 278 | local cnt = 1 | ||
| 279 | for j = 1, #metadata.ogFile do | ||
| 280 | if '/' == string.sub(metadata.ogFile, j, j) then cnt = cnt + 1 end | ||
| 281 | end | ||
| 282 | dst = string.rep('../', cnt) .. dst | ||
| 283 | a:write( | ||
| 284 | [=[<!DOCTYPE html> | ||
| 285 | <html> | ||
| 286 | <head><meta http-equiv="refresh" content="0; url=]=] .. dst .. '"' .. [=[/></head> | ||
| 287 | <body><p>Click this if you don't get redirected to the real page - <a href="]=] .. dst .. '"' .. [=[>Redirect</a></p></body> | ||
| 288 | </html> | ||
| 289 | ]=]) | ||
| 290 | a:close() | ||
| 291 | print('REDIRECT ' .. unsort .. tp .. '.HTML \t-> ' .. dst) | ||
| 245 | end | 292 | end |
| 293 | |||
| 246 | end | 294 | end |
| 247 | beg, en = RE.find(body, [['<div class="patternInfo">']]) if nil ~= beg then body = string.sub(body, 1, beg - 1) end | 295 | end |
| 248 | -- beg, en = RE.find(body, [['<div class="foswikiForm foswikiFormStep">']]) if nil ~= beg then body = string.sub(body, 1, en + 1) end | 296 | end |
| 249 | beg, en = RE.find(body, [['<div class="foswikiAttachments foswikiFormStep" style="overflow:auto">']]) if nil ~= beg then body = string.sub(body, 1, beg - 1) end | 297 | end |
| 250 | beg, en = RE.find(body, [['<div class="foswikiSearchResultsPager">']]) if nil ~= beg then body = string.sub(body, 1, beg - 1) end | 298 | |
| 251 | -- Some clean ups. | 299 | -- Look for copied pages from the other wikis. |
| 252 | local result = RE.compile( [[{~ | 300 | for l in io.popen('find -L ' .. Folder .. ' -name "*.HTM" -type f,l -printf "%P\n"'):lines() do |
| 301 | -- Only do this if .HTM is newer than .md, or .md doesn't exist. | ||
| 302 | local htime = io.popen("date -ur " .. l .. " +%s"):read('l') | ||
| 303 | local mtime = io.popen("date -ur " .. string.sub(l, 1, -4) .. "md +%s 2>/dev/null"):read('l') | ||
| 304 | if (nil == mtime) or (htime > mtime) then | ||
| 305 | print('pandoc converting ' .. l .. ' -> ' .. string.sub(l, 1, -4) .. 'md') | ||
| 306 | os.execute('cp ' .. l .. ' ' .. l .. '_ORIGINAL0') | ||
| 307 | -- Open the HTM files and do the initial cleanups, then pandoc them. | ||
| 308 | h = io.open(l, 'r') | ||
| 309 | if nil ~= h then | ||
| 310 | local body = h:read('*a') ; h:close() | ||
| 311 | writeString(l .. '_ORIGINAL1', body) | ||
| 312 | if 'Foswiki' == string.sub(l, 1, 7) then | ||
| 313 | -- Strip out the actual content. | ||
| 314 | local beg, en = RE.find(body, [['<div id="patternMainContents">']]) if nil ~= beg then body = string.sub(body, en + 1) end | ||
| 315 | beg, en = RE.find(body, [['<div class="patternContent">']]) if nil ~= beg then body = string.sub(body, en + 1) end | ||
| 316 | beg, en = RE.find(body, [['<div class="foswikiTopic">']]) if nil ~= beg then | ||
| 317 | if ' -- ' == string.sub(body, en + 1, en + 4) then | ||
| 318 | beg, en = RE.find(body, '[%nl]', en + 4) | ||
| 319 | body = string.sub(body, en + 1) | ||
| 320 | end | ||
| 321 | end | ||
| 322 | beg, en = RE.find(body, [['<div class="patternInfo">']]) if nil ~= beg then body = string.sub(body, 1, beg - 1) end | ||
| 323 | -- beg, en = RE.find(body, [['<div class="foswikiForm foswikiFormStep">']]) if nil ~= beg then body = string.sub(body, 1, en + 1) end | ||
| 324 | beg, en = RE.find(body, [['<div class="foswikiAttachments foswikiFormStep" style="overflow:auto">']]) if nil ~= beg then body = string.sub(body, 1, beg - 1) end | ||
| 325 | beg, en = RE.find(body, [['<div class="foswikiSearchResultsPager">']]) if nil ~= beg then body = string.sub(body, 1, beg - 1) end | ||
| 326 | -- Some clean ups. | ||
| 327 | local result = RE.compile( [[{~ | ||
| 253 | ( | 328 | ( |
| 254 | {'class="foswikiCurrentTopicLink"'} -> blank / | 329 | {'class="foswikiCurrentTopicLink"'} -> blank / |
| 255 | {'class="foswikiNewLink"'} -> blank / | 330 | {'class="foswikiNewLink"'} -> blank / |
| @@ -263,41 +338,58 @@ for l in io.popen('find -L ' .. Directory .. ' -name "*.HTM" -type f,l -printf " | |||
| 263 | -- {'style="' ([^"])+ '"'} -> blank / {"style='" ([^'])+ "'"} -> blank / | 338 | -- {'style="' ([^"])+ '"'} -> blank / {"style='" ([^'])+ "'"} -> blank / |
| 264 | . | 339 | . |
| 265 | )* ~}]], { blank = function(a) return '' end } ):match(body) | 340 | )* ~}]], { blank = function(a) return '' end } ):match(body) |
| 266 | body = result | 341 | body = result |
| 267 | -- body = RE.gsub(body, [=[{"<!-- ".*"-->"}]=], '') -- FIXME | 342 | -- body = RE.gsub(body, [=[{"<!-- ".*"-->"}]=], '') -- FIXME |
| 268 | local here = 1 | 343 | local here = 1 |
| 269 | beg, en = RE.find(body, [['https://fos.wiki.devuan.org/']], here) | 344 | beg, en = RE.find(body, [['https://fos.wiki.devuan.org/']], here) |
| 270 | while nil ~= beg do | 345 | while nil ~= beg do |
| 271 | here = beg + 1 | 346 | here = beg + 1 |
| 272 | local beg0, en0 | 347 | local beg0, en0 |
| 273 | local url = nil | 348 | local url = nil |
| 274 | if '"' == string.sub(body, beg - 1, beg - 1) then | 349 | if '"' == string.sub(body, beg - 1, beg - 1) then |
| 275 | beg0, en0 = RE.find(body, [['"']], en) | 350 | beg0, en0 = RE.find(body, [['"']], en) |
| 276 | url = string.sub(body, en + 1, en0 - 1) | 351 | url = string.sub(body, en + 1, en0 - 1) |
| 277 | end | 352 | end |
| 278 | if "'" == string.sub(body, beg - 1, beg - 1) then | 353 | if "'" == string.sub(body, beg - 1, beg - 1) then |
| 279 | beg0, en0 = RE.find(body, [["'"]], en) | 354 | beg0, en0 = RE.find(body, [["'"]], en) |
| 280 | url = string.sub(body, en + 1, en0) | 355 | url = string.sub(body, en + 1, en0) |
| 281 | end | 356 | end |
| 282 | 357 | ||
| 283 | if nil ~= url then | 358 | if nil ~= url then |
| 284 | if ('pub/' == string.sub(url, 1, 4)) then | 359 | if ('pub/' == string.sub(url, 1, 4)) then |
| 285 | -- FIXME? - evil hack? | 360 | -- FIXME? - evil hack? |
| 286 | url = 'Foswiki/' .. url | 361 | url = 'Foswiki/' .. url |
| 287 | else | 362 | --print('FOSWIKI HTM ' .. url) |
| 288 | url = nil | 363 | else |
| 364 | url = nil | ||
| 365 | end | ||
| 289 | end | 366 | end |
| 367 | --print('HTM0 ' .. string.sub(body, beg, en + 84) .. ' \t\t') | ||
| 368 | beg, en, body, here = commonLinky(l, body, 'https://fos.wiki.devuan.org/', url, beg, en, beg0, en0, 1) | ||
| 369 | --if nil ~= en then print('HTM1 ' .. string.sub(body, beg, en + 84) .. ' \t\t') end | ||
| 370 | --[=[ | ||
| 371 | if nil == url then | ||
| 372 | print('OOPS! unknown linky - @' .. l .. '\t\t\t' .. string.sub(body, beg - 9, en) .. ' ' .. string.sub(body, en + 1, en0)) | ||
| 373 | else | ||
| 374 | -- print(' linky - @' .. l .. '\t\t\t' .. string.sub(body, beg - 9, en) .. ' ' .. string.sub(body, en + 1, en0) .. ' -> ' .. url) | ||
| 375 | local md = readMdMd(url, {}) | ||
| 376 | -- if nil ~= md then | ||
| 377 | if nil ~= md.realURL then url = md.realURL end | ||
| 378 | -- end | ||
| 379 | body = string.sub(body, 1, beg - 1) .. url .. string.sub(body, en0 + 1) | ||
| 380 | here = here + #url | ||
| 381 | end | ||
| 382 | beg, en = RE.find(body, [['https://fos.wiki.devuan.org/']], here) | ||
| 383 | ]=] | ||
| 290 | end | 384 | end |
| 291 | beg, en, body, here = commonLinky(l, body, 'https://fos.wiki.devuan.org/', url, beg, en, beg0, en0, 1) | ||
| 292 | end | ||
| 293 | 385 | ||
| 294 | writeString(l .. '_NEW', body) | 386 | writeString(l .. '_NEW', body) |
| 295 | elseif 'PmWiki' == string.sub(l, 1, 6) then | 387 | elseif 'PmWiki' == string.sub(l, 1, 6) then |
| 296 | local beg, en = RE.find(body, [['<!--PageText-->']]) if nil ~= beg then body = string.sub(body, en + 2) end | 388 | local beg, en = RE.find(body, [['<!--PageText-->']]) if nil ~= beg then body = string.sub(body, en + 2) end |
| 297 | beg, en = RE.find(body, [["div id='wikitext'>"]]) if nil ~= beg then body = string.sub(body, en + 2) end | 389 | beg, en = RE.find(body, [["div id='wikitext'>"]]) if nil ~= beg then body = string.sub(body, en + 2) end |
| 298 | beg, en = RE.find(body, [["<div id='printfoot'>"]]) if nil ~= beg then body = string.sub(body, 1, beg - (2 + 9)) end -- There's a </div> to get rid of to. | 390 | beg, en = RE.find(body, [["<div id='printfoot'>"]]) if nil ~= beg then body = string.sub(body, 1, beg - (2 + 9)) end -- There's a </div> to get rid of to. |
| 299 | beg, en = RE.find(body, [['<!--HTMLFooter-->']]) if nil ~= beg then body = string.sub(body, 1, beg - 2) end | 391 | beg, en = RE.find(body, [['<!--HTMLFooter-->']]) if nil ~= beg then body = string.sub(body, 1, beg - 2) end |
| 300 | local result = RE.compile( [[{~ | 392 | local result = RE.compile( [[{~ |
| 301 | ( | 393 | ( |
| 302 | {"class='categorylink'"} -> blank / | 394 | {"class='categorylink'"} -> blank / |
| 303 | {"class='createlink'"} -> blank / | 395 | {"class='createlink'"} -> blank / |
| @@ -317,41 +409,53 @@ for l in io.popen('find -L ' .. Directory .. ' -name "*.HTM" -type f,l -printf " | |||
| 317 | {"<span class='hlt " {([a-z])+} "'></span><pre" } -> "<pre class='%2'" / | 409 | {"<span class='hlt " {([a-z])+} "'></span><pre" } -> "<pre class='%2'" / |
| 318 | . | 410 | . |
| 319 | )* ~}]], { blank = function(a) return '' end } ):match(body) | 411 | )* ~}]], { blank = function(a) return '' end } ):match(body) |
| 320 | body = result | 412 | body = result |
| 321 | here = 1 | 413 | -- body = RE.gsub(body, [=["<a " {([^ >])+} " >"]=], "<a %1>") |
| 322 | beg, en = RE.find(body, [["'https://wiki.devuan.org/"]], here) | 414 | -- DONE? - <span class='hlt html'></span><pre style='background-color: #cc00ff;' class='escaped'> ... lines of HTML code ... </pre> |
| 323 | while nil ~= beg do | 415 | -- most of the time I'll see <pre class='escaped'> |
| 324 | here = beg + 1 | 416 | -- My own looking glass has several. |
| 325 | local beg0, en0 = RE.find(body, [["'"]], en) | 417 | -- Foswiki <pre class='bash'> |
| 418 | -- CommonMark->HTML ---lua <pre><code class="language-lua"> .............................. </code></pre> | ||
| 419 | -- Seems to be the spec way of doing it. | ||
| 420 | -- most of the time I'll see <pre><code> | ||
| 421 | |||
| 422 | here = 1 | ||
| 423 | beg, en = RE.find(body, [["'https://wiki.devuan.org/"]], here) | ||
| 424 | while nil ~= beg do | ||
| 425 | here = beg + 1 | ||
| 426 | local beg0, en0 = RE.find(body, [["'"]], en) | ||
| 326 | -- FIXME? - This might be working around a bug elsewhere. | 427 | -- FIXME? - This might be working around a bug elsewhere. |
| 327 | if "'" == string.sub(body, en0, en0) then en0 = en0 - 1 end | 428 | if "'" == string.sub(body, en0, en0) then en0 = en0 - 1 end |
| 328 | local url = string.sub(body, en + 1, en0) | 429 | local url = string.sub(body, en + 1, en0) |
| 329 | if '?n=' == string.sub(url, 1, 3) then | 430 | if '?n=' == string.sub(url, 1, 3) then |
| 330 | url = string.sub(url, 4):gsub('[%a]+%.([%a-]+)', '%1_pm.HTML') | 431 | url = string.sub(url, 4):gsub('[%a]+%.([%a-]+)', '%1_pm.HTML') |
| 331 | elseif ("'" == url) or ('uploads/' == string.sub(url, 1, 8)) then | 432 | elseif ("'" == url) or ('uploads/' == string.sub(url, 1, 8)) then |
| 332 | -- FIXME - evil hack? Yep, evil hack, need to know the depth of the source, which isn't here. | 433 | -- FIXME - evil hack? Yep, evil hack, need to know the depth of the source, which isn't here. |
| 333 | url = 'PmWiki/' .. url | 434 | url = 'PmWiki/' .. url |
| 334 | else | 435 | else |
| 335 | url = nil | 436 | url = nil |
| 437 | end | ||
| 438 | --print('HTM0 ' .. string.sub(body, beg, en + 84) .. ' \t\t') | ||
| 439 | beg, en, body, here = commonLinky(l, body, "'https://wiki.devuan.org/", url, beg, en, beg0, en0, 0) | ||
| 440 | --if nil ~= en then print('HTM1 ' .. string.sub(body, beg, en + 84) .. ' \t\t') end | ||
| 336 | end | 441 | end |
| 337 | beg, en, body, here = commonLinky(l, body, "'https://wiki.devuan.org/", url, beg, en, beg0, en0, 0) | ||
| 338 | end | ||
| 339 | 442 | ||
| 340 | writeString(l .. '_NEW', body) | 443 | writeString(l .. '_NEW', body) |
| 444 | end | ||
| 341 | end | 445 | end |
| 342 | end | ||
| 343 | 446 | ||
| 344 | ok, rslt, status = os.execute('pandoc --wrap=preserve -f html -t commonmark_x --self-contained ' .. l .. '_NEW' .. ' >' .. string.sub(l, 1, -4) .. 'md') | 447 | ok, rslt, status = os.execute('pandoc --wrap=preserve -f html -t commonmark_x --self-contained ' .. l .. '_NEW' .. ' >' .. string.sub(l, 1, -4) .. 'md') |
| 448 | end | ||
| 345 | end | 449 | end |
| 346 | 450 | ||
| 347 | if '.' ~= Directory then | 451 | if '.' ~= Folder then |
| 348 | for l in io.popen('find -L . -name "*.md" -type f,l -printf "%P\n"'):lines() do | 452 | for l in io.popen('find -L . -name "*.md" -type f,l -printf "%P\n"'):lines() do |
| 349 | toFile(string.gsub(l, '%.md$', '')) | 453 | toFile(string.gsub(l, '%.md$', '')) |
| 350 | end | 454 | end |
| 351 | end | 455 | end |
| 352 | 456 | ||
| 353 | -- Can add in a distant directory to, for putting it's results in the current directory. | 457 | -- Can add in a distant folder to, for putting it's results in the current folder. |
| 354 | for l in io.popen('find -L ' .. Directory .. ' -name "*.md" -type f,l -printf "%P\n"'):lines() do | 458 | for l in io.popen('find -L ' .. Folder .. ' -name "*.md" -type f,l -printf "%P\n"'):lines() do |
| 355 | local n = string.gsub(l, '%.md$', '') | 459 | local n = string.gsub(l, '%.md$', '') |
| 356 | if nil == Files[n] then toFile(n) end | 460 | if nil == Files[n] then toFile(n) end |
| 357 | end | 461 | end |
| @@ -406,12 +510,25 @@ for name, file in pairs(Files) do | |||
| 406 | end | 510 | end |
| 407 | end | 511 | end |
| 408 | 512 | ||
| 513 | -- Find empty subs. | ||
| 514 | for name, sub in pairs(Subs) do | ||
| 515 | if 0 == #sub.files then | ||
| 516 | print("EMPTY " .. name) | ||
| 517 | h = io.open(name .. '/index.md', 'w') | ||
| 518 | if nil ~= h then | ||
| 519 | h:write('This folder has no files.') | ||
| 520 | h:close() | ||
| 521 | else | ||
| 522 | print("Can't open " .. name .. '/index.md for writing.') | ||
| 523 | end | ||
| 524 | end | ||
| 525 | end | ||
| 409 | 526 | ||
| 410 | 527 | ||
| 411 | --------------------------------------------------------------------------------- | 528 | --------------------------------------------------------------------------------- |
| 412 | -- These functions assume the above file and sub scan has completed. | 529 | -- These functions assume the above file and sub scan has completed. |
| 413 | 530 | ||
| 414 | -- Which page in this directory should we show? | 531 | -- Which page in this folder should we show? |
| 415 | -- NOTE - only looking for the .md files we scanned for before, any stray HTML, html, HTM, and htm files will get ignored. | 532 | -- NOTE - only looking for the .md files we scanned for before, any stray HTML, html, HTM, and htm files will get ignored. |
| 416 | local whichPage = function(f) | 533 | local whichPage = function(f) |
| 417 | local fl = '' | 534 | local fl = '' |
| @@ -454,7 +571,7 @@ local whichWiki = function(metadata) | |||
| 454 | end | 571 | end |
| 455 | 572 | ||
| 456 | 573 | ||
| 457 | -- Calculate a link from the source directory to the destination directory. | 574 | -- Calculate a link from the source folder to the destination folder. |
| 458 | local linkFrom = function(source, dest) | 575 | local linkFrom = function(source, dest) |
| 459 | -- Evil hacks! | 576 | -- Evil hacks! |
| 460 | if 'Profiles' == dest then dest = 'PmWiki/Profiles' end | 577 | if 'Profiles' == dest then dest = 'PmWiki/Profiles' end |
| @@ -507,7 +624,7 @@ end | |||
| 507 | -- More of this actually doing things nonsense. | 624 | -- More of this actually doing things nonsense. |
| 508 | 625 | ||
| 509 | -- Create an "everything" page, for URL links to every file.HTML. | 626 | -- Create an "everything" page, for URL links to every file.HTML. |
| 510 | local Bdy = '# All the pages\n\n| page | converted | original page | last edited UTC | \n| ---- | --------- | ------- | --------------- | ' | 627 | local Bdy = '# All the pages\n\n| page | original page | last edited UTC | \n| --------- | ------- | --------------- | ' |
| 511 | Pages = {} | 628 | Pages = {} |
| 512 | for name, file in pairs(Files) do | 629 | for name, file in pairs(Files) do |
| 513 | local metadata = derefTable(Files[name].metadata, true) | 630 | local metadata = derefTable(Files[name].metadata, true) |
| @@ -520,7 +637,7 @@ for name, file in pairs(Files) do | |||
| 520 | if nil ~= metadata.timestamp then ts = metadata.timestamp end | 637 | if nil ~= metadata.timestamp then ts = metadata.timestamp end |
| 521 | if nil ~= file.bit then ln = file.bit | 638 | if nil ~= file.bit then ln = file.bit |
| 522 | end | 639 | end |
| 523 | table.insert(Pages, '\n| ' .. name .. ' | [' .. ln .. '](<' .. name .. '.HTML>) | ' .. fw .. ' ' .. pw .. ' | ' .. ts .. ' |') | 640 | table.insert(Pages, '\n| [' .. name .. '](<' .. name .. '.HTML>) | ' .. fw .. ' ' .. pw .. ' | ' .. ts .. ' |') |
| 524 | 641 | ||
| 525 | -- Track our external links. | 642 | -- Track our external links. |
| 526 | if (nil ~= metadata.ogBase) and (nil ~= metadata.ogFile) then | 643 | if (nil ~= metadata.ogBase) and (nil ~= metadata.ogFile) then |
| @@ -626,9 +743,20 @@ local LunamarkOpts = { | |||
| 626 | } | 743 | } |
| 627 | local Writer = Lunamark.writer.html5.new(LunamarkOpts) | 744 | local Writer = Lunamark.writer.html5.new(LunamarkOpts) |
| 628 | -- Can override the various writer functions, there's something for each of the basic HTML elements. | 745 | -- Can override the various writer functions, there's something for each of the basic HTML elements. |
| 629 | local Context = {} -- Coz can't otherwise pass context through to the deeper Lunamark functions I'm overriding. | ||
| 630 | local lunaLinky = function(url) -- Fix up the links. | 746 | local lunaLinky = function(url) -- Fix up the links. |
| 631 | if ('https://wiki.devuan.org/' ~= url) and ('https://fos.wiki.devuan.org/' ~= url) then | 747 | if ('https://wiki.devuan.org/' ~= url) and ('https://fos.wiki.devuan.org/' ~= url) then |
| 748 | -- TODO - This might be covering up a bug elsewhere. | ||
| 749 | if '/Main/' == string.sub(url, 1, 6) then | ||
| 750 | local link = linkFrom(Context.path, 'Foswiki/Main') | ||
| 751 | if '' == link then | ||
| 752 | url = string.sub(url, 7) .. '.HTML' | ||
| 753 | else | ||
| 754 | url = link .. '/' .. string.sub(url, 7) .. '.HTML' | ||
| 755 | end | ||
| 756 | end | ||
| 757 | if '/System/' == string.sub(url, 1, 8) then | ||
| 758 | url = 'https://fos.wiki.devuan.org' .. url | ||
| 759 | end | ||
| 632 | for i, p in ipairs{'https://wiki.devuan.org/?n=', 'https://wiki.devuan.org?n=', 'PmWiki/uploads/', 'Foswiki/pub/', 'https://fos.wiki.devuan.org/'} do | 760 | for i, p in ipairs{'https://wiki.devuan.org/?n=', 'https://wiki.devuan.org?n=', 'PmWiki/uploads/', 'Foswiki/pub/', 'https://fos.wiki.devuan.org/'} do |
| 633 | if p == string.sub(url, 1, #p) then | 761 | if p == string.sub(url, 1, #p) then |
| 634 | local ur = string.sub(url, #p + 1) | 762 | local ur = string.sub(url, #p + 1) |
| @@ -646,26 +774,28 @@ local lunaLinky = function(url) -- Fix up the links. | |||
| 646 | end | 774 | end |
| 647 | if (nil ~= md) and (nil ~= md.realURL) then url = md.realURL end | 775 | if (nil ~= md) and (nil ~= md.realURL) then url = md.realURL end |
| 648 | 776 | ||
| 649 | local xlnk = xLinks[string.gsub(ur, '%..*', '', 1)] | 777 | if ('https://fos.wiki.devuan.org/bin/' ~= string.sub(url, 1, 32)) and ('https://fos.wiki.devuan.org/System/' ~= string.sub(url, 1, 35)) then |
| 650 | if nil == Context.path then | 778 | local xlnk = xLinks[string.gsub(ur, '%..*', '', 1)] |
| 651 | url = string.gsub(ur, '%.', '/', 1) | 779 | if nil == Context.path then |
| 652 | else | 780 | url = string.gsub(ur, '%.', '/', 1) |
| 653 | if nil == xlnk then xlnk = string.gsub(string.gsub(ur, '%..*', '', 1), '/.*', '', 1) end | 781 | else |
| 654 | if '' ~= Context.path then xlnk = linkFrom(Context.path, xlnk) end | 782 | if nil == xlnk then xlnk = string.gsub(string.gsub(ur, '%..*', '', 1), '/.*', '', 1) end |
| 655 | if '/' == string.sub(xlnk, 1, 1) then xlnk = string.sub(xlnk, 2) end | 783 | if '' ~= Context.path then xlnk = linkFrom(Context.path, xlnk) end |
| 656 | if ('' ~= xlnk) and ('/' ~= string.sub(xlnk, -1)) then xlnk = xlnk .. '/' end | 784 | if '/' == string.sub(xlnk, 1, 1) then xlnk = string.sub(xlnk, 2) end |
| 657 | if 'DUNNO/' == xlnk then print('OOPS! page not found - @' .. Context.path .. ' / ' .. Context.bit .. '\t' .. url .. ' -> ' .. xlnk .. ' ' .. string.gsub(ur, '.*%.', '', 1) .. '.HTML') end | 785 | if ('' ~= xlnk) and ('/' ~= string.sub(xlnk, -1)) then xlnk = xlnk .. '/' end |
| 658 | end | 786 | if 'DUNNO/' == xlnk then print('OOPS! page not found - @' .. Context.path .. ' / ' .. Context.bit .. '\t' .. url .. ' -> ' .. xlnk .. ' ' .. string.gsub(ur, '.*%.', '', 1) .. '.HTML') end |
| 787 | end | ||
| 659 | -- if (nil ~= md) and (nil ~= md.realURL) then url = md.realURL | 788 | -- if (nil ~= md) and (nil ~= md.realURL) then url = md.realURL |
| 660 | -- else | 789 | -- else |
| 661 | url = xlnk .. string.gsub(ur, '.*%.', '', 1) | 790 | url = xlnk .. string.gsub(ur, '.*%.', '', 1) |
| 662 | -- end | 791 | -- end |
| 663 | if 'PmWiki/uploads/' == p then | 792 | if 'PmWiki/uploads/' == p then |
| 664 | url = '../' .. p .. string.gsub(ur, '%.', '.', 1) | 793 | url = '../../' .. p .. string.gsub(ur, '%.', '.', 1) |
| 665 | elseif 'Foswiki/pub/' == p then | 794 | elseif 'Foswiki/pub/' == p then |
| 666 | url = '../' .. p .. ur | 795 | url = '../../' .. p .. ur |
| 667 | else | 796 | else |
| 668 | url = url .. '.HTML' | 797 | url = url .. '.HTML' |
| 798 | end | ||
| 669 | end | 799 | end |
| 670 | end | 800 | end |
| 671 | end | 801 | end |
| @@ -673,6 +803,12 @@ local lunaLinky = function(url) -- Fix up the links. | |||
| 673 | return url | 803 | return url |
| 674 | end | 804 | end |
| 675 | 805 | ||
| 806 | function Writer.header(s, level) | ||
| 807 | local text = Lunamark.util.rope_to_string(s) | ||
| 808 | -- FIXME - Work around a bug in Lunamark? | ||
| 809 | text = RE.gsub(text, "{[\\]}", "") | ||
| 810 | return '<h' .. level .. ' id="' .. RE.gsub(text, '{[ ]}', '_') .. '">' .. text .. ' <a style="font-size: 0.42em;" href="#top">🔼</a></h' .. level .. '>' | ||
| 811 | end | ||
| 676 | local OgWriterLink = Writer.link -- So we can call the original from within mine, we are just changing the URL. | 812 | local OgWriterLink = Writer.link -- So we can call the original from within mine, we are just changing the URL. |
| 677 | function Writer.link(lab, url, tit) | 813 | function Writer.link(lab, url, tit) |
| 678 | return OgWriterLink(lab, lunaLinky(url), tit) | 814 | return OgWriterLink(lab, lunaLinky(url), tit) |
| @@ -700,10 +836,10 @@ for name, file in pairs(Files) do | |||
| 700 | for i, b in ipairs(bits) do | 836 | for i, b in ipairs(bits) do |
| 701 | local p = table.concat(bits, '/', 1, i) | 837 | local p = table.concat(bits, '/', 1, i) |
| 702 | if i < #bits then | 838 | if i < #bits then |
| 703 | metadata.trail = metadata.trail .. '<a href="' .. linkFrom(file.path, p) .. Subs[p].whichPage .. '">' .. b .. '</a> 👣 ' | 839 | metadata.trail = metadata.trail .. '<a href="' .. linkFrom(file.path, p) .. Subs[p].whichPage .. '">' .. b .. '</a> 👣 ' |
| 704 | linkFrom(file.path, table.concat(bits, '/', 1, i)) | 840 | linkFrom(file.path, table.concat(bits, '/', 1, i)) |
| 705 | else | 841 | else |
| 706 | metadata.trail = metadata.trail .. b .. ' ' | 842 | metadata.trail = metadata.trail .. ' ' .. b |
| 707 | end | 843 | end |
| 708 | end | 844 | end |
| 709 | 845 | ||
| @@ -718,7 +854,7 @@ for name, file in pairs(Files) do | |||
| 718 | local pth = file.path | 854 | local pth = file.path |
| 719 | if '' ~= file.path then pth = file.path .. '/' end | 855 | if '' ~= file.path then pth = file.path .. '/' end |
| 720 | if 'true' ~= Subs[pth .. f].metadata.hidden then | 856 | if 'true' ~= Subs[pth .. f].metadata.hidden then |
| 721 | metadata.header = metadata.header .. '<a href="' .. f .. '/' .. whichPage(pth .. f) .. '">' .. f .. '</a> ' | 857 | metadata.header = metadata.header .. '<a href="' .. f .. '/' .. whichPage(pth .. f) .. '">' .. f .. '</a> 📂 ' |
| 722 | end | 858 | end |
| 723 | end | 859 | end |
| 724 | 860 | ||
| @@ -736,29 +872,62 @@ for name, file in pairs(Files) do | |||
| 736 | url = Files[file.path .. '/' .. f].metadata.URL | 872 | url = Files[file.path .. '/' .. f].metadata.URL |
| 737 | end | 873 | end |
| 738 | if nil == title then title = f end | 874 | if nil == title then title = f end |
| 739 | if bit == f then metadata.menu = metadata.menu .. '<p>' .. title .. '</p>' | 875 | if bit == f then |
| 876 | metadata.menu = metadata.menu .. '<p>' .. title .. '</p>' | ||
| 877 | for j, g in ipairs(file.headers) do | ||
| 878 | local beg, en = RE.find(g, [['{']]) | ||
| 879 | if nil ~= beg then | ||
| 880 | g = string.sub(g, 1, beg - 2) | ||
| 881 | end | ||
| 882 | local h = string.sub(RE.gsub(g, '{[#]}', ''), 2) | ||
| 883 | local l = string.len(g) - string.len(h) | ||
| 884 | g = h | ||
| 885 | h = RE.gsub(h, '{[ ]}', ' ') | ||
| 886 | -- FIXME - Work around a bug in Lunamark? | ||
| 887 | g = RE.gsub(g, '{[\\]}', '') | ||
| 888 | h = RE.gsub(h, '{[\\]}', '') | ||
| 889 | -- FIXME - if it's a linky, strip off the URL part. The Wiki audit has such things. | ||
| 890 | metadata.menu = metadata.menu .. '<p>' .. string.rep(' ', l) .. '<a style="font-size: 0.80em;" href="#' .. RE.gsub(g, '{[ ]}', '_') .. '">' .. h .. '</a></p>' | ||
| 891 | end | ||
| 740 | else | 892 | else |
| 741 | if nil ~= url then metadata.menu = metadata.menu .. '<p><a href="' .. url .. '">' .. title .. ' ☝</a></p>' | 893 | if nil ~= url then metadata.menu = metadata.menu .. '<p><a href="' .. url .. '">' .. title .. ' ☝</a></p>' |
| 742 | else metadata.menu = metadata.menu .. '<p><a href="' .. f .. '.HTML">' .. title .. '</a></p>' | 894 | else |
| 895 | local pth = file.path | ||
| 896 | if '' ~= pth then pth = pth .. '/' end | ||
| 897 | -- Don't include any left over .md.md files, so don't do this if f.md doesn't exist. | ||
| 898 | local a, e = io.open(pth .. f .. '.md' , 'r') | ||
| 899 | if nil ~= a then | ||
| 900 | a:close() | ||
| 901 | metadata.menu = metadata.menu .. '<p><a href="' .. f .. '.HTML">' .. title .. '</a></p>' | ||
| 902 | end | ||
| 743 | end | 903 | end |
| 744 | end | 904 | end |
| 745 | end | 905 | end |
| 746 | 906 | ||
| 747 | -- Figure out this pages footer links. | 907 | -- Figure out this pages footer links. |
| 908 | local temp = '' | ||
| 748 | metadata.footer = '' | 909 | metadata.footer = '' |
| 749 | if nil ~= metadata.pagehistory then metadata.history = '<p>Page <a href="' .. metadata.pagehistory .. '/' .. name .. '.md">history</a></p>' else metadata.history = '' end | 910 | if nil == metadata.pagehistory then |
| 911 | if 'Foswiki' == metadata.ogWiki then metadata.pagehistory = metadata.ogURL .. '/bin/oops/' .. metadata.ogBase .. '/' .. metadata.ogFile .. '?template=oopshistory' end | ||
| 912 | if 'PmWiki' == metadata.ogWiki then metadata.pagehistory = metadata.ogURL .. '/?n=' .. metadata.ogBase .. '.' .. metadata.ogFile .. '?action=diff' end | ||
| 913 | else | ||
| 914 | temp = '/' .. name .. '.md' | ||
| 915 | end | ||
| 916 | if nil ~= metadata.pagehistory then metadata.history = '<p>Page <a href="' .. metadata.pagehistory .. temp .. '">history</a></p>' else | ||
| 917 | metadata.history = '' | ||
| 918 | end | ||
| 750 | if nil ~= metadata.sourcecode then metadata.footer = '<a href="' .. metadata.sourcecode .. '">source code</a>' end | 919 | if nil ~= metadata.sourcecode then metadata.footer = '<a href="' .. metadata.sourcecode .. '">source code</a>' end |
| 751 | if nil ~= metadata.feedatom then metadata.footer = '<a href="' .. metadata.feedatom .. '">atom feed</a> ' .. metadata.footer end | 920 | if nil ~= metadata.feedatom then metadata.footer = '<a href="' .. metadata.feedatom .. '">atom feed<img src="feed-icon-14x14.png"></img></a> ' .. metadata.footer end |
| 752 | if metadata.footer ~= '' then metadata.footer = 'Web site ' .. metadata.footer end | 921 | if metadata.footer ~= '' then metadata.footer = 'Web site ' .. metadata.footer end |
| 753 | -- Add a link to the original page. | 922 | -- Add a link to the original page. |
| 754 | if nil ~= metadata.ogURL then | 923 | if nil ~= metadata.ogURL then |
| 755 | local title, link = whichWiki(metadata) | 924 | local title, link = whichWiki(metadata) |
| 756 | link = string.gsub(link, 'https://', 'HTTPS://') -- Prevent this one from being converted. | 925 | link = string.gsub(link, 'https://', 'HTTPS://') -- Prevent this one from being converted. |
| 757 | -- TODO - wrap "edit" in a link to actually edit it. PmWiki "?action=edit" Foswiki "https://fos.wiki.devuan.org/bit/edit/" .. page .. "?t=" .. 10 digit random number? | 926 | -- TODO - wrap "edit" in a link to actually edit it. PmWiki "?action=edit" Foswiki "https://fos.wiki.devuan.org/bit/edit/" .. page .. "?t=" .. 10 digit random number? |
| 758 | local edit = 'edit' | 927 | local edit = 'T' |
| 759 | if 'PmWiki' == metadata.ogWiki then edit = '<a href="' .. link .. '?action=edit">edit</a>' end | 928 | if 'PmWiki' == metadata.ogWiki then edit = 'Maybe you can <a href="' .. link .. '?action=edit">edit</a> t' end |
| 760 | -- if 'Foswiki' == metadata.ogWiki then edit = 'edit' end | 929 | -- if 'Foswiki' == metadata.ogWiki then edit = '' end |
| 761 | metadata.footer = '<a href="' .. link .. '">Original page</a>, maybe you can ' .. edit .. ' it. ' .. metadata.footer | 930 | metadata.footer = edit .. 'he <a href="' .. link .. '">original page</a>. ' .. metadata.footer |
| 762 | end | 931 | end |
| 763 | metadata.footer = '<p>' .. metadata.footer .. '</p>' | 932 | metadata.footer = '<p>' .. metadata.footer .. '</p>' |
| 764 | 933 | ||
| @@ -767,6 +936,7 @@ for name, file in pairs(Files) do | |||
| 767 | -- Toss the body in first, so the scan can deal with it to. | 936 | -- Toss the body in first, so the scan can deal with it to. |
| 768 | -- NOTE - this is where we actually parse the markup into HTML. | 937 | -- NOTE - this is where we actually parse the markup into HTML. |
| 769 | Context = file | 938 | Context = file |
| 939 | body = RE.gsub(body, '{[%nl]^1[%a]+}[.]^1 ', '%1$dot$ ') -- Coz otherwise stray . trip up the list detection. | ||
| 770 | local bd, md = Parse(body) -- The md is a table of extracted metadata, not likely to be any, and we wont do anything with it. | 940 | local bd, md = Parse(body) -- The md is a table of extracted metadata, not likely to be any, and we wont do anything with it. |
| 771 | bd = RE.gsub(bd, '{[%]}', '$perc$') -- Coz otherwise stray % trip up the capture part. | 941 | bd = RE.gsub(bd, '{[%]}', '$perc$') -- Coz otherwise stray % trip up the capture part. |
| 772 | temp = RE.gsub(temp, '"$body$"', bd) | 942 | temp = RE.gsub(temp, '"$body$"', bd) |
diff --git a/testing/index.md b/testing/index.md index 9866373..581d301 100644 --- a/testing/index.md +++ b/testing/index.md | |||
| @@ -78,17 +78,17 @@ Autonumbering? Needs the extension. Doesn't matter, they get renumbered anyway | |||
| 78 | 2. two | 78 | 2. two |
| 79 | 1. one | 79 | 1. one |
| 80 | 80 | ||
| 81 | Bug. If there's a single word and period at the beginning of a line, it gets turned into a list, or list item. | 81 | Bug. If there's a single word and period at the beginning of a line, it gets turned into a list, or list item. |
| 82 | 82 | ||
| 83 | <!-- Separate the lists. --> | 83 | <!-- Separate the lists. --> |
| 84 | 84 | ||
| 85 | Bug. If there's a single word and period at the beginning of a line, it gets turned into a list, or list item. | 85 | Bug. If there's a single word and period at the beginning of a line, it gets turned into a list, or list item. |
| 86 | 86 | ||
| 87 | ~~~ | 87 | ~~~ |
| 88 | Bug. If there's a single word and period at the beginning of a line, it gets turned into a list, or list item. | 88 | Bug. If there's a single word and period at the beginning of a line, it gets turned into a list, or list item. |
| 89 | ~~~ | 89 | ~~~ |
| 90 | 90 | ||
| 91 | Uncovering another bug, the stuff in a code block is in a different font. Ah, it's mono. lol | 91 | The stuff in a code block is in a different font, it's mono. lol |
| 92 | 92 | ||
| 93 | # images | 93 | # images |
| 94 | 94 | ||
