---input--- ! Copyright (C) 2008 Slava Pestov ! See http://factorcode.org/license.txt for BSD license. USING: accessors kernel hashtables calendar random assocs namespaces make splitting sequences sorting math.order present io.files io.directories io.encodings.ascii syndication farkup html.components html.forms http.server http.server.dispatchers furnace.actions furnace.utilities furnace.redirection furnace.auth furnace.auth.login furnace.boilerplate furnace.syndication validators db.types db.tuples lcs urls ; IN: webapps.wiki : wiki-url ( rest path -- url ) [ "$wiki/" % % "/" % present % ] "" make swap >>path ; : view-url ( title -- url ) "view" wiki-url ; : edit-url ( title -- url ) "edit" wiki-url ; : revisions-url ( title -- url ) "revisions" wiki-url ; : revision-url ( id -- url ) "revision" wiki-url ; : user-edits-url ( author -- url ) "user-edits" wiki-url ; TUPLE: wiki < dispatcher ; SYMBOL: can-delete-wiki-articles? can-delete-wiki-articles? define-capability TUPLE: article title revision ; article "ARTICLES" { { "title" "TITLE" { VARCHAR 256 } +not-null+ +user-assigned-id+ } { "revision" "REVISION" INTEGER +not-null+ } ! revision id } define-persistent :
( title -- article ) article new swap >>title ; TUPLE: revision id title author date content description ; revision "REVISIONS" { { "id" "ID" INTEGER +db-assigned-id+ } { "title" "TITLE" { VARCHAR 256 } +not-null+ } ! article id { "author" "AUTHOR" { VARCHAR 256 } +not-null+ } ! uid { "date" "DATE" TIMESTAMP +not-null+ } { "content" "CONTENT" TEXT +not-null+ } { "description" "DESCRIPTION" TEXT } } define-persistent M: revision feed-entry-title [ title>> ] [ drop " by " ] [ author>> ] tri 3append ; M: revision feed-entry-date date>> ; M: revision feed-entry-url id>> revision-url ; : reverse-chronological-order ( seq -- sorted ) [ date>> ] inv-sort-with ; : ( id -- revision ) revision new swap >>id ; : validate-title ( -- ) { { "title" [ v-one-line ] } } validate-params ; : validate-author ( -- ) { { "author" [ v-username ] } } validate-params ; : ( responder -- responder' ) { wiki "page-common" } >>template ; : ( -- action ) [ "Front Page" view-url ] >>display ; : latest-revision ( title -- revision/f )
select-tuple dup [ revision>> select-tuple ] when ; : ( -- action ) "title" >>rest [ validate-title ] >>init [ "title" value dup latest-revision [ from-object { wiki "view" } ] [ edit-url ] ?if ] >>display ; : ( -- action ) "id" >>rest [ validate-integer-id "id" value select-tuple from-object ] >>init { wiki "view" } >>template ; : ( -- action ) [ article new select-tuples random [ title>> ] [ "Front Page" ] if* view-url ] >>display ; : amend-article ( revision article -- ) swap id>> >>revision update-tuple ; : add-article ( revision -- ) [ title>> ] [ id>> ] bi article boa insert-tuple ; : add-revision ( revision -- ) [ insert-tuple ] [ dup title>>
select-tuple [ amend-article ] [ add-article ] if* ] bi ; : ( -- action ) "title" >>rest [ validate-title "title" value
select-tuple [ revision>> select-tuple ] [ f "title" value >>title ] if* [ title>> "title" set-value ] [ content>> "content" set-value ] bi ] >>init { wiki "edit" } >>template ; : ( -- action ) [ validate-title { { "content" [ v-required ] } { "description" [ [ v-one-line ] v-optional ] } } validate-params f "title" value >>title now >>date username >>author "content" value >>content "description" value >>description [ add-revision ] [ title>> view-url ] bi ] >>submit "edit wiki articles" >>description ; : ( responder -- responder ) { wiki "revisions-common" } >>template ; : list-revisions ( -- seq ) f "title" value >>title select-tuples reverse-chronological-order ; : ( -- action ) "title" >>rest [ validate-title list-revisions "revisions" set-value ] >>init { wiki "revisions" } >>template ; : ( -- action ) "title" >>rest [ validate-title ] >>init [ "Revisions of " "title" value append ] >>title [ "title" value revisions-url ] >>url [ list-revisions ] >>entries ; : rollback-description ( description -- description' ) [ "Rollback of '" "'" surround ] [ "Rollback" ] if* ; : ( -- action ) [ validate-integer-id ] >>validate [ "id" value select-tuple f >>id now >>date username >>author [ rollback-description ] change-description [ add-revision ] [ title>> revisions-url ] bi ] >>submit "rollback wiki articles" >>description ; : list-changes ( -- seq ) f select-tuples reverse-chronological-order ; : ( -- action ) [ list-changes "revisions" set-value ] >>init { wiki "changes" } >>template ; : ( -- action ) [ URL" $wiki/changes" ] >>url [ "All changes" ] >>title [ list-changes ] >>entries ; : ( -- action ) [ validate-title ] >>validate [ "title" value
delete-tuples f "title" value >>title delete-tuples URL" $wiki" ] >>submit "delete wiki articles" >>description { can-delete-wiki-articles? } >>capabilities ; : ( -- action ) [ { { "old-id" [ v-integer ] } { "new-id" [ v-integer ] } } validate-params "old-id" "new-id" [ value select-tuple ] bi@ [ over title>> "title" set-value [ "old" [ from-object ] nest-form ] [ "new" [ from-object ] nest-form ] bi* ] [ [ content>> string-lines ] bi@ diff "diff" set-value ] 2bi ] >>init { wiki "diff" } >>template ; : ( -- action ) [ f
select-tuples [ title>> ] sort-with "articles" set-value ] >>init { wiki "articles" } >>template ; : list-user-edits ( -- seq ) f "author" value >>author select-tuples reverse-chronological-order ; : ( -- action ) "author" >>rest [ validate-author list-user-edits "revisions" set-value ] >>init { wiki "user-edits" } >>template ; : ( -- action ) "author" >>rest [ validate-author ] >>init [ "Edits by " "author" value append ] >>title [ "author" value user-edits-url ] >>url [ list-user-edits ] >>entries ; : init-sidebars ( -- ) "Contents" latest-revision [ "contents" [ from-object ] nest-form ] when* "Footer" latest-revision [ "footer" [ from-object ] nest-form ] when* ; : init-relative-link-prefix ( -- ) URL" $wiki/view/" adjust-url present relative-link-prefix set ; : ( -- dispatcher ) wiki new-dispatcher "" add-responder "view" add-responder "revision" add-responder "random" add-responder "revisions" add-responder "revisions.atom" add-responder "diff" add-responder "edit" add-responder "submit" add-responder "rollback" add-responder "user-edits" add-responder "articles" add-responder "changes" add-responder "user-edits.atom" add-responder "changes.atom" add-responder "delete" add-responder [ init-sidebars init-relative-link-prefix ] >>init { wiki "wiki-common" } >>template ; : init-wiki ( -- ) "resource:extra/webapps/wiki/initial-content" [ [ dup ".txt" ?tail [ swap ascii file-contents f swap >>content swap >>title "slava" >>author now >>date add-revision ] [ 2drop ] if ] each ] with-directory-files ; ---tokens--- '! Copyright (C) 2008 Slava Pestov' Comment '\n' Text '! See http://factorcode.org/license.txt for BSD license.' Comment '\n' Text 'USING:' Keyword.Namespace ' ' Text 'accessors' Name.Namespace ' ' Text 'kernel' Name.Namespace ' ' Text 'hashtables' Name.Namespace ' ' Text 'calendar' Name.Namespace ' ' Text 'random' Name.Namespace ' ' Text 'assocs' Name.Namespace '\n' Text 'namespaces' Name.Namespace ' ' Text 'make' Name.Namespace ' ' Text 'splitting' Name.Namespace ' ' Text 'sequences' Name.Namespace ' ' Text 'sorting' Name.Namespace ' ' Text 'math.order' Name.Namespace ' ' Text 'present' Name.Namespace '\n' Text 'io.files' Name.Namespace ' ' Text 'io.directories' Name.Namespace ' ' Text 'io.encodings.ascii' Name.Namespace '\n' Text 'syndication' Name.Namespace ' ' Text 'farkup' Name.Namespace '\n' Text 'html.components' Name.Namespace ' ' Text 'html.forms' Name.Namespace '\n' Text 'http.server' Name.Namespace '\n' Text 'http.server.dispatchers' Name.Namespace '\n' Text 'furnace.actions' Name.Namespace '\n' Text 'furnace.utilities' Name.Namespace '\n' Text 'furnace.redirection' Name.Namespace '\n' Text 'furnace.auth' Name.Namespace '\n' Text 'furnace.auth.login' Name.Namespace '\n' Text 'furnace.boilerplate' Name.Namespace '\n' Text 'furnace.syndication' Name.Namespace '\n' Text 'validators' Name.Namespace '\n' Text 'db.types' Name.Namespace ' ' Text 'db.tuples' Name.Namespace ' ' Text 'lcs' Name.Namespace ' ' Text 'urls' Name.Namespace ' ' Text ';\n' Keyword 'IN:' Keyword.Namespace ' ' Text 'webapps.wiki' Name.Namespace '\n\n' Text ':' Keyword ' ' Text 'wiki-url' Name.Function ' ' Text '( ' Name.Function 'rest' Name.Variable ' ' Text 'path' Name.Variable ' ' Text '-- ' Name.Function 'url' Name.Variable ' ' Text ')\n' Name.Function ' ' Text '[' Text ' ' Text '"$wiki/"' Literal.String ' ' Text '%' Text ' ' Text '%' Text ' ' Text '"/"' Literal.String ' ' Text '%' Text ' ' Text 'present' Text ' ' Text '%' Text ' ' Text ']' Text ' ' Text '""' Literal.String ' ' Text 'make' Text '\n ' Text '' Text ' ' Text 'swap ' Name.Builtin '>>path' Text ' ' Text ';\n' Keyword '\n' Text ':' Keyword ' ' Text 'view-url' Name.Function ' ' Text '( ' Name.Function 'title' Name.Variable ' ' Text '-- ' Name.Function 'url' Name.Variable ' ' Text ') ' Name.Function '"view"' Literal.String ' ' Text 'wiki-url' Text ' ' Text ';\n' Keyword '\n' Text ':' Keyword ' ' Text 'edit-url' Name.Function ' ' Text '( ' Name.Function 'title' Name.Variable ' ' Text '-- ' Name.Function 'url' Name.Variable ' ' Text ') ' Name.Function '"edit"' Literal.String ' ' Text 'wiki-url' Text ' ' Text ';\n' Keyword '\n' Text ':' Keyword ' ' Text 'revisions-url' Name.Function ' ' Text '( ' Name.Function 'title' Name.Variable ' ' Text '-- ' Name.Function 'url' Name.Variable ' ' Text ') ' Name.Function '"revisions"' Literal.String ' ' Text 'wiki-url' Text ' ' Text ';\n' Keyword '\n' Text ':' Keyword ' ' Text 'revision-url' Name.Function ' ' Text '( ' Name.Function 'id' Name.Variable ' ' Text '-- ' Name.Function 'url' Name.Variable ' ' Text ') ' Name.Function '"revision"' Literal.String ' ' Text 'wiki-url' Text ' ' Text ';\n' Keyword '\n' Text ':' Keyword ' ' Text 'user-edits-url' Name.Function ' ' Text '( ' Name.Function 'author' Name.Variable ' ' Text '-- ' Name.Function 'url' Name.Variable ' ' Text ') ' Name.Function '"user-edits"' Literal.String ' ' Text 'wiki-url' Text ' ' Text ';\n' Keyword '\n' Text 'TUPLE:' Keyword ' ' Text 'wiki' Name.Class ' < ' Text 'dispatcher' Name.Class ' ' Text ';\n' Keyword '\n' Text 'SYMBOL:' Keyword ' ' Text 'can-delete-wiki-articles?' Name.Function '\n\n' Text 'can-delete-wiki-articles?' Text ' ' Text 'define-capability' Text '\n\n' Text 'TUPLE:' Keyword ' ' Text 'article' Name.Class ' ' Text 'title' Name.Variable ' ' Text 'revision' Name.Variable ' ' Text ';\n' Keyword '\n' Text 'article' Text ' ' Text '"ARTICLES"' Literal.String ' ' Text '{' Text '\n ' Text '{' Text ' ' Text '"title"' Literal.String ' ' Text '"TITLE"' Literal.String ' ' Text '{' Text ' ' Text 'VARCHAR' Text ' ' Text '256 ' Literal.Number '}' Text ' ' Text '+not-null+' Text ' ' Text '+user-assigned-id+' Text ' ' Text '}' Text '\n ' Text '{' Text ' ' Text '"revision"' Literal.String ' ' Text '"REVISION"' Literal.String ' ' Text 'INTEGER' Text ' ' Text '+not-null+' Text ' ' Text '}' Text ' ' Text '! revision id' Comment '\n' Text '}' Text ' ' Text 'define-persistent' Text '\n\n' Text ':' Keyword ' ' Text '
' Name.Function ' ' Text '( ' Name.Function 'title' Name.Variable ' ' Text '-- ' Name.Function 'article' Name.Variable ' ' Text ') ' Name.Function 'article' Text ' ' Text 'new ' Name.Builtin 'swap ' Name.Builtin '>>title' Text ' ' Text ';\n' Keyword '\n' Text 'TUPLE:' Keyword ' ' Text 'revision' Name.Class ' ' Text 'id' Name.Variable ' ' Text 'title' Name.Variable ' ' Text 'author' Name.Variable ' ' Text 'date' Name.Variable ' ' Text 'content' Name.Variable ' ' Text 'description' Name.Variable ' ' Text ';\n' Keyword '\n' Text 'revision' Text ' ' Text '"REVISIONS"' Literal.String ' ' Text '{' Text '\n ' Text '{' Text ' ' Text '"id"' Literal.String ' ' Text '"ID"' Literal.String ' ' Text 'INTEGER' Text ' ' Text '+db-assigned-id+' Text ' ' Text '}' Text '\n ' Text '{' Text ' ' Text '"title"' Literal.String ' ' Text '"TITLE"' Literal.String ' ' Text '{' Text ' ' Text 'VARCHAR' Text ' ' Text '256 ' Literal.Number '}' Text ' ' Text '+not-null+' Text ' ' Text '}' Text ' ' Text '! article id' Comment '\n ' Text '{' Text ' ' Text '"author"' Literal.String ' ' Text '"AUTHOR"' Literal.String ' ' Text '{' Text ' ' Text 'VARCHAR' Text ' ' Text '256 ' Literal.Number '}' Text ' ' Text '+not-null+' Text ' ' Text '}' Text ' ' Text '! uid' Comment '\n ' Text '{' Text ' ' Text '"date"' Literal.String ' ' Text '"DATE"' Literal.String ' ' Text 'TIMESTAMP' Text ' ' Text '+not-null+' Text ' ' Text '}' Text '\n ' Text '{' Text ' ' Text '"content"' Literal.String ' ' Text '"CONTENT"' Literal.String ' ' Text 'TEXT' Text ' ' Text '+not-null+' Text ' ' Text '}' Text '\n ' Text '{' Text ' ' Text '"description"' Literal.String ' ' Text '"DESCRIPTION"' Literal.String ' ' Text 'TEXT' Text ' ' Text '}' Text '\n' Text '}' Text ' ' Text 'define-persistent' Text '\n\n' Text 'M:' Keyword ' ' Text 'revision' Name.Class ' ' Text 'feed-entry-title' Name.Function '\n ' Text '[' Text ' ' Text 'title>>' Text ' ' Text ']' Text ' ' Text '[' Text ' ' Text 'drop ' Name.Builtin '" by "' Literal.String ' ' Text ']' Text ' ' Text '[' Text ' ' Text 'author>>' Text ' ' Text ']' Text ' ' Text 'tri ' Name.Builtin '3append ' Name.Builtin ';\n' Keyword '\n' Text 'M:' Keyword ' ' Text 'revision' Name.Class ' ' Text 'feed-entry-date' Name.Function ' ' Text 'date>>' Text ' ' Text ';\n' Keyword '\n' Text 'M:' Keyword ' ' Text 'revision' Name.Class ' ' Text 'feed-entry-url' Name.Function ' ' Text 'id>>' Text ' ' Text 'revision-url' Text ' ' Text ';\n' Keyword '\n' Text ':' Keyword ' ' Text 'reverse-chronological-order' Name.Function ' ' Text '( ' Name.Function 'seq' Name.Variable ' ' Text '-- ' Name.Function 'sorted' Name.Variable ' ' Text ')\n' Name.Function ' ' Text '[' Text ' ' Text 'date>>' Text ' ' Text ']' Text ' ' Text 'inv-sort-with' Text ' ' Text ';\n' Keyword '\n' Text ':' Keyword ' ' Text '' Name.Function ' ' Text '( ' Name.Function 'id' Name.Variable ' ' Text '-- ' Name.Function 'revision' Name.Variable ' ' Text ')\n' Name.Function ' ' Text 'revision' Text ' ' Text 'new ' Name.Builtin 'swap ' Name.Builtin '>>id' Text ' ' Text ';\n' Keyword '\n' Text ':' Keyword ' ' Text 'validate-title' Name.Function ' ' Text '( ' Name.Function '-- ' Name.Function ')\n' Name.Function ' ' Text '{' Text ' ' Text '{' Text ' ' Text '"title"' Literal.String ' ' Text '[' Text ' ' Text 'v-one-line' Text ' ' Text ']' Text ' ' Text '}' Text ' ' Text '}' Text ' ' Text 'validate-params' Text ' ' Text ';\n' Keyword '\n' Text ':' Keyword ' ' Text 'validate-author' Name.Function ' ' Text '( ' Name.Function '-- ' Name.Function ')\n' Name.Function ' ' Text '{' Text ' ' Text '{' Text ' ' Text '"author"' Literal.String ' ' Text '[' Text ' ' Text 'v-username' Text ' ' Text ']' Text ' ' Text '}' Text ' ' Text '}' Text ' ' Text 'validate-params' Text ' ' Text ';\n' Keyword '\n' Text ':' Keyword ' ' Text '' Name.Function ' ' Text '( ' Name.Function 'responder' Name.Variable ' ' Text '-- ' Name.Function "responder'" Name.Variable ' ' Text ')\n' Name.Function ' ' Text '' Text '\n ' Text '{' Text ' ' Text 'wiki' Text ' ' Text '"page-common"' Literal.String ' ' Text '}' Text ' ' Text '>>template' Text ' ' Text ';\n' Keyword '\n' Text ':' Keyword ' ' Text '' Name.Function ' ' Text '( ' Name.Function '-- ' Name.Function 'action' Name.Variable ' ' Text ')\n' Name.Function ' ' Text '' Text '\n ' Text '[' Text ' ' Text '"Front Page"' Literal.String ' ' Text 'view-url' Text ' ' Text '' Text ' ' Text ']' Text ' ' Text '>>display' Text ' ' Text ';\n' Keyword '\n' Text ':' Keyword ' ' Text 'latest-revision' Name.Function ' ' Text '( ' Name.Function 'title' Name.Variable ' ' Text '-- ' Name.Function 'revision/f' Name.Variable ' ' Text ')\n' Name.Function ' ' Text '
' Text ' ' Text 'select-tuple' Text '\n ' Text 'dup ' Name.Builtin '[' Text ' ' Text 'revision>>' Text ' ' Text '' Text ' ' Text 'select-tuple' Text ' ' Text ']' Text ' ' Text 'when ' Name.Builtin ';\n' Keyword '\n' Text ':' Keyword ' ' Text '' Name.Function ' ' Text '( ' Name.Function '-- ' Name.Function 'action' Name.Variable ' ' Text ')\n' Name.Function ' ' Text '' Text '\n\n ' Text '"title"' Literal.String ' ' Text '>>rest' Text '\n\n ' Text '[' Text ' ' Text 'validate-title' Text ' ' Text ']' Text ' ' Text '>>init' Text '\n\n ' Text '[' Text '\n ' Text '"title"' Literal.String ' ' Text 'value' Text ' ' Text 'dup ' Name.Builtin 'latest-revision' Text ' ' Text '[' Text '\n ' Text 'from-object' Text '\n ' Text '{' Text ' ' Text 'wiki' Text ' ' Text '"view"' Literal.String ' ' Text '}' Text ' ' Text '' Text '\n ' Text ']' Text ' ' Text '[' Text '\n ' Text 'edit-url' Text ' ' Text '' Text '\n ' Text ']' Text ' ' Text '?if\n' Name.Builtin ' ' Text ']' Text ' ' Text '>>display' Text '\n\n ' Text '' Text ' ' Text ';\n' Keyword '\n' Text ':' Keyword ' ' Text '' Name.Function ' ' Text '( ' Name.Function '-- ' Name.Function 'action' Name.Variable ' ' Text ')\n' Name.Function ' ' Text '' Text '\n\n ' Text '"id"' Literal.String ' ' Text '>>rest' Text '\n\n ' Text '[' Text '\n ' Text 'validate-integer-id' Text '\n ' Text '"id"' Literal.String ' ' Text 'value' Text ' ' Text '' Text '\n ' Text 'select-tuple' Text ' ' Text 'from-object' Text '\n ' Text ']' Text ' ' Text '>>init' Text '\n\n ' Text '{' Text ' ' Text 'wiki' Text ' ' Text '"view"' Literal.String ' ' Text '}' Text ' ' Text '>>template' Text '\n \n ' Text '' Text ' ' Text ';\n' Keyword '\n' Text ':' Keyword ' ' Text '' Name.Function ' ' Text '( ' Name.Function '-- ' Name.Function 'action' Name.Variable ' ' Text ')\n' Name.Function ' ' Text '' Text '\n ' Text '[' Text '\n ' Text 'article' Text ' ' Text 'new ' Name.Builtin 'select-tuples' Text ' ' Text 'random' Text '\n ' Text '[' Text ' ' Text 'title>>' Text ' ' Text ']' Text ' ' Text '[' Text ' ' Text '"Front Page"' Literal.String ' ' Text ']' Text ' ' Text 'if*\n' Name.Builtin ' ' Text 'view-url' Text ' ' Text '' Text '\n ' Text ']' Text ' ' Text '>>display' Text ' ' Text ';\n' Keyword '\n' Text ':' Keyword ' ' Text 'amend-article' Name.Function ' ' Text '( ' Name.Function 'revision' Name.Variable ' ' Text 'article' Name.Variable ' ' Text '-- ' Name.Function ')\n' Name.Function ' ' Text 'swap ' Name.Builtin 'id>>' Text ' ' Text '>>revision' Text ' ' Text 'update-tuple' Text ' ' Text ';\n' Keyword '\n' Text ':' Keyword ' ' Text 'add-article' Name.Function ' ' Text '( ' Name.Function 'revision' Name.Variable ' ' Text '-- ' Name.Function ')\n' Name.Function ' ' Text '[' Text ' ' Text 'title>>' Text ' ' Text ']' Text ' ' Text '[' Text ' ' Text 'id>>' Text ' ' Text ']' Text ' ' Text 'bi ' Name.Builtin 'article' Text ' ' Text 'boa ' Name.Builtin 'insert-tuple' Text ' ' Text ';\n' Keyword '\n' Text ':' Keyword ' ' Text 'add-revision' Name.Function ' ' Text '( ' Name.Function 'revision' Name.Variable ' ' Text '-- ' Name.Function ')\n' Name.Function ' ' Text '[' Text ' ' Text 'insert-tuple' Text ' ' Text ']' Text '\n ' Text '[' Text '\n ' Text 'dup ' Name.Builtin 'title>>' Text ' ' Text '
' Text ' ' Text 'select-tuple' Text '\n ' Text '[' Text ' ' Text 'amend-article' Text ' ' Text ']' Text ' ' Text '[' Text ' ' Text 'add-article' Text ' ' Text ']' Text ' ' Text 'if*\n' Name.Builtin ' ' Text ']' Text '\n ' Text 'bi ' Name.Builtin ';\n' Keyword '\n' Text ':' Keyword ' ' Text '' Name.Function ' ' Text '( ' Name.Function '-- ' Name.Function 'action' Name.Variable ' ' Text ')\n' Name.Function ' ' Text '' Text '\n\n ' Text '"title"' Literal.String ' ' Text '>>rest' Text '\n\n ' Text '[' Text '\n ' Text 'validate-title' Text '\n\n ' Text '"title"' Literal.String ' ' Text 'value' Text ' ' Text '
' Text ' ' Text 'select-tuple' Text '\n ' Text '[' Text ' ' Text 'revision>>' Text ' ' Text '' Text ' ' Text 'select-tuple' Text ' ' Text ']' Text '\n ' Text '[' Text ' ' Text 'f ' Name.Constant '' Text ' ' Text '"title"' Literal.String ' ' Text 'value' Text ' ' Text '>>title' Text ' ' Text ']' Text '\n ' Text 'if*\n' Name.Builtin '\n ' Text '[' Text ' ' Text 'title>>' Text ' ' Text '"title"' Literal.String ' ' Text 'set-value' Text ' ' Text ']' Text '\n ' Text '[' Text ' ' Text 'content>>' Text ' ' Text '"content"' Literal.String ' ' Text 'set-value' Text ' ' Text ']' Text '\n ' Text 'bi\n' Name.Builtin ' ' Text ']' Text ' ' Text '>>init' Text '\n\n ' Text '{' Text ' ' Text 'wiki' Text ' ' Text '"edit"' Literal.String ' ' Text '}' Text ' ' Text '>>template' Text '\n\n ' Text '' Text ' ' Text ';\n' Keyword '\n' Text ':' Keyword ' ' Text '' Name.Function ' ' Text '( ' Name.Function '-- ' Name.Function 'action' Name.Variable ' ' Text ')\n' Name.Function ' ' Text '' Text '\n ' Text '[' Text '\n ' Text 'validate-title' Text '\n\n ' Text '{' Text '\n ' Text '{' Text ' ' Text '"content"' Literal.String ' ' Text '[' Text ' ' Text 'v-required' Text ' ' Text ']' Text ' ' Text '}' Text '\n ' Text '{' Text ' ' Text '"description"' Literal.String ' ' Text '[' Text ' ' Text '[' Text ' ' Text 'v-one-line' Text ' ' Text ']' Text ' ' Text 'v-optional' Text ' ' Text ']' Text ' ' Text '}' Text '\n ' Text '}' Text ' ' Text 'validate-params' Text '\n\n ' Text 'f ' Name.Constant '' Text '\n ' Text '"title"' Literal.String ' ' Text 'value' Text ' ' Text '>>title' Text '\n ' Text 'now' Text ' ' Text '>>date' Text '\n ' Text 'username' Text ' ' Text '>>author' Text '\n ' Text '"content"' Literal.String ' ' Text 'value' Text ' ' Text '>>content' Text '\n ' Text '"description"' Literal.String ' ' Text 'value' Text ' ' Text '>>description' Text '\n ' Text '[' Text ' ' Text 'add-revision' Text ' ' Text ']' Text ' ' Text '[' Text ' ' Text 'title>>' Text ' ' Text 'view-url' Text ' ' Text '' Text ' ' Text ']' Text ' ' Text 'bi\n' Name.Builtin ' ' Text ']' Text ' ' Text '>>submit' Text '\n\n ' Text '' Text '\n ' Text '"edit wiki articles"' Literal.String ' ' Text '>>description' Text ' ' Text ';\n' Keyword '\n' Text ':' Keyword ' ' Text '' Name.Function ' ' Text '( ' Name.Function 'responder' Name.Variable ' ' Text '-- ' Name.Function 'responder' Name.Variable ' ' Text ')\n' Name.Function ' ' Text '' Text '\n ' Text '{' Text ' ' Text 'wiki' Text ' ' Text '"revisions-common"' Literal.String ' ' Text '}' Text ' ' Text '>>template' Text ' ' Text ';\n' Keyword '\n' Text ':' Keyword ' ' Text 'list-revisions' Name.Function ' ' Text '( ' Name.Function '-- ' Name.Function 'seq' Name.Variable ' ' Text ')\n' Name.Function ' ' Text 'f ' Name.Constant '' Text ' ' Text '"title"' Literal.String ' ' Text 'value' Text ' ' Text '>>title' Text ' ' Text 'select-tuples' Text '\n ' Text 'reverse-chronological-order' Text ' ' Text ';\n' Keyword '\n' Text ':' Keyword ' ' Text '' Name.Function ' ' Text '( ' Name.Function '-- ' Name.Function 'action' Name.Variable ' ' Text ')\n' Name.Function ' ' Text '' Text '\n\n ' Text '"title"' Literal.String ' ' Text '>>rest' Text '\n\n ' Text '[' Text '\n ' Text 'validate-title' Text '\n ' Text 'list-revisions' Text ' ' Text '"revisions"' Literal.String ' ' Text 'set-value' Text '\n ' Text ']' Text ' ' Text '>>init' Text '\n\n ' Text '{' Text ' ' Text 'wiki' Text ' ' Text '"revisions"' Literal.String ' ' Text '}' Text ' ' Text '>>template' Text '\n\n ' Text '' Text '\n ' Text '' Text ' ' Text ';\n' Keyword '\n' Text ':' Keyword ' ' Text '' Name.Function ' ' Text '( ' Name.Function '-- ' Name.Function 'action' Name.Variable ' ' Text ')\n' Name.Function ' ' Text '' Text '\n\n ' Text '"title"' Literal.String ' ' Text '>>rest' Text '\n\n ' Text '[' Text ' ' Text 'validate-title' Text ' ' Text ']' Text ' ' Text '>>init' Text '\n\n ' Text '[' Text ' ' Text '"Revisions of "' Literal.String ' ' Text '"title"' Literal.String ' ' Text 'value' Text ' ' Text 'append ' Name.Builtin ']' Text ' ' Text '>>title' Text '\n\n ' Text '[' Text ' ' Text '"title"' Literal.String ' ' Text 'value' Text ' ' Text 'revisions-url' Text ' ' Text ']' Text ' ' Text '>>url' Text '\n\n ' Text '[' Text ' ' Text 'list-revisions' Text ' ' Text ']' Text ' ' Text '>>entries' Text ' ' Text ';\n' Keyword '\n' Text ':' Keyword ' ' Text 'rollback-description' Name.Function ' ' Text '( ' Name.Function 'description' Name.Variable ' ' Text '-- ' Name.Function "description'" Name.Variable ' ' Text ')\n' Name.Function ' ' Text '[' Text ' ' Text '"Rollback of \'"' Literal.String ' ' Text '"\'"' Literal.String ' ' Text 'surround ' Name.Builtin ']' Text ' ' Text '[' Text ' ' Text '"Rollback"' Literal.String ' ' Text ']' Text ' ' Text 'if* ' Name.Builtin ';\n' Keyword '\n' Text ':' Keyword ' ' Text '' Name.Function ' ' Text '( ' Name.Function '-- ' Name.Function 'action' Name.Variable ' ' Text ')\n' Name.Function ' ' Text '' Text '\n\n ' Text '[' Text ' ' Text 'validate-integer-id' Text ' ' Text ']' Text ' ' Text '>>validate' Text '\n\n ' Text '[' Text '\n ' Text '"id"' Literal.String ' ' Text 'value' Text ' ' Text '' Text ' ' Text 'select-tuple' Text '\n ' Text 'f ' Name.Constant '>>id' Text '\n ' Text 'now' Text ' ' Text '>>date' Text '\n ' Text 'username' Text ' ' Text '>>author' Text '\n ' Text '[' Text ' ' Text 'rollback-description' Text ' ' Text ']' Text ' ' Text 'change-description' Text '\n ' Text '[' Text ' ' Text 'add-revision' Text ' ' Text ']' Text '\n ' Text '[' Text ' ' Text 'title>>' Text ' ' Text 'revisions-url' Text ' ' Text '' Text ' ' Text ']' Text ' ' Text 'bi\n' Name.Builtin ' ' Text ']' Text ' ' Text '>>submit' Text '\n \n ' Text '' Text '\n ' Text '"rollback wiki articles"' Literal.String ' ' Text '>>description' Text ' ' Text ';\n' Keyword '\n' Text ':' Keyword ' ' Text 'list-changes' Name.Function ' ' Text '( ' Name.Function '-- ' Name.Function 'seq' Name.Variable ' ' Text ')\n' Name.Function ' ' Text 'f ' Name.Constant '' Text ' ' Text 'select-tuples' Text '\n ' Text 'reverse-chronological-order' Text ' ' Text ';\n' Keyword '\n' Text ':' Keyword ' ' Text '' Name.Function ' ' Text '( ' Name.Function '-- ' Name.Function 'action' Name.Variable ' ' Text ')\n' Name.Function ' ' Text '' Text '\n ' Text '[' Text ' ' Text 'list-changes' Text ' ' Text '"revisions"' Literal.String ' ' Text 'set-value' Text ' ' Text ']' Text ' ' Text '>>init' Text '\n ' Text '{' Text ' ' Text 'wiki' Text ' ' Text '"changes"' Literal.String ' ' Text '}' Text ' ' Text '>>template' Text '\n\n ' Text '' Text ' ' Text ';\n' Keyword '\n' Text ':' Keyword ' ' Text '' Name.Function ' ' Text '( ' Name.Function '-- ' Name.Function 'action' Name.Variable ' ' Text ')\n' Name.Function ' ' Text '' Text '\n ' Text '[' Text ' ' Text 'URL" $wiki/changes"' Literal.String ' ' Text ']' Text ' ' Text '>>url' Text '\n ' Text '[' Text ' ' Text '"All changes"' Literal.String ' ' Text ']' Text ' ' Text '>>title' Text '\n ' Text '[' Text ' ' Text 'list-changes' Text ' ' Text ']' Text ' ' Text '>>entries' Text ' ' Text ';\n' Keyword '\n' Text ':' Keyword ' ' Text '' Name.Function ' ' Text '( ' Name.Function '-- ' Name.Function 'action' Name.Variable ' ' Text ')\n' Name.Function ' ' Text '' Text '\n\n ' Text '[' Text ' ' Text 'validate-title' Text ' ' Text ']' Text ' ' Text '>>validate' Text '\n\n ' Text '[' Text '\n ' Text '"title"' Literal.String ' ' Text 'value' Text ' ' Text '
' Text ' ' Text 'delete-tuples' Text '\n ' Text 'f ' Name.Constant '' Text ' ' Text '"title"' Literal.String ' ' Text 'value' Text ' ' Text '>>title' Text ' ' Text 'delete-tuples' Text '\n ' Text 'URL" $wiki"' Literal.String ' ' Text '' Text '\n ' Text ']' Text ' ' Text '>>submit' Text '\n\n ' Text '' Text '\n ' Text '"delete wiki articles"' Literal.String ' ' Text '>>description' Text '\n ' Text '{' Text ' ' Text 'can-delete-wiki-articles?' Text ' ' Text '}' Text ' ' Text '>>capabilities' Text ' ' Text ';\n' Keyword '\n' Text ':' Keyword ' ' Text '' Name.Function ' ' Text '( ' Name.Function '-- ' Name.Function 'action' Name.Variable ' ' Text ')\n' Name.Function ' ' Text '' Text '\n\n ' Text '[' Text '\n ' Text '{' Text '\n ' Text '{' Text ' ' Text '"old-id"' Literal.String ' ' Text '[' Text ' ' Text 'v-integer' Text ' ' Text ']' Text ' ' Text '}' Text '\n ' Text '{' Text ' ' Text '"new-id"' Literal.String ' ' Text '[' Text ' ' Text 'v-integer' Text ' ' Text ']' Text ' ' Text '}' Text '\n ' Text '}' Text ' ' Text 'validate-params' Text '\n\n ' Text '"old-id"' Literal.String ' ' Text '"new-id"' Literal.String '\n ' Text '[' Text ' ' Text 'value' Text ' ' Text '' Text ' ' Text 'select-tuple' Text ' ' Text ']' Text ' ' Text 'bi@\n' Name.Builtin ' ' Text '[' Text '\n ' Text 'over ' Name.Builtin 'title>>' Text ' ' Text '"title"' Literal.String ' ' Text 'set-value' Text '\n ' Text '[' Text ' ' Text '"old"' Literal.String ' ' Text '[' Text ' ' Text 'from-object' Text ' ' Text ']' Text ' ' Text 'nest-form' Text ' ' Text ']' Text '\n ' Text '[' Text ' ' Text '"new"' Literal.String ' ' Text '[' Text ' ' Text 'from-object' Text ' ' Text ']' Text ' ' Text 'nest-form' Text ' ' Text ']' Text '\n ' Text 'bi*\n' Name.Builtin ' ' Text ']' Text '\n ' Text '[' Text ' ' Text '[' Text ' ' Text 'content>>' Text ' ' Text 'string-lines' Text ' ' Text ']' Text ' ' Text 'bi@ ' Name.Builtin 'diff' Text ' ' Text '"diff"' Literal.String ' ' Text 'set-value' Text ' ' Text ']' Text '\n ' Text '2bi\n' Name.Builtin ' ' Text ']' Text ' ' Text '>>init' Text '\n\n ' Text '{' Text ' ' Text 'wiki' Text ' ' Text '"diff"' Literal.String ' ' Text '}' Text ' ' Text '>>template' Text '\n\n ' Text '' Text ' ' Text ';\n' Keyword '\n' Text ':' Keyword ' ' Text '' Name.Function ' ' Text '( ' Name.Function '-- ' Name.Function 'action' Name.Variable ' ' Text ')\n' Name.Function ' ' Text '' Text '\n\n ' Text '[' Text '\n ' Text 'f ' Name.Constant '
' Text ' ' Text 'select-tuples' Text '\n ' Text '[' Text ' ' Text 'title>>' Text ' ' Text ']' Text ' ' Text 'sort-with' Text '\n ' Text '"articles"' Literal.String ' ' Text 'set-value' Text '\n ' Text ']' Text ' ' Text '>>init' Text '\n\n ' Text '{' Text ' ' Text 'wiki' Text ' ' Text '"articles"' Literal.String ' ' Text '}' Text ' ' Text '>>template' Text ' ' Text ';\n' Keyword '\n' Text ':' Keyword ' ' Text 'list-user-edits' Name.Function ' ' Text '( ' Name.Function '-- ' Name.Function 'seq' Name.Variable ' ' Text ')\n' Name.Function ' ' Text 'f ' Name.Constant '' Text ' ' Text '"author"' Literal.String ' ' Text 'value' Text ' ' Text '>>author' Text ' ' Text 'select-tuples' Text '\n ' Text 'reverse-chronological-order' Text ' ' Text ';\n' Keyword '\n' Text ':' Keyword ' ' Text '' Name.Function ' ' Text '( ' Name.Function '-- ' Name.Function 'action' Name.Variable ' ' Text ')\n' Name.Function ' ' Text '' Text '\n\n ' Text '"author"' Literal.String ' ' Text '>>rest' Text '\n\n ' Text '[' Text '\n ' Text 'validate-author' Text '\n ' Text 'list-user-edits' Text ' ' Text '"revisions"' Literal.String ' ' Text 'set-value' Text '\n ' Text ']' Text ' ' Text '>>init' Text '\n\n ' Text '{' Text ' ' Text 'wiki' Text ' ' Text '"user-edits"' Literal.String ' ' Text '}' Text ' ' Text '>>template' Text '\n\n ' Text '' Text ' ' Text ';\n' Keyword '\n' Text ':' Keyword ' ' Text '' Name.Function ' ' Text '( ' Name.Function '-- ' Name.Function 'action' Name.Variable ' ' Text ')\n' Name.Function ' ' Text '' Text '\n ' Text '"author"' Literal.String ' ' Text '>>rest' Text '\n ' Text '[' Text ' ' Text 'validate-author' Text ' ' Text ']' Text ' ' Text '>>init' Text '\n ' Text '[' Text ' ' Text '"Edits by "' Literal.String ' ' Text '"author"' Literal.String ' ' Text 'value' Text ' ' Text 'append ' Name.Builtin ']' Text ' ' Text '>>title' Text '\n ' Text '[' Text ' ' Text '"author"' Literal.String ' ' Text 'value' Text ' ' Text 'user-edits-url' Text ' ' Text ']' Text ' ' Text '>>url' Text '\n ' Text '[' Text ' ' Text 'list-user-edits' Text ' ' Text ']' Text ' ' Text '>>entries' Text ' ' Text ';\n' Keyword '\n' Text ':' Keyword ' ' Text 'init-sidebars' Name.Function ' ' Text '( ' Name.Function '-- ' Name.Function ')\n' Name.Function ' ' Text '"Contents"' Literal.String ' ' Text 'latest-revision' Text ' ' Text '[' Text ' ' Text '"contents"' Literal.String ' ' Text '[' Text ' ' Text 'from-object' Text ' ' Text ']' Text ' ' Text 'nest-form' Text ' ' Text ']' Text ' ' Text 'when*\n' Name.Builtin ' ' Text '"Footer"' Literal.String ' ' Text 'latest-revision' Text ' ' Text '[' Text ' ' Text '"footer"' Literal.String ' ' Text '[' Text ' ' Text 'from-object' Text ' ' Text ']' Text ' ' Text 'nest-form' Text ' ' Text ']' Text ' ' Text 'when* ' Name.Builtin ';\n' Keyword '\n' Text ':' Keyword ' ' Text 'init-relative-link-prefix' Name.Function ' ' Text '( ' Name.Function '-- ' Name.Function ')\n' Name.Function ' ' Text 'URL" $wiki/view/"' Literal.String ' ' Text 'adjust-url' Text ' ' Text 'present' Text ' ' Text 'relative-link-prefix' Text ' ' Text 'set ' Name.Builtin ';\n' Keyword '\n' Text ':' Keyword ' ' Text '' Name.Function ' ' Text '( ' Name.Function '-- ' Name.Function 'dispatcher' Name.Variable ' ' Text ')\n' Name.Function ' ' Text 'wiki' Text ' ' Text 'new-dispatcher' Text '\n ' Text '' Text ' ' Text '""' Literal.String ' ' Text 'add-responder' Text '\n ' Text '' Text ' ' Text '"view"' Literal.String ' ' Text 'add-responder' Text '\n ' Text '' Text ' ' Text '"revision"' Literal.String ' ' Text 'add-responder' Text '\n ' Text '' Text ' ' Text '"random"' Literal.String ' ' Text 'add-responder' Text '\n ' Text '' Text ' ' Text '"revisions"' Literal.String ' ' Text 'add-responder' Text '\n ' Text '' Text ' ' Text '"revisions.atom"' Literal.String ' ' Text 'add-responder' Text '\n ' Text '' Text ' ' Text '"diff"' Literal.String ' ' Text 'add-responder' Text '\n ' Text '' Text ' ' Text '"edit"' Literal.String ' ' Text 'add-responder' Text '\n ' Text '' Text ' ' Text '"submit"' Literal.String ' ' Text 'add-responder' Text '\n ' Text '' Text ' ' Text '"rollback"' Literal.String ' ' Text 'add-responder' Text '\n ' Text '' Text ' ' Text '"user-edits"' Literal.String ' ' Text 'add-responder' Text '\n ' Text '' Text ' ' Text '"articles"' Literal.String ' ' Text 'add-responder' Text '\n ' Text '' Text ' ' Text '"changes"' Literal.String ' ' Text 'add-responder' Text '\n ' Text '' Text ' ' Text '"user-edits.atom"' Literal.String ' ' Text 'add-responder' Text '\n ' Text '' Text ' ' Text '"changes.atom"' Literal.String ' ' Text 'add-responder' Text '\n ' Text '' Text ' ' Text '"delete"' Literal.String ' ' Text 'add-responder' Text '\n ' Text '' Text '\n ' Text '[' Text ' ' Text 'init-sidebars' Text ' ' Text 'init-relative-link-prefix' Text ' ' Text ']' Text ' ' Text '>>init' Text '\n ' Text '{' Text ' ' Text 'wiki' Text ' ' Text '"wiki-common"' Literal.String ' ' Text '}' Text ' ' Text '>>template' Text ' ' Text ';\n' Keyword '\n' Text ':' Keyword ' ' Text 'init-wiki' Name.Function ' ' Text '( ' Name.Function '-- ' Name.Function ')\n' Name.Function ' ' Text '"resource:extra/webapps/wiki/initial-content"' Literal.String ' ' Text '[' Text '\n ' Text '[' Text '\n ' Text 'dup ' Name.Builtin '".txt"' Literal.String ' ' Text '?tail' Text ' ' Text '[' Text '\n ' Text 'swap ' Name.Builtin 'ascii' Text ' ' Text 'file-contents' Text '\n ' Text 'f ' Name.Constant '' Text '\n ' Text 'swap ' Name.Builtin '>>content' Text '\n ' Text 'swap ' Name.Builtin '>>title' Text '\n ' Text '"slava"' Literal.String ' ' Text '>>author' Text '\n ' Text 'now' Text ' ' Text '>>date' Text '\n ' Text 'add-revision' Text '\n ' Text ']' Text ' ' Text '[' Text ' ' Text '2drop ' Name.Builtin ']' Text ' ' Text 'if\n' Name.Builtin ' ' Text ']' Text ' ' Text 'each\n' Name.Builtin ' ' Text ']' Text ' ' Text 'with-directory-files' Text ' ' Text ';\n' Keyword