aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
-rw-r--r--.md.md5
-rw-r--r--Connie_click-me.gifbin4259 -> 0 bytes
-rw-r--r--INSTALL.md11
-rw-r--r--LICENCE31
-rw-r--r--README23
-rw-r--r--README.md.md1
-rwxr-xr-xSuckIt162
-rwxr-xr-xSuckItClean13
-rwxr-xr-xSuckItCron4
-rw-r--r--TODO.md100
l---------about/Connie_click-me.gif1
-rw-r--r--about/index.md25
-rw-r--r--default.template150
-rw-r--r--empty.md1
-rwxr-xr-xfeed-icon-14x14.pngbin0 -> 689 bytes
-rwxr-xr-xfeed-icon-28x28.pngbin0 -> 1737 bytes
-rw-r--r--help.md43
-rw-r--r--menu.template2
-rw-r--r--nYAW.pngbin0 -> 16624 bytes
-rw-r--r--nYAW.xcfbin0 -> 25929 bytes
-rw-r--r--nYAW_icon.pngbin0 -> 6315 bytes
-rw-r--r--nYAW_icon.xcfbin0 -> 14685 bytes
-rwxr-xr-xnotYetAnotherWiki.lua1058
-rw-r--r--testing/.md.md1
-rw-r--r--[l---------]testing/Connie_click-me.gifbin22 -> 4259 bytes
-rw-r--r--testing/index.md117
-rw-r--r--testing/index.md.md1
27 files changed, 1464 insertions, 285 deletions
diff --git a/.md.md b/.md.md
new file mode 100644
index 0000000..4a55e50
--- /dev/null
+++ b/.md.md
@@ -0,0 +1,5 @@
1favicon=nYAW_icon.png
2logo=nYAW.png
3sourcecode=https://sledjhamr.org/cgit/notYetAnotherWiki/
4pagehistory=https://sledjhamr.org/cgit/notYetAnotherWiki/log
5feedatom=https://sledjhamr.org/cgit/notYetAnotherWiki/atom
diff --git a/Connie_click-me.gif b/Connie_click-me.gif
deleted file mode 100644
index 6f0b361..0000000
--- a/Connie_click-me.gif
+++ /dev/null
Binary files differ
diff --git a/INSTALL.md b/INSTALL.md
index 2d8ed96..a2b2842 100644
--- a/INSTALL.md
+++ b/INSTALL.md
@@ -1,13 +1,6 @@
1--- 1# Install
2favicon: cartdave_favicon.png
3pagetitle: "INSTALL"
4author: onefang
5feedatom: https://sledjhamr.org/cgit/notYetAnotherWiki/atom
6history: https://sledjhamr.org/cgit/notYetAnotherWiki/log/INSTALL.md
7sourcecode: https://sledjhamr.org/cgit/notYetAnotherWiki/
8---
9 2
10notYetAnotherWiki uses [lcmark](https://github.com/jgm/lcmark) to parse [CommonMark](https://commonmark.org/) into HTML. You can probably install it using luarocks. lua-yaml is the YAML parsing library I test with. 3notYetAnotherWiki uses [lunamark](https://github.com/jgm/lunamark) to parse [CommonMark](https://commonmark.org/) into HTML. You can probably install it using luarocks. lua-yaml is the YAML parsing library I test with.
11 4
12You also need luajit installed. 5You also need luajit installed.
13 6
diff --git a/LICENCE b/LICENCE
new file mode 100644
index 0000000..eea8e4f
--- /dev/null
+++ b/LICENCE
@@ -0,0 +1,31 @@
1Copyright notice for notYetAnotherWiki:
2
3Copyright (C) 2024 David Walter Seikel AKA onefang
4
5All rights reserved.
6
7Redistribution and use in source and binary forms, with or without
8modification, are permitted provided that the following conditions are
9met:
10
111. Redistributions of source code must retain the above copyright
12notice, this list of conditions and the following disclaimer.
13
142. Redistributions in binary form must reproduce the above copyright
15notice, this list of conditions and the following disclaimer in the
16documentation and/or other materials provided with the distribution.
17
18THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
19INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
20AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
21THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
22INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
24USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
25ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28
29Freedom -1: the author specifically grants themselves the freedom to not
30be infected by the viral licence clauses of any code this source code
31"links" to. It's my code, I choose my licence terms, no one else does.
diff --git a/README b/README
index aedd92a..954bc7a 100644
--- a/README
+++ b/README
@@ -1,11 +1,4 @@
1--- 1# notYetAnotherWiki
2favicon: cartdave_favicon.png
3pagetitle: "notYetAnotherWiki"
4author: onefang
5feedatom: https://sledjhamr.org/cgit/notYetAnotherWiki/atom
6history: https://sledjhamr.org/cgit/notYetAnotherWiki/log/index.md
7sourcecode: https://sledjhamr.org/cgit/notYetAnotherWiki/
8---
9 2
10notYetAnotherWiki is not another wiki, at least not yet. It'll be much 3notYetAnotherWiki is not another wiki, at least not yet. It'll be much
11more than that, eventually. 4more than that, eventually.
@@ -59,22 +52,30 @@ the useful info that makes it's way into the system one way or another.
59Someone comes into your chat system, asking for help, within minutes 52Someone comes into your chat system, asking for help, within minutes
60people are helping out and come up with a working solution. After a few 53people are helping out and come up with a working solution. After a few
61other people turn up with the same problem, the existing conversations 54other people turn up with the same problem, the existing conversations
62are moved to the decumentation section, where the original participants 55are moved to the documentation section, where the original participants
63and others can polish it into proper documentation about solving what has 56and others can polish it into proper documentation about solving what has
64suddenly become a common problem. Every one knows where to find it, on 57suddenly become a common problem. Every one knows where to find it, on
65the one system. They can chat about it, on the one system. 58the one system. They can chat about it, on the one system.
66 59
67## What does it do already? 60## What does it do already?
68 61
69Currently it'll scan the current directory and subdirectories looking for 62Currently it'll scan the current folder and sub folders looking for
70.md files in CommonMark syntax. This should cover some MarkDown 63.md files in CommonMark syntax. This should cover some MarkDown
71variations. Then it produces .HTML files converted from these .md files, 64variations. Then it produces .HTML files converted from these .md files,
72and links them all together into a web site. 65and links them all together into a web site.
73 66
67Any .md file that is just the beginning metadata block doesn't get
68rendered into HTML, but is global metadata for this folder and subs,
69though the subs can override this with their own metadata.md files.
70
74git is used to store the .md files, and provides edit history. Added on 71git is used to store the .md files, and provides edit history. Added on
75the footer is links to cgit, which is used to store the files in git on 72the footer is links to cgit, which is used to store the files in git on
76your server. This provides acces to the source code, history, and ATOM 73your server. This provides acces to the source code, history, and ATOM
77feed for the site. 74feed for the site.
78 75
79It can also scan an external directory and merge that with the current 76It can also scan an external folder and merge that with the current
80one, but this isn't tested yet. 77one, but this isn't tested yet.
78
79## other stuff
80
81The font femkeklaver.ttf was used for making the nYAW logo.
diff --git a/README.md.md b/README.md.md
new file mode 100644
index 0000000..31ea1e7
--- /dev/null
+++ b/README.md.md
@@ -0,0 +1 @@
title=nYAW
diff --git a/SuckIt b/SuckIt
new file mode 100755
index 0000000..38fe18e
--- /dev/null
+++ b/SuckIt
@@ -0,0 +1,162 @@
1#!/bin/bash
2
3TIMEFORMAT=" took %lR using %P%% CPU"
4time {
5pushd /opt/nyaw
6
7#rm -fr Foswiki/*
8cp -r /opt/nyaw_EMPTY/Foswiki .
9#rm -fr PmWiki/*
10cp -r /opt/nyaw_EMPTY/PmWiki .
11#rm -fr unsorted
12mkdir -p unsorted
13cp -r /opt/nyaw_EMPTY/unsorted .
14#rm -fr users/*
15mkdir -p users
16cp -r /opt/nyaw_EMPTY/users .
17
18# Copy across things like images that where uploaded.
19mkdir -p /opt/nyaw/Foswiki/pub/
20# TODO - Should rsync this instead.
21cp -r /opt/Foswiki/pub/Main /opt/nyaw/Foswiki/pub/
22filter="
23 -name _default -prune -o \
24 -name _empty -prune -o \
25 -name System -prune -o \
26 -name Trash -prune -o \
27 -name TWiki -prune -o \
28"
29ogURL="https://fos.wiki.devuan.org"
30ogWiki="Foswiki"
31time find /opt/Foswiki/data ${filter} \
32-name "*.txt" -type f,l -printf "%P\n" | while read line
33do
34 base=`echo "${line}" | cut -d '/' -f 1`
35 file=`echo "${line}" | cut -d '/' -f 2- | rev | cut -b 5- | rev`
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
37 doit='false'
38 if [ ! -s ${ogWiki}/${base}/${file}.HTM ]; then
39 echo "NEW /opt/Foswiki/data/${base}/${file}.txt"
40 doit='true'
41 elif [ /opt/Foswiki/data/${base}/${file}.txt -nt ${ogWiki}/${base}/${file}.HTM ]; then
42 echo "NEWER /opt/Foswiki/data/${base}/${file}.txt"
43 date --rfc-3339=seconds -ur /opt/Foswiki/data/${base}/${file}.txt
44 date --rfc-3339=seconds -ur ${ogWiki}/${base}/${file}.HTM
45 doit='true'
46 fi
47 if [[ ${doit} == "true" ]]; then
48 realURL=${ogWiki}/${base}/${file}
49 time=`date --rfc-3339=seconds -ur /opt/Foswiki/data/${base}/${file}.txt | cut -d '+' -f 1`
50 mkdir -p ${ogWiki}/${base}
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
92 fi
93 fi
94 fi
95done
96
97
98# Copy across things like images that where uploaded.
99cp -r /opt/pmwiki/uploads /opt/nyaw/PmWiki/
100filter="
101 -not -name "*~" -a \
102 -not -name ".flock" -a \
103 -not -name ".htaccess" -a \
104 -not -name ".lastmod" -a \
105 -not -name ".pageindex" -a \
106"
107ogURL="https://wiki.devuan.org"
108ogWiki="PmWiki"
109time find /opt/pmwiki/wiki.d ${filter} \
110-name "*.*" -type f,l -printf "%P\n" | while read line
111do
112 base=`echo "${line}" | cut -d '.' -f 1`
113 file=`echo "${line}" | cut -d '.' -f 2`
114 if [[ "${base}" != "Site" ]]; then
115 doit='false'
116 if [ ! -s ${ogWiki}/${base}/${file}.HTM ]; then
117 echo "NEW /opt/pmwiki/wiki.d/${base}.${file} ${ogWiki}/${base}/${file}.HTM"
118 doit='true'
119 elif [ /opt/pmwiki/wiki.d/${base}.${file} -nt ${ogWiki}/${base}/${file}.HTM ]; then
120 echo "NEWER /opt/pmwiki/wiki.d/${base}.${file}"
121 date --rfc-3339=seconds -ur /opt/pmwiki/wiki.d/${base}.${file}
122 date --rfc-3339=seconds -ur ${ogWiki}/${base}/${file}.HTM
123 doit='true'
124 fi
125 if [[ ${doit} == "true" ]]; then
126 realURL=${ogWiki}/${base}/${file}
127 time=`date --rfc-3339=seconds -ur /opt/pmwiki/wiki.d/${base}.${file} | cut -d '+' -f 1`
128 mkdir -p ${ogWiki}/${base}
129 echo -e "ogWiki=${ogWiki}\nogURL=${ogURL}\nrealURL=${realURL}\nogBase=${base}\nogFile=${file}\ntimestamp=${time}\n" > ${ogWiki}/${base}/${file}.md.md
130# echo "downloading ${ogURL}/?n=${base}.${file}?action=markdown"
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
147 fi
148
149# TODO - groups are PmWiki/Onefang and PmWiki/Tiki
150
151# pandoc -f markdown -t commonmark_x --self-contained ${ogWiki}//${base}/${file}.MD >${ogWiki}/${base}/${file}.md
152# pandoc -f html -t commonmark_x --self-contained ${ogWiki}//${base}/${file}.HTM >${ogWiki}/${base}/${file}.md
153 fi
154done
155
156
157time notYetAnotherWiki.lua
158# No idea why yet, but needs a second run to sort out everything. Shouldn't take long anyway.
159time notYetAnotherWiki.lua
160
161popd
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
3TIMEFORMAT=" took %lR using %P%% CPU"
4time {
5pushd /opt/nyaw
6
7rm -fr Foswiki/*
8rm -fr PmWiki/*
9rm -fr unsorted
10rm -fr users/*
11popd
12./SuckIt
13}
diff --git a/SuckItCron b/SuckItCron
new file mode 100755
index 0000000..e817948
--- /dev/null
+++ b/SuckItCron
@@ -0,0 +1,4 @@
1#!/bin/sh
2
3cd /opt/notYetAnotherWiki
4./SuckIt >/dev/null 2>&1
diff --git a/TODO.md b/TODO.md
index 9eda53e..3453ba0 100644
--- a/TODO.md
+++ b/TODO.md
@@ -1,34 +1,100 @@
1--- 1# TODO
2favicon: cartdave_favicon.png 2
3pagetitle: "TODO" 3Make it perphekd!
4author: onefang 4
5feedatom: https://sledjhamr.org/cgit/notYetAnotherWiki/atom
6history: https://sledjhamr.org/cgit/notYetAnotherWiki/log/TODO.md
7sourcecode: https://sledjhamr.org/cgit/notYetAnotherWiki/
8---
9## Do these 5## Do these
10 6
11Check the timestamps on the files, only update if source is newer than destination. Meh, it's already 600 times faster than the pandoc version. 7Convert it to polygLua.
12 One quirk to watch for is if a URL path cahnges, the docs that have that URL need to be redone. 8
9It's all a bit too fragile, fix what I can. Too many messes colliding.
10
11Flock it.
12
13Some sort of search system.
14
15A member system, and edit / manage system for their pages.
16
17Fix up linky conversion. DONE, mostly.
18
19- Need to deal with real file name versus title. Also symlink name not matching what it points to.
20
21Use the default.template that comes with nYAW if none is availaable.
22
23"collapsing headings" I guess that means click on a heading to hide / show the content under that heading.
24
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.
33
34Add ATOM feed for single page. Alas cgit only seems to have ATOM feed on the whole repo, not individual files.
35
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
38into Fos and Pm edit form's save function. So when they save in the
39original 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
41and 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.
45
46Syntax highlighting in code blocks. The highlight package looks promising, already had it installed on my desktop.
47
48## Some ideas
13 49
14Add atom feed for single page. Alas cgit only seems to have ATOM feed on the whole repo, not individual files. 50Mostly from something chomwitt wrote -
15 51
52- "validation", not sure exactly what that would validate.
53- I'll just quote some of the rest -
54
55~~~
56 !!! co-editing
57 The toolbar should contain tools that facilitate :
58 * intergration (to other workflows)
59 ** for example search-completion to other workflows names-tags.
60~~~
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
65Automate 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/.
16 68
17 69
18## Try out 70## Try out
19 71
20htmx 72lua-lpeg-patterns might be useful
73
74lua-luxio might be the wheel I'm reinventing?
75
76lua-wsapi-fcgi
21 77
22pandoc replacements 78https://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.
23 cmark-gfm 79
80htmx
24 81
25cgit has Lua 82cgit has Lua
26 83
84lua-gall for git stuff
85
86lua-lace for access control
87
88lua-unbound
27 89
28 90
29## User system 91## Member system
92
93Reuse the member system from SledjChisl.
30 94
31levels - 95levels -
96
97- everyone
32- banned 98- banned
33- reader 99- reader
34- member 100- member
@@ -38,6 +104,8 @@ levels -
38- shell 104- shell
39- root 105- root
40 106
107Everyone can read the pages, no need for an account.
108
41Banned people can't do squat, except maybe pester an admin once to start the unbanning process. 109Banned people can't do squat, except maybe pester an admin once to start the unbanning process.
42 110
43When first registered, accounts are set to reader level. 111When first registered, accounts are set to reader level.
@@ -64,6 +132,6 @@ site, including configuration and modules. Likely this is the person
64that set the system up in the first place. 132that set the system up in the first place.
65 133
66Admin should have access to everything that shell level has, but there's always things need tweaking at some lower level. 134Admin should have access to everything that shell level has, but there's always things need tweaking at some lower level.
67Built in file browser might do the trick. Would be useful for content creators to to organise the content. Naturally should obey the permisisons. 135Built in file browser might do the trick. Would be useful for content creators to organise the content. Naturally should obey the permissions.
68 136
69root level is whoever controls the server things are running on. They can do anything at all. 137root level is whoever controls the server things are running on. They can do anything at all.
diff --git a/about/Connie_click-me.gif b/about/Connie_click-me.gif
deleted file mode 120000
index 35d25cd..0000000
--- a/about/Connie_click-me.gif
+++ /dev/null
@@ -1 +0,0 @@
1../Connie_click-me.gif \ No newline at end of file
diff --git a/about/index.md b/about/index.md
index 51b84cc..3f15be7 100644
--- a/about/index.md
+++ b/about/index.md
@@ -1,24 +1,5 @@
1--- 1# notYetAnotherWiki is not another wiki, at least not yet. It'll be much more than that, eventually.
2favicon: cartdave_favicon.png
3pagetitle: "notYetAnotherWiki is not another wiki, at least not yet. It'll be much more than that, eventually."
4author: onefang
5feedatom: https://sledjhamr.org/cgit/notYetAnotherWiki/atom
6history: https://sledjhamr.org/cgit/notYetAnotherWiki/log/About/index.md
7sourcecode: https://sledjhamr.org/cgit/notYetAnotherWiki/
8---
9 2
10This is a new directory, an entire PR department can hang out here. 3This is a new folder, an entire PR department can hang out here.
11 4
12notYetAnotherWiki is not another wiki, at least not yet. It'll be much more than that, eventually. 5This would just be a duplicate of README, but for testing purposes.
13
14So to start with it's not a wiki. It's currently a way to create a web
15site with CommonMark wiki markup, using git to update the content.
16
17So it's not a wiki, yet.
18
19Next comes accounts and online editing of content with the web pages. It'll then barely be a wiki.
20
21The missing bit is talk pages, which requires some sort of archiving chat
22system built into the thing. Now it's Yet Another Wiki.
23
24Finally comes the magic, so it's "not Yet Another Wiki", it's much more than that.
diff --git a/default.template b/default.template
index 4c1ac12..baefad1 100644
--- a/default.template
+++ b/default.template
@@ -2,68 +2,118 @@
2<html> 2<html>
3 <head> 3 <head>
4 <meta charset="utf-8"> 4 <meta charset="utf-8">
5 <meta name="generator" contents="lcmark">
6 <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes"> 5 <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes">
7 <title>$pagetitle$</title> 6 <title>$title$</title>
8 <link rel="icon" type="image/png" href="$favicon$" /> 7 <link rel="icon" type="image/png" href="$favicon$" />
9 <style> 8 <style>
10 html {font-family: sans-serif;} 9 a:hover {color: red;}
11
12 body { 10 body {
13 background-color: black; 11 height: 100vh; width: 100vw;
14 color: white !important; 12 margin: 0; padding: 0; border: none;
13 background-image: linear-gradient($onefangPurple$, $karenPurple$);
14 color: white;
15 font-family: sans-serif;
15 } 16 }
16 17 menu {list-style-type: none;}
17 pre { 18 pre {
18 background-color: #cc00ff; 19 background-image: linear-gradient(to right, $PinkFloyd$, $onefangPurple$);
19 overflow: auto; 20 width: fit-content; max-width: 99%; overflow-x: auto;
20 width: 42%; 21 margin: 2px; border: 2px solid grey;
21 } 22 }
23 table, td, th {border-collapse: collapse; border: 2px solid grey;}
24
25 .toolTip {background: darkcyan; font-size: 1.42em;}
22 26
23 menu { 27 .boxWrapper {
24 list-style-type: none; 28 height: 100%; width: 100%;
29 margin: 0; padding: 0; border: none;
30 display: grid;
31// grid-template-areas:
32// "logo tools tools tools"
33// "logo head head head"
34// "menu body body body"
35// "history foot foot foot"
36// "nyaw nyaw nyaw nyaw";
37 grid-template-columns: 1.4fr 8fr auto auto;
38 grid-template-rows: auto auto 1fr auto auto;
39 overflow-x: auto; overflow-y: auto;
25 } 40 }
41 .boxLogo {grid-area: logo; grid-column: 1 / 1; grid-row: 1 / 2; height: min-content;}
42 .boxTools {grid-area: tools; grid-column: 2 / 4; grid-row: 1 / 1; height: min-content;}
43 .boxHead {grid-area: head; grid-column: 2 / 4; grid-row: 2 / 2; height: min-content; text-align: right;}
26 44
27 .contentBox { 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;}
28 overflow-y: auto; 46 .boxBody {grid-area: body; grid-column: 2 / 4; grid-row: 3 / 3; vertical-align: top;
29 overflow-x: hidden; 47 height: 100%; width: 100%;
48 background: black; color: white;
30 } 49 }
50 .boxBody a:active {color: red;}
51 .boxBody a:link {color: orange;}
52 .boxBody a:visited {color: $onefangGreen$;}
53 .boxBody a:hover {color: red;}
54
55 .boxHistory {grid-area: history; grid-column: 1 / 1; grid-row: 4 / 4; height: min-content;}
56 .boxFoot {grid-area: foot; grid-column: 2 / 4; grid-row: 4 / 4; height: min-content; text-align: right;}
57 .boxnyaw {grid-area: nyaw; grid-column: 1 / 4; grid-row: 5 / 5; height: min-content; text-align: right; font-size: 0.55em;}
58
59 #modeToggleBody {display: none;}
60 #modeToggleMenu {display: none;}
61 #modeBtn {color: white; display: inline-block;}
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
71 #modeToggleBody:checked ~ .boxBody {background: white; color: black;}
72 #modeToggleBody:checked ~ .boxBody a:active {color: $devuanDevuanalink$;}
73 #modeToggleBody:checked ~ .boxBody a:link {color: $devuanDevuanlink$;}
74 #modeToggleBody:checked ~ .boxBody a:visited {color: $devuanDevuanvlink$;}
75 #modeToggleBody:checked ~ .boxBody a:hover {color: $devuanDevuanhlink$;}
76
77 #modeToggleMenu:checked ~ .boxHistory {display: none;}
78 #modeToggleMenu:checked ~ .boxFoot {display: none;}
79 #modeToggleMenu:checked ~ .boxnyaw {display: none;}
31 </style> 80 </style>
32 </head> 81 </head>
33 <body bgcolor="black" text="white" alink="red" link="yellow" vlink="blue"> 82 <body alink="red" link="orange" vlink="$onefangGreen$">
34 <table> 83 <div class="boxWrapper">
35 <tr> 84 <input type="checkbox" id="modeToggleMenu"/>
36 <td><img src="Connie_click-me.gif" alt="alt text" title="Not (Yet) (Another / A) Wiki."/></td> 85 <input type="checkbox" id="modeToggleBody"/>
37 <td>$header$ &nbsp; plus login and register buttons</td> 86 <div class="boxLogo" id="top"><header><nav>
38 </tr> 87 <a href="$home$"><img src="$logo$" alt="not (Yet) (Another / A) Wiki."/></a>
39 <td rowspan=0 style="background-color: rebeccapurple; text-align:left; white-space:nowrap; vertical-align:top"> 88 </nav></header></div>
40 menu for the current directory 89 <div class="boxTools"><header><nav>
41 $menu$ 90 &nbsp; <a href="/help.HTML"><b class="toolTip" title="🍔 hides / shows non content, reverse hamburger menu.
42 </td> 91🕶 switches between dark and light themes.
43 <td style="background-color: rebeccapurple"> 92📚 shows the list of all pages.
44 &#x1f463; $trail$ 93🔮 a folder of unsorted pages.
45 </td> 94👥 shows the list of users.
46 </tr> 95🪵 will be for logging in, when I have written that bit.
47 <tr> 96🔍 will be the search, when I have written that bit.
48 <td> 97👣 is a trail of the steps to get here.">❓</b></a>
49 <main class="contentBox"> 98 &nbsp; <b class="toolTip"><label for="modeToggleMenu" class='modeBtn'>&#127828;</label></b>
50 <div name="contentFrame"> 99 &nbsp; <b class="toolTip"><label for="modeToggleBody" class='modeBtn'>&#x1F576;</label></b>
51 <h1>$pagetitle$</h1> 100 &nbsp; <a href="/everything.HTML"><b class="toolTip">&#128218;</b></a>
52 Author: $author$ 101 &nbsp; <a href="/unsorted/" ><b class="toolTip">&#128302;</b></a>
53 $body$ 102 &nbsp; <a href="/users/" ><b class="toolTip">&#128101;</b></a>
54 </div> 103 &nbsp; <b class="toolTip">&#129717;</b>
55 </main> 104 &nbsp; <b class="toolTip">&#128269;</b>
56 </td> 105 <b> &nbsp; &#x1f463; $trail$ </b>
57 </tr> 106 </nav></header></div>
58 <tr> 107 <div class="boxHead"><header><nav><b>$header$</b> &nbsp; </nav></header></div>
59 <td style="background-color: rebeccapurple"> 108
60 <p>Page <a href="$history$">history</a>. &nbsp; Web site <a href="$feedatom$">atom feed</a> and <a href="$sourcecode$">source code</a> &nbsp; Powered by <a href="https://sledjhamr.org/cgit/notYetAnotherWiki/about/">notYetAnotherWiki</a> Version $version$.</p> 109 <div class="boxMenu"><nav><p><b>$menu$</b></p></nav></div>
61 </td> 110 <div class="boxBody"><main>$body$<br/></main></div>
62 </tr> 111
63 <tr> 112 <div class="boxHistory"><footer>$history$</footer></div>
64 <td> 113 <div class="boxFoot"><footer>$footer$</footer></div>
65 </td> 114 <div class="boxnyaw"><footer>
66 </tr> 115 <p>Powered&nbsp;by&nbsp;<a href="https://sledjhamr.org/notYetAnotherWiki/">notYetAnotherWiki</a>&nbsp;v&nbsp;0.0 &nbsp; No cookies or scripts where harmed in the making of this web site. &nbsp; May contain low fat CSS.</p>
67 </table> 116 </footer></div>
117 </div>
68 </body> 118 </body>
69</html> 119</html>
diff --git a/empty.md b/empty.md
new file mode 100644
index 0000000..b68450f
--- /dev/null
+++ b/empty.md
@@ -0,0 +1 @@
Nothing to see here, yet.
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
diff --git a/help.md b/help.md
new file mode 100644
index 0000000..bc4cc46
--- /dev/null
+++ b/help.md
@@ -0,0 +1,43 @@
1# How to use this wiki
2
3On 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&#x1f463; is a trail of breadcrumbs, though I'm using a footsteps icon
15for this. Showing the footsteps you have followed to get to the current
16folder.
17
18On the top right of the pages is links to the sub folders of the current
19folder the current page is in.
20
21Down the left side is links to the pages in the current folder. Most of
22them will be symlinks to the converted pages from the Foswiki and PmWiki
23sub folders. Some will be links &#9757; to external sites. For the
24current page, links to the headings are also shown, those headings have
25their own icon 🔼to go back to the top.
26
27The bit you are reading is the badly converted content of the current
28page. At the bottom of each converted page is a link to the original,
29and if you are logged into that other system, you might be able to edit
30the page. Note that unconverted pages don't have these links to the
31originals.
32
33At the bottom is links to things like page history, web site source code,
34and the software I'm writing to do all of this. Or should be some day.
35
36
37
38# Under the hood
39
40Internally this wiki is made of the root folder and it's sub folders
41representing the structure of the wiki content. Each folder has it's own
42pages. Symlinks are used to copy or move pages around, with special
43folders for the original stuff from the other wikis.
diff --git a/menu.template b/menu.template
index 7cf0ba2..3abcd81 100644
--- a/menu.template
+++ b/menu.template
@@ -4,7 +4,7 @@
4 <meta charset="utf-8"> 4 <meta charset="utf-8">
5 <meta name="generator" contents="lcmark"> 5 <meta name="generator" contents="lcmark">
6 <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes"> 6 <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes">
7 <title>$pagetitle$</title> 7 <title>$title$</title>
8 <link rel="icon" type="image/png" href="$favicon$" /> 8 <link rel="icon" type="image/png" href="$favicon$" />
9 <style> 9 <style>
10html { 10html {
diff --git a/nYAW.png b/nYAW.png
new file mode 100644
index 0000000..3d756a0
--- /dev/null
+++ b/nYAW.png
Binary files differ
diff --git a/nYAW.xcf b/nYAW.xcf
new file mode 100644
index 0000000..369f57e
--- /dev/null
+++ b/nYAW.xcf
Binary files differ
diff --git a/nYAW_icon.png b/nYAW_icon.png
new file mode 100644
index 0000000..5788080
--- /dev/null
+++ b/nYAW_icon.png
Binary files differ
diff --git a/nYAW_icon.xcf b/nYAW_icon.xcf
new file mode 100644
index 0000000..512fd0b
--- /dev/null
+++ b/nYAW_icon.xcf
Binary files differ
diff --git a/notYetAnotherWiki.lua b/notYetAnotherWiki.lua
index 0ee0f10..f53691b 100755
--- a/notYetAnotherWiki.lua
+++ b/notYetAnotherWiki.lua
@@ -1,189 +1,967 @@
1#!/usr/bin/env luajit 1#!/usr/bin/env luajit
2 2
3local lcmark = require("lcmark") 3--[[ Read the README file for what this is all about.
4 If there is no README or similar, then you can find the link to the source below.
4 5
5local globalData = {version = '-0.1', header = '', footer = '', menu = '', ['_'] = '&nbsp;', ['dlr'] = '&dollar;'} 6 Normally I define functions and globals at the top, but here I'm interleaving them.
6local site = {} 7]]
7 8
8local createHTML = function(cm, file) 9local Lunamark = require("lunamark") -- https://github.com/jgm/lunamark
9-- cm = string.gsub(cm, '. ', '.&nbsp; ') 10local Lpeg = require("lpeg") -- https://www.inf.puc-rio.br/~roberto/lpeg/lpeg.html Lunamark uses this, so we can to.
10 if (nil ~= file) and ('' ~= file) then io.write('Parsing ' .. file .. ' -> ') end 11local RE = require("re") -- Part of lpeg. https://www.inf.puc-rio.br/~roberto/lpeg/re.html
11 local result = '' 12
12 local body, metadata, err = lcmark.convert(cm, "html", {smart = true, yaml_metadata = true, columns = 0}) 13
13 14---------------------------------------------------------------------------------
14 if nil == body then print('oops! ' .. err) else 15-- Some global data.
15 local bod, err = lcmark.compile_template(body) 16
16 if nil == bod then print('oops! ' .. err) else 17local GlobalMetaData = {
17 local templateFile = metadata.template 18 dlr = '&dollar;', perc = '%', dot = '.',
18 if nil == file then 19 devuanCinnabarDark = '#310202', devuanCinnabarLight = '#510505',
19 templateFile = nil 20 devuanDarkPurpyDark = '#33313b', devuanDarkPurpyLight = '#3c3a45',
20 else 21 devuanDeepSeaDark = '#132f40', devuanDeepSeaLight = '#1a4562',
21 if nil == templateFile then templateFile = 'default' end 22 devuanSaphireDark = '#004489', devuanSaphireLight = '#00509f',
22 templateFile = templateFile .. '.template' 23 devuanDevuanDark = '#000000', devuanDevuanLight = '#ffffff',
23 for k, v in pairs(globalData) do 24 -- HTML link colours. Naturally HTML5 deprecated the simple version, replacing it with less simple CSS.
24 if nill == metadata[k] then metadata[k] = v else print('metadata already has ' .. k) end 25 -- <body> has alink, link, vlink; CSS has active, link, visited, and hover.
25 end 26 devuanDevuanalink = '#03a4ff', devuanDevuanlink = '#0076b6', devuanDevuanvlink = '#6aa4db', devuanDevuanhlink = '#03a4ff',
26 end 27 devuanSDevuanalink = '#98c3db', devuanSDevuanlink = '#ffffff', devuanSDevuanvlink = '#ffffff', devuanSDevuanhlink = '#98c3db',
27 28 karenPurple = '#8800ff', onefangPurple = '#cc00ff', onefangGreen = '#42ff00',
28 if nil ~= file then 29 PinkFloyd = '#AA00AA', DeepPurple = '#220022', -- From an ancient site of mine, which went from PinkFloyd to DeepPurple as a background gradient.
29 local depth = 0 30 favicon = 'nYAW_icon.png', logo = 'nYAW.png',
30 local base = '' 31}
31 for p in string.gmatch(file, '(%w+)/') do 32
32 depth = depth + 1 33local Files, Subs, xLinks = {}, {}, {}
33 base = p 34local Context = {} -- Coz can't otherwise pass context through to the deeper Lunamark functions I'm overriding.
34 end 35
35 local path = string.sub(file, 1, #base) 36local Template = ''
36 37local h = io.open("default.template", 'r')
37 metadata.header = '' 38if nil ~= h then
38 metadata.menu = '' 39 Template = h:read('*a')
39 local trl = {} 40 h:close()
40 metadata.trail = '' 41else
41 local dir = site[''] 42 print('oops! No such file ' .. 'default.template')
42 local dr, pdr, tr = '', '', '' 43end
43 while nil ~= dir.subs do 44
44 local old = dir 45
45 for m, x in pairs(dir.subs) do 46---------------------------------------------------------------------------------
46 if x == string.sub(file, 1, #x) then 47-- Useful functions, part 0.
47 pdr = pdr .. '/' .. m 48
48 tr = tr .. '../' 49-- A simple table.subtable = subtable wont work, you end up with a reference so that changes to the later get applied to the former.
49 dr = m 50local derefiTable = function(t, strip)
50 dir = site[dr] 51 local argh = {}
51 table.insert(trl, '">' .. m .. '</a> &#x1f463;') 52 for l, y in ipairs(t) do if (l ~= y.name) and strip then table.insert(argh, y) end end
52 break 53 return argh
53 end 54end
55local derefTable = function(t, strip)
56 local argh = {}
57 for l, y in pairs(t) do argh[l] = y end
58 return argh
59end
60
61
62local writeString = function(base, body)
63 local a, e = io.open(base, 'w')
64 if nil == a then print('Could not open ' .. base .. ' - ' .. e) else
65 a:write(body)
66 a:close()
67 end
68end
69
70
71-- String together the bits array into a path string. Or the other way around. lol
72local stringBits = function(l)
73 local bits = {}
74 local last = 1
75 for j = 1, #l do
76 if '/' == string.sub(l, j, j) then
77 table.insert(bits, string.sub(l, last, j - 1))
78 last = j + 1
79 end
80 end
81 return bits, string.sub(l, last)
82end
83
84
85-- Put a value into the Files or Subs table, creating things if needed.
86local toFile = function(name, key, value)
87 if nil == Files[name] then
88 local bits, bit = stringBits(name)
89 local path = ''
90 Files[name] = {}
91 Files[name].headers = {}
92 Files[name].bits = bits
93 Files[name].bit = bit
94 for i, d in ipairs(bits) do
95 if '' ~= path then path = path .. '/' end
96 path = path .. d
97 end
98 Files[name].path = path
99-- Files[name].body = ''
100 if ("Foswiki" == bits[1]) or ("PmWiki" == bits[1]) then Files[name].ogWiki = bits[1] end
101 end
102 if nil ~= key then Files[name][key] = value end
103 for i, v in ipairs{'metadata', 'bits', } do
104 if nil == Files[name][v] then Files[name][v] = {} end
105 end
106 -- Open the files and do the initial cleanups.
107 local body = ''
108 if '.md' ~= string.sub(name, -3, -1) then
109 h = io.open(name .. '.md', 'r')
110 if nil ~= h then
111-- print('Parsing ' .. name .. '.md')
112 Context = Files[name]
113 body = h:read('*a') ; h:close()
114 -- Deal with my typical double spaced sentence endings, and other things.
115 local result = RE.compile( [=[{~
116 (
117 {[.?!]{" "}} -> '%1&nbsp;' / -- '&nbsp;' gets turned into hex 0xA0 by parse(). So feed it another metadata token that gets translated to &nbsp;. Seems we now skip this issue.
118 {[\\]{['"|$]}} -> '%2' / -- Do the same for fixing the \' \" \| etc mess pandoc left.
119 {"[ ]{.foswikiGrayFG}" } -> '' / -- Coz Foswiki sucks. No idea why the next thing didn't catch it.
120 {"[" {([^]])+} "]{.foswiki" {([^FG}])+} "FG}" } -> "<span style='color: %3;'>%2</span>" /
121 {"::: {."[A-Za-z_. ]+"}"} -> '' /
122 {":::"} -> '' /
123 {"-noComment-"} -> ' -- ' /
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>" /
127 {"{#"[A-Za-z_]+"}"} -> '' /
128 {"### [[edit](/bin/edit/Main/" {([^%nl])+} } -> '' /
129 {"#"+ " " {([^%nl])+} } -> header /
130 .
131 )* ~}]=], { header = function(a) table.insert(Context.headers, a); return a end } ):match(body)
132 body = result
133-- {"<!--".*"-->"} -> '' /
134-- {"[$]"} -> '$dlr$' / -- Replace $, coz otherwise it confuses things later.
135 body = RE.gsub(body, '{[$]}', '$dlr$')
136-- {"[%]"} -> '$perc$' / -- Gotta be done after the %1's above. otherwise screws things up when included above.
137-- body = RE.gsub(body, '{[%]}', '$perc$') -- Coz otherwise stray % trip up the capture part.
138 end
139 Files[name].body = body
140 end
141end
142local toSub = function(name, key, value)
143 if nil == Subs[name] then
144 local bits, bit = stringBits(name)
145 local path = ''
146 Subs[name] = {}
147 table.insert(bits, bit)
148 Subs[name].bits = bits
149 Subs[name].bit = bit
150 for i, d in ipairs(bits) do
151 if '' ~= path then path = path .. '/' end
152 path = path .. d
153 end
154 Subs[name].path = path
155 end
156 if nil ~= key then Subs[name][key] = value end
157 for i, v in ipairs{'metadata', 'bits', 'files', 'subs'} do
158 if nil == Subs[name][v] then Subs[name][v] = {} end
159 end
160end
161
162
163
164local readMdMd = function(name, metadata)
165 local h1 = io.open(name .. '.md')
166 if nil == h1 then
167-- print('Could not open ' .. name .. '.md')
168 return {}
169 else
170 for l in h1:lines() do
171 for k, v in string.gmatch(l, "(%w+)%s*=%s*(.+)") do
172 if nil == v then
173 print(name .. ' ' .. k)
174 else
175 metadata[k] = v
54 end 176 end
55 if old == dir then break end
56 end
57 table.remove(trl)
58 for m, x in ipairs(trl) do
59 tr = string.sub(tr, 4)
60 trl[m] = '&nbsp;<a href="' .. tr .. x
61 end 177 end
62 metadata.trail = table.concat(trl) 178 end
179 end
180 return metadata
181end
63 182
64 if nil ~= dir.files then 183
65 local l = {} 184
66 for m, x in pairs(dir.files) do table.insert(l, {m = m; x = x}) end 185local commonLinky = function(l, body, u, url, beg, en, beg0, en0, bump)
67 table.sort(l, function(a, b) return (a.m <= b.m) end) 186 if nil == url then
68 for m, x in ipairs(l) do 187-- print('OOPS! unknown linky - @' .. l .. '\t\t\t' .. string.sub(body, beg - 9, en) .. ' ' .. string.sub(body, en + 1, en0))
69 metadata.menu = metadata.menu .. '<p><a href="' .. string.sub(x.x, 1 + #pdr) .. '.HTML">' .. x.m .. '</a></p>\n' 188 else
70 end 189 local md = readMdMd(url, {})
190-- if nil ~= md then
191 if nil ~= md.realURL then url = md.realURL end
192-- end
193 body = string.sub(body, 1, beg - bump) .. url .. string.sub(body, en0 + 1)
194 here = here + string.len(url)
195 end
196 if 1 == bump then
197 here = here + 1
198 beg, en = RE.find(body, [['https://fos.wiki.devuan.org/']], here)
199 else
200 beg, en = RE.find(body, [["'https://wiki.devuan.org/"]], here)
71 end 201 end
72 if nil ~= dir.subs then 202 return beg, en, body, here
73 local l = {} 203end
74 for m, x in pairs(dir.subs) do table.insert(l, {m = m; x = x}) end 204
75 table.sort(l, function(a, b) return (a.m <= b.m) end) 205
76 for m, x in pairs(l) do 206
77 metadata.header = metadata.header .. '<a href="' .. string.sub(x.x, 1 + #pdr) .. '">' .. x.m .. '</a> &nbsp; ' 207---------------------------------------------------------------------------------
208-- Actually start doing things.
209
210-- Create the base of everything.md here, so it gets picked up as usual in the file scan.
211h = io.open('everything.md', 'w')
212if nil ~= h then
213 h:close()
214else
215 print("Can't open everything.md for writing.")
216end
217
218-- Scan the sub folders looking for our files.
219local Folder = arg[1]
220toSub('')
221if nil == Folder then Folder = '.' end
222--GlobalMetaData.root = Folder
223
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]]
235for l in io.popen('find -L ' .. Folder .. ' -name unsorted -prune -o -name "*.md.md" -xtype l -printf "%P\n"'):lines() do
236 local metadata = readMdMd(string.sub(l, 1, -4), {})
237 if nil == metadata.realURL then
238 metadata.realURL = string.sub(l, 1, -7)
239 else
240 if metadata.realURL ~= string.sub(l, 1, -7) then
241 metadata.realURL = string.sub(l, 1, -7)
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()
257 end
258 end
259end
260
261-- Clean up unsorted.
262for 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
263 local tp = '_fos'
264 local metadata = readMdMd(l, {})
265 if nil ~= metadata then
266 if "PmWiki" == metadata.ogWiki then tp = '_pm' end
267 if nil ~= metadata.ogFile then
268 local unsort = 'unsorted/' .. metadata.ogFile
269 local a, e = io.open(unsort .. tp .. '.md' , 'r')
270 if nil ~= a then
271 a:close()
272 -- Keep the .md.md symlink, delete the rest.
273 os.execute('rm ' .. unsort .. tp .. '.HTML')
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
78 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)
79 end 292 end
293
80 end 294 end
295 end
296 end
297end
81 298
82 metadata.body = lcmark.apply_template(bod, metadata) 299-- Look for copied pages from the other wikis.
300for 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')
306os.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()
311writeString(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( [[{~
328 (
329 {'class="foswikiCurrentTopicLink"'} -> blank /
330 {'class="foswikiNewLink"'} -> blank /
331 {"<span class='foswikiSmall'><a href='/bin/edit/Main/" ([^;action=form])* ";action=form'>edit</a></span>"} -> blank /
332 {" -- "} -> '-noComment-' /
333-- {"-- " ([^%nl])* } -> blank /
334 {'<div class="foswikiTopic">'} -> blank /
335 {'rel="nofollow"'} -> blank / {"rel='nofollow'"} -> blank /
336 {"target='_blank'"} -> blank /
337 {"</div>" ([%nl])* } -> blank /
338-- {'style="' ([^"])+ '"'} -> blank / {"style='" ([^'])+ "'"} -> blank /
339 .
340 )* ~}]], { blank = function(a) return '' end } ):match(body)
341 body = result
342-- body = RE.gsub(body, [=[{"<!-- ".*"-->"}]=], '') -- FIXME
343 local here = 1
344 beg, en = RE.find(body, [['https://fos.wiki.devuan.org/']], here)
345 while nil ~= beg do
346 here = beg + 1
347 local beg0, en0
348 local url = nil
349 if '"' == string.sub(body, beg - 1, beg - 1) then
350 beg0, en0 = RE.find(body, [['"']], en)
351 url = string.sub(body, en + 1, en0 - 1)
352 end
353 if "'" == string.sub(body, beg - 1, beg - 1) then
354 beg0, en0 = RE.find(body, [["'"]], en)
355 url = string.sub(body, en + 1, en0)
356 end
83 357
84 local tm = '' 358 if nil ~= url then
85 if nil ~= templateFile then 359 if ('pub/' == string.sub(url, 1, 4)) then
86 local h = io.open(templateFile, 'r') 360-- FIXME? - evil hack?
87 if nil ~= h then 361 url = 'Foswiki/' .. url
88 tm = tm .. h:read('*a') 362--print('FOSWIKI HTM ' .. url)
89 h:close() 363 else
364 url = nil
365 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))
90 else 373 else
91 print('oops! No such file ' .. templateFile) 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]=]
92 end 384 end
93 385
94 local template, err = lcmark.compile_template(tm) 386 writeString(l .. '_NEW', body)
95 if nil == template then print('oops! ' .. err) else 387 elseif 'PmWiki' == string.sub(l, 1, 6) then
96 result = lcmark.apply_template(template, metadata) 388 local beg, en = RE.find(body, [['<!--PageText-->']]) 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
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.
391 beg, en = RE.find(body, [['<!--HTMLFooter-->']]) if nil ~= beg then body = string.sub(body, 1, beg - 2) end
392 local result = RE.compile( [[{~
393 (
394 {"class='categorylink'"} -> blank /
395 {"class='createlink'"} -> blank /
396 {"class='createlinktext'"} -> blank /
397 {"class='escaped'"} -> blank /
398 {"class='diffmarkup'"} -> blank /
399 {"class='selflink'"} -> blank /
400 {"class='urllink'"} -> blank /
401 {"<div class='vspace'></div><hr /> <a class='wikilink' href='https://wiki.devuan.org?n=Profiles." .* ([%nl])* } -> blank /
402 {"<a class='selflink' href='https://wiki.devuan.org?n=Profiles." .* ([%nl])* } -> blank /
403 {"<div class='vspace'></div><hr />"} -> blank /
404 {"<div class='vspace'></div>"} -> blank /
405 {"class='wikilink'"} -> blank /
406 {'rel="nofollow"'} -> blank / {"rel='nofollow'"} -> blank /
407 {"target='_blank'"} -> blank /
408-- {'style="' ([^"])+ '"'} -> blank / {"style='" ([^'])+ "'"} -> blank /
409 {"<span class='hlt " {([a-z])+} "'></span><pre" } -> "<pre class='%2'" /
410 .
411 )* ~}]], { blank = function(a) return '' end } ):match(body)
412 body = result
413-- body = RE.gsub(body, [=["<a " {([^ >])+} " >"]=], "<a %1>")
414-- DONE? - <span class='hlt html'></span><pre style='background-color: #cc00ff;' class='escaped'> ... lines of HTML code ... </pre>
415-- most of the time I'll see <pre class='escaped'>
416-- My own looking glass has several.
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)
427-- FIXME? - This might be working around a bug elsewhere.
428 if "'" == string.sub(body, en0, en0) then en0 = en0 - 1 end
429 local url = string.sub(body, en + 1, en0)
430 if '?n=' == string.sub(url, 1, 3) then
431 url = string.sub(url, 4):gsub('[%a]+%.([%a-]+)', '%1_pm.HTML')
432 elseif ("'" == url) or ('uploads/' == string.sub(url, 1, 8)) then
433-- FIXME - evil hack? Yep, evil hack, need to know the depth of the source, which isn't here.
434 url = 'PmWiki/' .. url
435 else
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
97 end 441 end
98 else 442
99 result = body 443 writeString(l .. '_NEW', body)
100 end 444 end
101 end 445 end
446
447 ok, rslt, status = os.execute('pandoc --wrap=preserve -f html -t commonmark_x --self-contained ' .. l .. '_NEW' .. ' >' .. string.sub(l, 1, -4) .. 'md')
102 end 448 end
449end
103 450
104 if ('' ~= result) and (nil ~= file) then 451if '.' ~= Folder then
105 local base = string.gsub(file, '%.md$', '') 452 for l in io.popen('find -L . -name "*.md" -type f,l -printf "%P\n"'):lines() do
106 print(base .. '.HTML') 453 toFile(string.gsub(l, '%.md$', ''))
107 local a, e = io.open(base .. '.HTML', 'w') 454 end
108 if nil == a then print('Could not open ' .. base .. '.HTML - ' .. e) else 455end
109 a:write(result) 456
110 a:close() 457-- Can add in a distant folder to, for putting it's results in the current folder.
458for l in io.popen('find -L ' .. Folder .. ' -name "*.md" -type f,l -printf "%P\n"'):lines() do
459 local n = string.gsub(l, '%.md$', '')
460 if nil == Files[n] then toFile(n) end
461end
462
463
464-- Gotta figure out all the files and subs first. File and sub metadata comes along for the ride, coz we need them later.
465local NewMeta = {}
466for name, file in pairs(Files) do
467 local bitter, path = '', ''
468 local bits, bit = file.bits, file.bit
469 local ln = #bits
470 local body, metadata = '', {}
471
472 -- Go through our bits, construct Subs with bits.
473 if ln > 0 then bitter = bits[1] end
474 if '' ~= bitter then Subs[''].subs[bitter] = bitter end -- "bitter end" was entirely by accident, I'm keeping it. B-)
475 for i, d in ipairs(bits) do
476 if '' ~= path then path = path .. '/' end
477 path = path .. d
478 toSub(path)
479 if i < ln then
480 Subs[path].subs[bits[i + 1]] = bits[i + 1]
481 table.remove(Subs[path].bits, #bits)
111 end 482 end
112 else
113 print('')
114 end 483 end
115 return result 484
485 if '.md' == string.sub(name, -3, -1) then
486 -- This is a metadata only file, no content, stash the matadata.
487
488 metadata = readMdMd(name, metadata)
489 if '.md' == name then toSub(path, 'metadata', metadata)
490 elseif '/.md' == string.sub(name, -4, -1) then toSub(path, 'metadata', metadata)
491-- else toFile(string.sub(name, 1, -4), 'metadata', metadata)
492 else NewMeta[string.sub(name, 1, -4)] = metadata -- Coz we can't add to Files here.
493 end
494 Files[name] = nil
495 end
496end
497
498-- FIXED - Lua doesn't like modifying the thing you are pair()ing, like we want to do in the last loop.
499for name, file in pairs(NewMeta) do
500 if nil == Files[name] then toFile(name) end
501 for k, v in pairs(file) do
502 if nil == Files[name].metadata[k] then Files[name].metadata[k] = v end
503 end
116end 504end
117 505
118local directory = arg[1] 506-- Fix up subs now we have all the file bits.
119if nil == directory then directory = '.' end 507for name, file in pairs(Files) do
120local all = {} 508 if '.md' ~= string.sub(name, -3, -1) then
121if '.' ~= directory then 509 table.insert(Subs[file.path].files, file.bit)
122 for l in io.popen('find . -name "*.md" -type f,l -printf "%P\n"'):lines() do
123 all[l] = l
124 end 510 end
125end 511end
126for l in io.popen('find ' .. directory .. ' -name "*.md" -type f,l -printf "%P\n"'):lines() do 512
127 if nil == all[l] then all[l] = l end 513-- Find empty subs.
514for 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
128end 525end
129 526
130for i, l in pairs(all) do
131 local dir = ''
132 local files, subs = {}, {}
133 local c, parent = 1, ''
134 527
135 for p in string.gmatch(l, '(%w+)/') do 528---------------------------------------------------------------------------------
136 if '' == dir then 529-- These functions assume the above file and sub scan has completed.
137 dir = p 530
138 if nil ~= site[dir] then 531-- Which page in this folder should we show?
139 subs = site[dir].subs 532-- NOTE - only looking for the .md files we scanned for before, any stray HTML, html, HTM, and htm files will get ignored.
140 files = site[dir].files 533local whichPage = function(f)
534 local fl = ''
535 if nil ~= Subs[f] then
536 if nil ~= Subs[f].whichPage then return Subs[f].whichPage end
537 if nil ~= Subs[f].files then
538 if 1 == #(Subs[f].files) then fl = Subs[f].files[1] else
539 -- Standard files to search for.
540 for i, v in ipairs{'about', 'readme', 'index', 'homepage', 'mainpage', 'webhome'} do
541 for j, w in ipairs(Subs[f].files) do
542 if v == string.lower(w) then
543 fl = w
544 break
545 end
546 end
547 if '' ~= fl then break end
548 end
549 -- If nothing else, just grab the first one.
550 if ('' == fl) and (nil ~= Subs[f].files[1]) then fl = Subs[f].files[1] end
141 end 551 end
142 end 552 end
553 end
554 if '' ~= fl then fl = fl .. '.HTML' ; Subs[f].whichPage = fl end
555 return fl
556end
557
143 558
144 local path = string.sub(l, 1, -1 - #(string.gsub(l, '.*/', ''))) 559-- Figure out the original title and link for the original wiki.
145 if nil ~= site[parent] then 560local whichWiki = function(metadata)
146 if nil == site[parent].subs then site[parent].subs = {} end 561 local title, link = '', ''
147 site[parent].subs[p] = path 562 if 'PmWiki' == metadata.ogWiki then
148 elseif 1 == c then subs[p] = path 563 title = metadata.ogBase .. '.' .. metadata.ogFile
564 link = metadata.ogURL .. '/?n=' .. metadata.ogBase .. '.' .. metadata.ogFile
565 end
566 if 'Foswiki' == metadata.ogWiki then
567 title = metadata.ogBase .. '/' .. metadata.ogFile
568 link = metadata.ogURL .. '/' .. metadata.ogBase .. '/' .. metadata.ogFile
569 end
570 return title, link
571end
572
573
574-- Calculate a link from the source folder to the destination folder.
575local linkFrom = function(source, dest)
576 -- Evil hacks!
577 if 'Profiles' == dest then dest = 'PmWiki/Profiles' end
578 if 'Onefang' == dest then dest = 'PmWiki/Onefang' end
579 if 'Tiki' == dest then dest = 'PmWiki/Tiki' end
580
581 if source == dest then return '' end
582 local depth = 0
583 local lnk = ''
584 if source ~= dest then
585 if nil == Subs[source] then
586-- print('!!!! No idea where to find source ' .. source)
587 return 'DUNNO'
588 end
589 if nil == Subs[dest] then
590 if dest == Subs[source].bit then
591 return ''
592 else
593-- print('!!!! No idea where to find dest ' .. dest .. ' from ' .. Subs[source].path .. ' / ' .. Subs[source].bit)
594 return 'DUNNO'
595 end
596 end
597 local s = Subs[source].bits
598 local d = Subs[dest].bits
599 local sl = #s
600 local dl = #d
601
602 if 0 == dl then
603 depth = sl
149 else 604 else
150 if ('' ~= parent) and (dir == parent) then subs[p] = path end 605 for i, v in ipairs(s) do
151 site[parent] = {subs = {[p] = path}} 606 if (nil == d[i]) or (v ~= d[i]) then
607 depth = i
608 break
609 end
610 end
152 end 611 end
153 c = c + #p + 1 612 -- depth is where they DON'T match.
154 parent = p 613 local m = depth - 1
614 if 0 > m then m = 0 end
615 lnk = string.rep('../', sl - m)
616 if 0 ~= (m + 1) then lnk = lnk .. table.concat(d, '/', m + 1, dl) end
155 end 617 end
618 return lnk
619end
620
621
622
623---------------------------------------------------------------------------------
624-- More of this actually doing things nonsense.
156 625
157 if (1 == c) and (nil ~= site[dir]) then 626-- Create an "everything" page, for URL links to every file.HTML.
158 subs = site[dir].subs 627local Bdy = '# All the pages\n\n| page | original page | last edited UTC | \n| --------- | ------- | --------------- | '
159 files = site[dir].files 628Pages = {}
629for name, file in pairs(Files) do
630 local metadata = derefTable(Files[name].metadata, true)
631 if ('everything' ~= name) then
632 local ln, fw, pw, ts = 'DUNNO', '', '', ''
633 local title, link = whichWiki(metadata)
634 link = string.gsub(link, 'https://', 'HTTPS://') -- Prevent this one from being converted.
635 if 'PmWiki' == metadata.ogWiki then pw = 'PmWiki [' .. title .. '](' .. link .. ')' end
636 if 'Foswiki' == metadata.ogWiki then fw = 'Foswiki [' .. title .. '](' .. link .. ')' end
637 if nil ~= metadata.timestamp then ts = metadata.timestamp end
638 if nil ~= file.bit then ln = file.bit
639 end
640 table.insert(Pages, '\n| [' .. name .. '](<' .. name .. '.HTML>) | ' .. fw .. ' ' .. pw .. ' | ' .. ts .. ' |')
641
642 -- Track our external links.
643 if (nil ~= metadata.ogBase) and (nil ~= metadata.ogFile) then
644 local n = metadata.ogBase
645 if 'PmWiki' == metadata.ogWiki then n = n .. '.' else n = n .. '/' end
646 xLinks[n .. metadata.ogFile] = file.path
647 end
160 end 648 end
649end
650table.sort(Pages, function(a, b) return (string.lower(a) < string.lower(b)) end)
651for i, f in ipairs(Pages) do
652 Bdy = Bdy .. f
653end
654h = io.open('everything.md', 'a+')
655if nil ~= h then
656 h:write(Bdy)
657 h:close()
658else
659 print("Can't open everything.md for writing.")
660end
661toFile('everything', 'body', Bdy)
161 662
162 local base = string.gsub(string.sub(l, c, -1), '%.md$', '') 663
163 if nil ~= site[parent] then site[parent].files[base] = string.sub(l, 1, -4) 664-- Loop through Subs, doing whichPage and inheritance.
164 elseif 1 == c then files[base] = string.sub(l, 1, -4) 665-- It gets to testing/even/deeper BEFORE it gets to testing/even sometimes. So sort them.
165 else 666SUBS = {}
166 if ('' ~= parent) and (dir == parent) then files[base] = string.sub(l, 1, -4) end 667for name, sub in pairs(Subs) do
167 site[parent] = {files = {[base] = string.sub(l, 1, -4)}} 668 table.insert(SUBS, sub)
669end
670table.sort(SUBS, function(a, b) return (string.lower(a.path) < string.lower(b.path)) end)
671for n, sub in pairs(SUBS) do
672 local name = sub.path
673 sub.whichPage = whichPage(name)
674 local metadata = sub.metadata
675 for i, s in pairs(sub.subs) do
676 local nm = i
677 if '' ~= name then nm = name .. '/' .. i end
678 for k, v in pairs(metadata) do
679 if nil == Subs[nm].metadata[k] then
680 if ('favicon' == k) or ('logo' == k) then
681 Subs[nm].metadata[k] = linkFrom(nm, name) .. v
682 else
683 if 'hidden' ~= k then -- Don't inherit hidden.
684 Subs[nm].metadata[k] = v
685 end
686 end
687 end
688 end
168 end 689 end
690end
169 691
170-- FIXME - still some minor bug somewhere, this fixes that, but causes other problems. Meh, I can live with excess empty subs tables. 692-- Files inheritance.
171-- if (nil ~= subs) and (0 == #subs) then subs = nil end 693for name, file in pairs(Files) do
172 site[dir] = {files = files, subs = subs} 694 if '' ~= file.body then
695 local mdata = Subs[file.path].metadata
696 for k, v in pairs(mdata) do
697 if nil == file.metadata[k] then
698 Files[name].metadata[k] = v
699 end
700 end
701 end
173end 702end
174 703
175for k, v in pairs(site) do 704
176 if nil ~= v.files then 705---------------------------------------------------------------------------------
177 for m, x in pairs(v.files) do 706-- Setup the lunarmark stuff.
178 local file = x .. '.md' 707local LunamarkOpts = {
179 local h = io.open(file, 'r') 708 layout='compact',
180 if nil ~= h then 709-- This list is copied from the lunamark source code, until I discover a way to discover it. The descriptions are useful to.
181 createHTML(h:read('*a'), file) 710 containers=false, -- Put sections in containers (e.g. div or section tags)
182 h:close() 711 slides=false, -- Like containers, but do not nest them
712 startnum=true, -- Start number of an ordered list is significant
713 smart=false, -- Smart typography (quotes, dashes, ellipses)
714 preserve_tabs=true, -- Don't expand tabs to spaces
715 notes=true, -- Footnotes
716 inline_notes=true, -- Inline footnotes
717 definition_lists=true, -- Definition lists
718 citations=true, -- Citations
719 citation_nbsps=true, -- Turn spacing into non-breaking spaces in citations
720 fenced_code_blocks=true, -- Fenced code blocks
721 lua_metadata=true, -- Lua metadata
722 pandoc_title_blocks=true, -- Pandoc style title blocks
723 hash_enumerators=true, -- may be used as ordered list enumerator
724 require_blank_before_blockquote=false,
725 require_blank_before_header=false,
726 require_blank_before_fenced_code_block=false,
727 fancy_lists=true, -- Pandoc style fancy lists
728 task_list=true, -- GitHub-Flavored Markdown task list
729 strikeout=true, -- Strike-through with double tildes
730 mark=true, -- Highlight with double equals
731 subscript=true, -- Subscripted text between tildes
732 superscript=true, -- Superscripted text between circumflexes
733 bracketed_spans=true, -- Spans with attributes
734 fenced_divs=true, -- Divs with attributes
735 raw_attribute=true, -- Raw pass-through on code elements
736 fenced_code_attributes=true, -- Fenced code block attributes
737 link_attributes=true, -- Link attributes
738 pipe_tables=true, -- PHP Markdown Extra pipe table support
739 table_captions=true, -- Table caption syntax extension
740 header_attributes=true, -- Header attributes
741 line_blocks=true, -- Line blocks
742 escaped_line_breaks=true, -- Pandoc-style escaped hard line breaks
743}
744local Writer = Lunamark.writer.html5.new(LunamarkOpts)
745-- Can override the various writer functions, there's something for each of the basic HTML elements.
746local lunaLinky = function(url) -- Fix up the links.
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'
183 else 753 else
184 print('oops! No such file ' .. file) 754 url = link .. '/' .. string.sub(url, 7) .. '.HTML'
185 end 755 end
756 end
757 if '/System/' == string.sub(url, 1, 8) then
758 url = 'https://fos.wiki.devuan.org' .. url
759 end
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
761 if p == string.sub(url, 1, #p) then
762 local ur = string.sub(url, #p + 1)
763-- TODO - could probably replace some of this mess with RE.gsub() and friends. Meh, it works.
764 local f4, f5, tk1 = string.find(ur, '?', 1, true)
765 if fail ~= f4 then
766 local u = string.sub(ur, 1, f4 - 1)
767 ur = u
768 end
769 local md
770 if ('fos' == string.sub(p, 9, 11)) or ('Fos' == string.sub(p, 1, 3)) then
771 md = readMdMd('Foswiki/' .. ur .. '.md', {})
772 else
773 md = readMdMd('PmWiki/' .. string.gsub(ur, '%.', '/', 1) .. '.md', {})
774 end
775 if (nil ~= md) and (nil ~= md.realURL) then url = md.realURL end
186 776
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
778 local xlnk = xLinks[string.gsub(ur, '%..*', '', 1)]
779 if nil == Context.path then
780 url = string.gsub(ur, '%.', '/', 1)
781 else
782 if nil == xlnk then xlnk = string.gsub(string.gsub(ur, '%..*', '', 1), '/.*', '', 1) end
783 if '' ~= Context.path then xlnk = linkFrom(Context.path, xlnk) end
784 if '/' == string.sub(xlnk, 1, 1) then xlnk = string.sub(xlnk, 2) end
785 if ('' ~= xlnk) and ('/' ~= string.sub(xlnk, -1)) then xlnk = xlnk .. '/' 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
788-- if (nil ~= md) and (nil ~= md.realURL) then url = md.realURL
789-- else
790 url = xlnk .. string.gsub(ur, '.*%.', '', 1)
791-- end
792 if 'PmWiki/uploads/' == p then
793 url = '../../' .. p .. string.gsub(ur, '%.', '.', 1)
794 elseif 'Foswiki/pub/' == p then
795 url = '../../' .. p .. ur
796 else
797 url = url .. '.HTML'
798 end
799 end
800 end
187 end 801 end
188 end 802 end
803 return url
189end 804end
805
806function 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 .. '>'
811end
812local OgWriterLink = Writer.link -- So we can call the original from within mine, we are just changing the URL.
813function Writer.link(lab, url, tit)
814 return OgWriterLink(lab, lunaLinky(url), tit)
815end
816local OgWriterImage = Writer.image
817function Writer.image(lab, url, tit)
818 return OgWriterImage(lab, lunaLinky(url), tit)
819end
820
821local Parse = Lunamark.reader.markdown.new(Writer, LunamarkOpts)
822
823
824---------------------------------------------------------------------------------
825-- Loop through the files we found and actually create their HTML files.
826for name, file in pairs(Files) do
827 local body, metadata = Files[name].body, derefTable(Files[name].metadata, true)
828 local bits, bit = Files[name].bits, Files[name].bit
829 local ln = #bits
830 local result = ''
831
832 if '' ~= body then
833 -- Figure out this pages trail links.
834 metadata.home = linkFrom(file.path, '') .. Subs[''].whichPage
835 metadata.trail = ''
836 for i, b in ipairs(bits) do
837 local p = table.concat(bits, '/', 1, i)
838 if i < #bits then
839 metadata.trail = metadata.trail .. '<a href="' .. linkFrom(file.path, p) .. Subs[p].whichPage .. '">' .. b .. '</a> &nbsp; &#x1f463; '
840 linkFrom(file.path, table.concat(bits, '/', 1, i))
841 else
842 metadata.trail = metadata.trail .. ' ' .. b
843 end
844 end
845
846 -- Figure out this pages header links.
847 metadata.header = ''
848 subs = {}
849 for i, f in pairs(Subs[file.path].subs) do
850 table.insert(subs, f)
851 end
852 table.sort(subs, function(a, b) return (string.lower(a) < string.lower(b)) end)
853 for i, f in ipairs(subs) do
854 local pth = file.path
855 if '' ~= file.path then pth = file.path .. '/' end
856 if 'true' ~= Subs[pth .. f].metadata.hidden then
857 metadata.header = metadata.header .. '<a href="' .. f .. '/' .. whichPage(pth .. f) .. '">' .. f .. '</a> &nbsp; &#128194; '
858 end
859 end
860
861 -- Figure out this pages menu links.
862 metadata.menu = ''
863 if nil == metadata.title then metadata.title = bit end
864 if nil ~= Subs[file.path].files then table.sort(Subs[file.path].files, function(a, b) return (string.lower(a) < string.lower(b)) end) end
865 for i, f in ipairs(Subs[file.path].files) do
866 local title, url = nil, nil
867 if '' == file.path then
868 title = Files[f].metadata.title
869 url = Files[f].metadata.URL
870 else
871 title = Files[file.path .. '/' .. f].metadata.title
872 url = Files[file.path .. '/' .. f].metadata.URL
873 end
874 if nil == title then title = f end
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, '{[ ]}', '&nbsp;')
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('&nbsp;', l) .. '<a style="font-size: 0.80em;" href="#' .. RE.gsub(g, '{[ ]}', '_') .. '">' .. h .. '</a></p>'
891 end
892 else
893 if nil ~= url then metadata.menu = metadata.menu .. '<p><a href="' .. url .. '">' .. title .. ' &#9757;</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
903 end
904 end
905 end
906
907 -- Figure out this pages footer links.
908 local temp = ''
909 metadata.footer = ''
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&nbsp;<a href="' .. metadata.pagehistory .. temp .. '">history</a></p>' else
917 metadata.history = ''
918 end
919 if nil ~= metadata.sourcecode then metadata.footer = '<a href="' .. metadata.sourcecode .. '">source code</a>' end
920 if nil ~= metadata.feedatom then metadata.footer = '<a href="' .. metadata.feedatom .. '">atom feed<img src="feed-icon-14x14.png"></img></a> &nbsp; &nbsp; ' .. metadata.footer end
921 if metadata.footer ~= '' then metadata.footer = 'Web site ' .. metadata.footer end
922 -- Add a link to the original page.
923 if nil ~= metadata.ogURL then
924 local title, link = whichWiki(metadata)
925 link = string.gsub(link, 'https://', 'HTTPS://') -- Prevent this one from being converted.
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?
927 local edit = 'T'
928 if 'PmWiki' == metadata.ogWiki then edit = 'Maybe you can <a href="' .. link .. '?action=edit">edit</a> t' end
929-- if 'Foswiki' == metadata.ogWiki then edit = '' end
930 metadata.footer = edit .. 'he <a href="' .. link .. '">original page</a>. &nbsp; ' .. metadata.footer
931 end
932 metadata.footer = '<p>' .. metadata.footer .. '</p>'
933
934 -- Do our own metadata replacement, it's simple and works better.
935 local temp = Template
936 -- Toss the body in first, so the scan can deal with it to.
937 -- NOTE - this is where we actually parse the markup into HTML.
938 Context = file
939 body = RE.gsub(body, '{[%nl]^1[%a]+}[.]^1 ', '%1$dot$ ') -- Coz otherwise stray . trip up the list detection.
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.
941 bd = RE.gsub(bd, '{[%]}', '$perc$') -- Coz otherwise stray % trip up the capture part.
942 temp = RE.gsub(temp, '"$body$"', bd)
943 -- The actual metadata replacement.
944 result = RE.compile ('{~ ({[$][A-Za-z_]+[$]} -> meta / .)* ~}',
945 {
946 meta = function(a)
947 a = string.sub(a, 2, -2)
948 local md = metadata[a]
949 if nil == md then
950 md = GlobalMetaData[a]
951 if nil == md then
952 md = a
953 end
954 end
955 return md
956 end
957 } ):match(temp)
958
959 -- Write the file.
960 if '' ~= result then
961-- print('From ' .. name .. '.md -> ' .. base)
962 writeString(name .. '.HTML', result)
963 end
964 end
965end
966
967
diff --git a/testing/.md.md b/testing/.md.md
new file mode 100644
index 0000000..28c4410
--- /dev/null
+++ b/testing/.md.md
@@ -0,0 +1 @@
logo=Connie_click-me.gif
diff --git a/testing/Connie_click-me.gif b/testing/Connie_click-me.gif
index 35d25cd..6f0b361 120000..100644
--- a/testing/Connie_click-me.gif
+++ b/testing/Connie_click-me.gif
Binary files differ
diff --git a/testing/index.md b/testing/index.md
index 54808d5..581d301 100644
--- a/testing/index.md
+++ b/testing/index.md
@@ -1,74 +1,94 @@
1--- 1# G'day world!
2favicon: cartdave_favicon.png 2
3pagetitle: "G'day world!" 3I've been around since the early sixties, but no one ever noticed. You
4author: onefang 4really should have tried to pay attention though, I'm awesome. I try to
5feedatom: https://sledjhamr.org/cgit/notYetAnotherWiki/atom 5help the world, but that's not what everyone wants me to do. Well, the
6history: https://sledjhamr.org/cgit/notYetAnotherWiki/log/testing/index.md
7sourcecode: https://sledjhamr.org/cgit/notYetAnotherWiki/
8---
9
10I've been around since the early sixties, but no one ever noticed.&nbsp; You
11really should have tried to pay attention though, I'm awesome.&nbsp; I try to
12help the world, but that's not what everyone wants me to do.$_$ Well, the
13people in charge of this poor defenseless world of ours. 6people in charge of this poor defenseless world of ours.
14 7
15 8
16*** 9***
17 10
11## Em'n'Strong
12
13Test *em* _em_ **strong** __strong__ .
14
18# Spaces 15# Spaces
19 16
20Can it *handle* my _usual_ two **space** sentence breaks? Let's test it.$_$ Not by default. 17Can it *handle* my _usual_ two **space** sentence breaks? Let's test it. Not by default.
21 18
22The \\ before a space turns it into a "a literal unicode nonbreaking space character" which looks invisible in the source.&nbsp; \--ascii should output the HTML code far that.$_$ Except doesn't actually work. 19The \\ before a space turns it into a "a literal unicode nonbreaking space character" which looks invisible in the source.\ \--ascii should output the HTML code far that. Except doesn't actually work.
23 20
24Also a \\ at the end of a line turns into a line break, though they get wrapped in paragraph tags.$_$ lol 21Also a \\ at the end of a line turns into a line break, though they get wrapped in paragraph tags. lol \
25 22
26Take two.$_$ And now for something completely different.&nbsp; It's not consistant, need to manually put in the nbsp a few times above.&nbsp; Ah, it only works for the first one per line. 23Just to double check. That's a single space.
27 24
28\ 25\ \$ \' \" \| %
26
27I'm 100% sure that % will get treated correctly now.
29 28
30## Strike out 29## Strike out
31 30
32Test ~~strike~~ --out--.$_$ Needs the extension. 31Test ~~strike~~ --out--. Needs the extension.
33 32
34### URL 33### URL
35 34
36[untalenz](https://untalenz.rocks/) 35[untalenz](https://untalenz.rocks/)
37 36
37[nope.example.com](http://nope.example.com/)
38
38https://sledjhamr.org/ 39https://sledjhamr.org/
39 40
40# Lists 41# Lists
41 42
42 43
43* zero 44* first star
44* 1 45* second star
45* two
46 46
47- zero 47<!-- Separate the lists. -->
48- 1
49- two
50 48
49- first dash
50- second dash
51 51
52No way to say "here is the end of the list" without putting something **else** here?$_$ Ah a comment will work, or anything else. 52No way to say "here is the end of the list" without putting something **else** here? Ah a comment will work, or anything else.
53 53
541. one
552. two
56
57<!-- A comment will work -->
54 58
590. zero
551. one 601. one
562. 2 612. two
57 62
63Autonumbering? Needs the extension. Doesn't matter, they get renumbered anyway if out of order.
58 64
59<!-- A comment will work --> 650. zero
66#. first hash
67#. second hash
60 68
69<!-- Separate the lists. -->
61 70
620. 0 71#. first hash
631. one 72#. second hash
642. 2 73#. third hash
65 74
66Autonumbering? Nope. B-( 75<!-- Separate the lists. -->
67 76
680. zero 770. zero
69 1 782. two
70 two 791. one
80
81Bug. If there's a single word and period at the beginning of a line, it gets turned into a list, or list item.
82
83<!-- Separate the lists. -->
84
85Bug. If there's a single word and period at the beginning of a line, it gets turned into a list, or list item.
86
87~~~
88Bug. If there's a single word and period at the beginning of a line, it gets turned into a list, or list item.
89~~~
71 90
91The stuff in a code block is in a different font, it's mono. lol
72 92
73# images 93# images
74 94
@@ -87,19 +107,46 @@ Autonumbering? Nope. B-(
87 107
88 Plus some extra text. 108 Plus some extra text.
89 109
110
111Next code block.
112
113
114~~~lua
115 a simple
116 indented code block
117 <a/>
118 *hi*
119
120 - one
121
122 Plus some extra text.
123~~~
124
125
126Next code block.
127
90~~~ 128~~~
91< 129<
92 > 130 >
93~~~ 131~~~
94 132
133And a really long one, should turn scrollable.
95~~~lua 134~~~lua
96-- Show some Lua code here, may even be highlighted right. 135-- Show some Lua code here, may even be highlighted right.
97print("G'day world!") 136print("G'day world!")
98-- Let's see what happens with the HTML output by cmark, then gets rendered by the web browser, inside my CSS styled pre code thingy that cmark produces. For a very very very loooong line. Needs to be much longer. What else can I add to this already quite long line to get it to trigger being overly long? I need even mooooooore??? 137-- Let's see what happens with the HTML output by cmark, then gets rendered by the web browser, inside my CSS styled pre code thingy that cmark produces. For a very very very loooong line. Needs to be much longer. What else can I add to this already quite long line to get it to trigger being overly long? I need even mooooooore???
99print'The problem here is that I have to use CSS to style these things, coz cmark wont let me at the style stuff as far as I can see. But using CSS web browsers think the nmall box STILL extends all the way to the end of the content, but the scroll works anyway. So it's fucking up the size of the container.' 138print'The problem here is that I have to use CSS to style these things, coz cmark wont let me at the style stuff as far as I can see. But using CSS web browsers think the small box STILL extends all the way to the end of the content, but the scroll works anyway. So it's fucking up the size of the container.'
100~~~ 139~~~
101 140
102> # What is a blockquote? 141> # What is a blockquote?
103> Still don't know. lol 142> Still don't know. lol
104> 143>
105> Just another useless way to eat space I guess.$_$ shrugs 144> Just another useless way to eat space I guess. shrugs
145> Might be why emails sometimes get that symbol dropped in HTML conversions.
146
147
148|This should be a table. |With two columns and a link |
149|-------------------------|-------------------------------|
150|cell 0,0 |cell 0,1 |
151|cell 1,0 |[linky](https://sledjhamr.org) |
152
diff --git a/testing/index.md.md b/testing/index.md.md
new file mode 100644
index 0000000..c85bb3f
--- /dev/null
+++ b/testing/index.md.md
@@ -0,0 +1 @@
title=G'day world!