From 46262a6554d1ff78e92cc12361e67115a22c1692 Mon Sep 17 00:00:00 2001 From: Doug Coleman Date: Tue, 23 Sep 2008 15:59:33 -0500 Subject: [PATCH 01/16] refactoring db.tuples, all tests pass so far.. --- basis/db/queries/queries.factor | 8 +++--- basis/db/tuples/tuples-tests.factor | 15 ++++++++++ basis/db/tuples/tuples.factor | 44 ++++++++++++++++++----------- 3 files changed, 46 insertions(+), 21 deletions(-) diff --git a/basis/db/queries/queries.factor b/basis/db/queries/queries.factor index 89c28b5262..300822cc50 100644 --- a/basis/db/queries/queries.factor +++ b/basis/db/queries/queries.factor @@ -168,7 +168,7 @@ M: db ( tuple class -- statement ) number>string " limit " swap 3append ] curry change-sql drop ; -: make-query ( tuple query -- tuple' ) +: make-query* ( tuple query -- tuple' ) dupd { [ group>> [ drop ] [ do-group ] if-empty ] @@ -177,8 +177,8 @@ M: db ( tuple class -- statement ) [ offset>> [ do-offset ] [ drop ] if* ] } 2cleave ; -M: db ( tuple class query -- tuple ) - [ ] dip make-query ; +M: db make-query ( tuple class query -- tuple ) + [ ] dip make-query* ; ! select ID, NAME, SCORE from EXAM limit 1 offset 3 @@ -198,7 +198,7 @@ M: db ( tuple class groups -- statement ) \ query new swap >>group [ [ "select count(*) from " 0% 0% where-clause ] query-make ] - dip make-query ; + dip make-query* ; : create-index ( index-name table-name columns -- ) [ diff --git a/basis/db/tuples/tuples-tests.factor b/basis/db/tuples/tuples-tests.factor index 67e46f9e18..466d086fbe 100755 --- a/basis/db/tuples/tuples-tests.factor +++ b/basis/db/tuples/tuples-tests.factor @@ -499,3 +499,18 @@ string-encoding-test "STRING_ENCODING_TEST" { \ ensure-table must-infer \ create-table must-infer \ drop-table must-infer + +: test-queries ( -- ) + [ ] [ exam ensure-table ] unit-test + ! [ ] [ T{ exam f f "Kyle" 100 } insert-tuple ] unit-test + ! [ ] [ T{ exam f f "Stan" 80 } insert-tuple ] unit-test + ! [ ] [ T{ exam f f "Kenny" 60 } insert-tuple ] unit-test + ! [ ] [ T{ exam f f "Cartman" 41 } insert-tuple ] unit-test + [ ] [ 10 [ random-exam insert-tuple ] times ] unit-test + [ ] [ ] unit-test + ! [ ] [ query ] unit-test + + ; + +: test-db ( -- ) + "tuples-test.db" temp-file sqlite-db make-db db-open db set ; diff --git a/basis/db/tuples/tuples.factor b/basis/db/tuples/tuples.factor index 3c3bae3adc..534b91b8fc 100755 --- a/basis/db/tuples/tuples.factor +++ b/basis/db/tuples/tuples.factor @@ -6,6 +6,30 @@ math.parser io prettyprint db.types continuations destructors mirrors ; IN: db.tuples +TUPLE: query tuple group order offset limit ; + +: ( -- query ) \ query new ; + +GENERIC: >query ( object -- query ) + +M: query >query ; + +M: tuple >query swap >>tuple ; + +! returns a sequence of prepared-statements +HOOK: create-sql-statement db ( class -- object ) +HOOK: drop-sql-statement db ( class -- object ) + +HOOK: db ( class -- object ) +HOOK: db ( class -- object ) +HOOK: db ( class -- object ) +HOOK: db ( tuple class -- object ) +HOOK: db ( tuple class -- tuple ) +HOOK: db ( tuple class groups -- statement ) +HOOK: make-query db ( tuple class query -- statement ) + +HOOK: insert-tuple* db ( tuple statement -- ) + : define-persistent ( class table columns -- ) >r dupd "db-table" set-word-prop dup r> [ relation? ] partition swapd @@ -33,21 +57,6 @@ SYMBOL: sql-counter : next-sql-counter ( -- str ) sql-counter [ inc ] [ get ] bi number>string ; -! returns a sequence of prepared-statements -HOOK: create-sql-statement db ( class -- object ) -HOOK: drop-sql-statement db ( class -- object ) - -HOOK: db ( class -- object ) -HOOK: db ( class -- object ) -HOOK: db ( class -- object ) -HOOK: db ( tuple class -- object ) -HOOK: db ( tuple class -- tuple ) -TUPLE: query group order offset limit ; -HOOK: db ( tuple class query -- statement' ) -HOOK: db ( tuple class groups -- n ) - -HOOK: insert-tuple* db ( tuple statement -- ) - GENERIC: eval-generator ( singleton -- object ) : resulting-tuple ( exemplar-tuple row out-params -- tuple ) @@ -121,13 +130,14 @@ GENERIC: eval-generator ( singleton -- object ) [ [ bind-tuple ] [ query-tuples ] 2bi ] with-disposal ; : query ( tuple query -- tuples ) - [ dup dup class ] dip do-select ; + [ dup dup class ] dip make-query do-select ; + : select-tuples ( tuple -- tuples ) dup dup class do-select ; : select-tuple ( tuple -- tuple/f ) - dup dup class \ query new 1 >>limit do-select + dup dup class \ query new 1 >>limit make-query do-select [ f ] [ first ] if-empty ; : do-count ( exemplar-tuple statement -- tuples ) From dad89fb2b79bc7156587ac55b38ba6d86a515723 Mon Sep 17 00:00:00 2001 From: Slava Pestov Date: Tue, 23 Sep 2008 16:46:50 -0500 Subject: [PATCH 02/16] Fix XHTML validation --- basis/furnace/chloe-tags/chloe-tags.factor | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/basis/furnace/chloe-tags/chloe-tags.factor b/basis/furnace/chloe-tags/chloe-tags.factor index 6645e04c93..b67431092c 100644 --- a/basis/furnace/chloe-tags/chloe-tags.factor +++ b/basis/furnace/chloe-tags/chloe-tags.factor @@ -72,9 +72,11 @@ CHLOE: a : compile-hidden-form-fields ( for -- ) '[ - _ [ "," split [ hidden render ] each ] when* - nested-forms get " " join f like nested-forms-key hidden-form-field - [ modify-form ] each-responder +
+ _ [ "," split [ hidden render ] each ] when* + nested-forms get " " join f like nested-forms-key hidden-form-field + [ modify-form ] each-responder +
] [code] ; : compile-form-attrs ( method action attrs -- ) From 28bf85e9677d7fdb2d457bbf75b56964081a095d Mon Sep 17 00:00:00 2001 From: Slava Pestov Date: Tue, 23 Sep 2008 16:50:23 -0500 Subject: [PATCH 03/16] Fix XHTML validation --- basis/furnace/chloe-tags/chloe-tags.factor | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/basis/furnace/chloe-tags/chloe-tags.factor b/basis/furnace/chloe-tags/chloe-tags.factor index b67431092c..d3ed2054b5 100644 --- a/basis/furnace/chloe-tags/chloe-tags.factor +++ b/basis/furnace/chloe-tags/chloe-tags.factor @@ -111,7 +111,7 @@ CHLOE: form STRING: button-tag-markup - +
; @@ -122,7 +122,7 @@ CHLOE: button button-tag-markup string>xml body>> { [ [ attrs>> chloe-attrs-only ] dip add-tag-attrs ] - [ [ attrs>> non-chloe-attrs-only ] dip "button" tag-named add-tag-attrs ] - [ [ children>> ] dip "button" tag-named (>>children) ] + [ [ attrs>> non-chloe-attrs-only ] dip "button" deep-tag-named add-tag-attrs ] + [ [ children>> ] dip "button" deep-tag-named (>>children) ] [ nip ] } 2cleave compile-chloe-tag ; From 57c3a823b53df3eff86905c3477de945f1287484 Mon Sep 17 00:00:00 2001 From: Slava Pestov Date: Tue, 23 Sep 2008 16:52:50 -0500 Subject: [PATCH 04/16] Fix XHTML validation --- extra/webapps/pastebin/pastebin.xml | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/extra/webapps/pastebin/pastebin.xml b/extra/webapps/pastebin/pastebin.xml index a6b3078aa7..3c9cb7ce96 100644 --- a/extra/webapps/pastebin/pastebin.xml +++ b/extra/webapps/pastebin/pastebin.xml @@ -5,9 +5,11 @@ Pastebin - - - + + + + + From ce7117e3d1ada79db85b800b1175965034e1af93 Mon Sep 17 00:00:00 2001 From: Slava Pestov Date: Tue, 23 Sep 2008 16:55:00 -0500 Subject: [PATCH 05/16] Fix CSS validation --- extra/webapps/wiki/wiki.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extra/webapps/wiki/wiki.css b/extra/webapps/wiki/wiki.css index c27c44315f..4ecc6e5282 100644 --- a/extra/webapps/wiki/wiki.css +++ b/extra/webapps/wiki/wiki.css @@ -41,7 +41,7 @@ .contents { padding: 4px; margin: 4px; - border: 1px dashed grey; + border: 1px dashed gray; background: #f5f1fd; width: 200px; } From 8eea1d13c2dd269ac6e7c8cc3fd8c017cbee4f0a Mon Sep 17 00:00:00 2001 From: Doug Coleman Date: Tue, 23 Sep 2008 16:55:32 -0500 Subject: [PATCH 06/16] define-persistent checks that slots exist --- basis/db/tuples/tuples-tests.factor | 14 ++++++++++++-- basis/db/tuples/tuples.factor | 13 +++++++++++-- 2 files changed, 23 insertions(+), 4 deletions(-) diff --git a/basis/db/tuples/tuples-tests.factor b/basis/db/tuples/tuples-tests.factor index 466d086fbe..45a51719f9 100755 --- a/basis/db/tuples/tuples-tests.factor +++ b/basis/db/tuples/tuples-tests.factor @@ -236,6 +236,17 @@ TUPLE: exam id name score ; exam boa ; : test-intervals ( -- ) + [ + exam "EXAM" + { + { "idd" "ID" +db-assigned-id+ } + { "named" "NAME" TEXT } + { "score" "SCORE" INTEGER } + } define-persistent + ] [ + seq>> { "idd" "named" } = + ] must-fail-with + exam "EXAM" { { "id" "ID" +db-assigned-id+ } @@ -507,9 +518,8 @@ string-encoding-test "STRING_ENCODING_TEST" { ! [ ] [ T{ exam f f "Kenny" 60 } insert-tuple ] unit-test ! [ ] [ T{ exam f f "Cartman" 41 } insert-tuple ] unit-test [ ] [ 10 [ random-exam insert-tuple ] times ] unit-test - [ ] [ ] unit-test + ! [ ] [ T{ exam { name "Kenny" } } >query ] unit-test ! [ ] [ query ] unit-test - ; : test-db ( -- ) diff --git a/basis/db/tuples/tuples.factor b/basis/db/tuples/tuples.factor index 534b91b8fc..bff83b5b49 100755 --- a/basis/db/tuples/tuples.factor +++ b/basis/db/tuples/tuples.factor @@ -3,7 +3,7 @@ USING: arrays assocs classes db kernel namespaces classes.tuple words sequences slots math accessors math.parser io prettyprint db.types continuations -destructors mirrors ; +destructors mirrors sets ; IN: db.tuples TUPLE: query tuple group order offset limit ; @@ -30,8 +30,17 @@ HOOK: make-query db ( tuple class query -- statement ) HOOK: insert-tuple* db ( tuple statement -- ) +ERROR: no-slots-named class seq ; +: check-columns ( class columns -- ) + tuck + [ [ first ] map ] + [ "slots" word-prop [ name>> ] map ] bi* diff + [ drop ] [ no-slots-named ] if-empty ; + : define-persistent ( class table columns -- ) - >r dupd "db-table" set-word-prop dup r> + pick dupd + check-columns + [ dupd "db-table" set-word-prop dup ] dip [ relation? ] partition swapd dupd [ spec>tuple ] with map "db-columns" set-word-prop From d3044b698ab2104c4d451ea3d27d69fd05de37e2 Mon Sep 17 00:00:00 2001 From: Slava Pestov Date: Tue, 23 Sep 2008 17:01:57 -0500 Subject: [PATCH 07/16] XHTML 1.1 --- extra/websites/concatenative/page.xml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/extra/websites/concatenative/page.xml b/extra/websites/concatenative/page.xml index 129dcb1546..2a5cbf7024 100644 --- a/extra/websites/concatenative/page.xml +++ b/extra/websites/concatenative/page.xml @@ -1,7 +1,6 @@ - + From 3a11e4d09a39dd91ec6f757b5cbf4bfc80de067b Mon Sep 17 00:00:00 2001 From: Slava Pestov Date: Tue, 23 Sep 2008 19:08:32 -0500 Subject: [PATCH 08/16] Fix rendering issue --- basis/furnace/chloe-tags/chloe-tags.factor | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/basis/furnace/chloe-tags/chloe-tags.factor b/basis/furnace/chloe-tags/chloe-tags.factor index d3ed2054b5..faa74d1a16 100644 --- a/basis/furnace/chloe-tags/chloe-tags.factor +++ b/basis/furnace/chloe-tags/chloe-tags.factor @@ -111,7 +111,7 @@ CHLOE: form STRING: button-tag-markup -
+
; From f16348fe757e872619ce1cd6aa368d534343d283 Mon Sep 17 00:00:00 2001 From: Slava Pestov Date: Tue, 23 Sep 2008 19:29:09 -0500 Subject: [PATCH 09/16] Fix tests --- .../redirection/redirection-tests.factor | 20 +++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/basis/http/server/redirection/redirection-tests.factor b/basis/http/server/redirection/redirection-tests.factor index c7a1370397..14855ca875 100644 --- a/basis/http/server/redirection/redirection-tests.factor +++ b/basis/http/server/redirection/redirection-tests.factor @@ -15,35 +15,39 @@ namespaces tools.test present kernel ; >>url request set - [ "http://www.apple.com:80/xxx/bar" ] [ + [ "http://www.apple.com/xxx/bar" ] [ relative-to-request present ] unit-test - [ "http://www.apple.com:80/xxx/baz" ] [ + [ "http://www.apple.com/xxx/baz" ] [ "baz" >>path relative-to-request present ] unit-test - [ "http://www.apple.com:80/xxx/baz?c=d" ] [ + [ "http://www.apple.com/xxx/baz?c=d" ] [ "baz" >>path { { "c" "d" } } >>query relative-to-request present ] unit-test - [ "http://www.apple.com:80/xxx/bar?c=d" ] [ + [ "http://www.apple.com/xxx/bar?c=d" ] [ { { "c" "d" } } >>query relative-to-request present ] unit-test - [ "http://www.apple.com:80/flip" ] [ + [ "http://www.apple.com/flip" ] [ "/flip" >>path relative-to-request present ] unit-test - [ "http://www.apple.com:80/flip?c=d" ] [ + [ "http://www.apple.com/flip?c=d" ] [ "/flip" >>path { { "c" "d" } } >>query relative-to-request present ] unit-test - [ "http://www.jedit.org:80/" ] [ + [ "http://www.jedit.org/" ] [ "http://www.jedit.org" >url relative-to-request present ] unit-test - [ "http://www.jedit.org:80/?a=b" ] [ + [ "http://www.jedit.org/?a=b" ] [ "http://www.jedit.org" >url { { "a" "b" } } >>query relative-to-request present ] unit-test + + [ "http://www.jedit.org:1234/?a=b" ] [ + "http://www.jedit.org:1234" >url { { "a" "b" } } >>query relative-to-request present + ] unit-test ] with-scope From 94ec8c7f78d00ae6c1ed683ca52d7231771555a4 Mon Sep 17 00:00:00 2001 From: Doug Coleman Date: Tue, 23 Sep 2008 20:34:33 -0500 Subject: [PATCH 10/16] search all-slots instead --- basis/db/tuples/tuples.factor | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/basis/db/tuples/tuples.factor b/basis/db/tuples/tuples.factor index bff83b5b49..2bdbb138d7 100755 --- a/basis/db/tuples/tuples.factor +++ b/basis/db/tuples/tuples.factor @@ -34,7 +34,7 @@ ERROR: no-slots-named class seq ; : check-columns ( class columns -- ) tuck [ [ first ] map ] - [ "slots" word-prop [ name>> ] map ] bi* diff + [ all-slots [ name>> ] map ] bi* diff [ drop ] [ no-slots-named ] if-empty ; : define-persistent ( class table columns -- ) From f1317758343b99d956a0d81b86abce82d8b01d30 Mon Sep 17 00:00:00 2001 From: Slava Pestov Date: Tue, 23 Sep 2008 22:01:19 -0500 Subject: [PATCH 11/16] Fix Chloe unit tests --- basis/html/templates/chloe/chloe-tests.factor | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/basis/html/templates/chloe/chloe-tests.factor b/basis/html/templates/chloe/chloe-tests.factor index 3fd0d00712..5114b4088a 100644 --- a/basis/html/templates/chloe/chloe-tests.factor +++ b/basis/html/templates/chloe/chloe-tests.factor @@ -134,7 +134,7 @@ TUPLE: person first-name last-name ; [ ] [ H{ { "a" H{ { "b" "c" } } } } values set ] unit-test -[ "
" ] [ +[ "
" ] [ [ "test10" test-template call-template ] run-template From f435e1cf75a2864f5af3c7abc8fa10dbffd51cb4 Mon Sep 17 00:00:00 2001 From: Slava Pestov Date: Tue, 23 Sep 2008 22:01:26 -0500 Subject: [PATCH 12/16] Docs for html.* --- basis/html/components/components-docs.factor | 105 +++++++ basis/html/components/components.factor | 3 + basis/html/elements/elements-docs.factor | 29 ++ basis/html/elements/elements.factor | 41 +-- basis/html/forms/forms-docs.factor | 125 ++++++++ basis/html/forms/forms.factor | 2 +- basis/html/streams/streams-docs.factor | 32 +++ basis/html/streams/streams.factor | 2 +- basis/html/templates/chloe/chloe-docs.factor | 284 +++++++++++++++++++ basis/html/templates/fhtml/fhtml-docs.factor | 14 + basis/html/templates/templates-docs.factor | 89 ++++++ basis/html/templates/templates.factor | 2 +- 12 files changed, 685 insertions(+), 43 deletions(-) create mode 100644 basis/html/components/components-docs.factor create mode 100644 basis/html/elements/elements-docs.factor create mode 100644 basis/html/forms/forms-docs.factor create mode 100644 basis/html/streams/streams-docs.factor create mode 100644 basis/html/templates/chloe/chloe-docs.factor create mode 100644 basis/html/templates/fhtml/fhtml-docs.factor create mode 100644 basis/html/templates/templates-docs.factor diff --git a/basis/html/components/components-docs.factor b/basis/html/components/components-docs.factor new file mode 100644 index 0000000000..d7690b30e2 --- /dev/null +++ b/basis/html/components/components-docs.factor @@ -0,0 +1,105 @@ +! Copyright (C) 2008 Your name. +! See http://factorcode.org/license.txt for BSD license. +USING: help.markup help.syntax io.streams.string kernel strings +urls lcs inspector present io ; +IN: html.components + +HELP: checkbox +{ $class-description "Checkbox components render a boolean value. The " { $slot "label" } " slot must be set to a string." } ; + +HELP: choice +{ $class-description "Choice components render a popup menu or list box with either single or multiple selection." +$nl +"The " { $slot "multiple" } " slot determines whether multiple elements may be selected at once; if this is set to a true value, then the component value must be a sequence of strings, otherwise it must be a single string." +$nl +"The " { $slot "size" } " slot determines the number of items visible at one time; if neither this nor " { $slot "multiple" } " is set, the component is rendered as a popup menu rather than a list." +$nl +"The " { $slot "choices" } " slot determines all possible choices which may be selected. It names a value, rather than storing the choices directly." } ; + +HELP: code +{ $class-description "Code components render string value with the " { $vocab-link "xmode.code2html" } " syntax highlighting vocabulary. The " { $slot "mode" } " slot names a value holding an XMode mode name." } ; + +HELP: field +{ $class-description "Field components display a one-line editor for a string value. The " { $slot "size" } " slot determines the maximum displayed width of the field." } ; + +HELP: password +{ $class-description "Password field components display a one-line editor which obscures the user's input. The " { $slot "size" } " slot determines the maximum displayed width of the field. Unlike other components, on failed validation, the contents of a password field are not sent back to the client. This is a security feature, intended to avoid revealing the password to potential snoopers who use the " { $strong "View Source" } " feature." } ; + +HELP: textarea +{ $class-description "Text area components display a multi-line editor for a string value. The " { $slot "rows" } " and " { $slot "cols" } " properties determine the size of the text area." } ; + +HELP: link +{ $description "Link components render a link to an object stored at a value, with the link title and URL determined by the " { $link link-title } " and " { $link link-href } " generic words." } ; + +HELP: link-title +{ $values { "obj" object } { "string" string } } +{ $description "Outputs the title to render for a link to the object." } ; + +HELP: link-href +{ $values { "obj" object } { "url" "a " { $link string } " or " { $link url } } } +{ $description "Outputs the URL to render for a link to the object." } ; + +ARTICLE: "html.components.links" "Link components" +"Link components render a link to an object." +{ $subsection link } +"The link title and URL are determined by passing the object to a pair of generic words:" +{ $subsection link-title } +{ $subsection link-href } +"The generic words provide methods on the " { $link string } " and " { $link url } " classes which treat the object as a URL. New methods can be defined for rendering links to custom data types." ; + +HELP: comparison +{ $description "Comparison components render diffs output by the " { $link diff } " word." } ; + +HELP: farkup +{ $description "Farkup components render " { $link "farkup" } "." } ; + +HELP: hidden +{ $description "Hidden components render as a hidden form field. For example, a page for editing a weblog post might contain a hidden field with the post ID." } ; + +HELP: html +{ $description "HTML components render HTML verbatim, without any escaping. Care must be taken to only render trusted input, to avoid cross-site scripting attacks." } ; + +HELP: inspector +{ $description "Inspector components render an arbitrary object by passing it to the " { $link describe } " word." } ; + +HELP: label +{ $description "Label components render an object as a piece of text by passing it to the " { $link present } " word." } ; + +HELP: render +{ $values { "name" "a value name" } { "renderer" "a component renderer" } } +{ $description "Renders an HTML component to the " { $link output-stream } "." } ; + +HELP: render* +{ $values { "value" "a value" } { "name" "a value name" } { "renderer" "a component renderer" } } +{ $contract "Renders an HTML component to the " { $link output-stream } "." } ; + +ARTICLE: "html.components" "HTML components" +"The " { $vocab-link "html.components" } " vocabulary provides various HTML form components." +$nl +"Most web applications can use the " { $vocab-link "html.templates.chloe" } " templating framework instead of using this vocabulary directly. Where maximum flexibility is required, this vocabulary can be used together with the " { $vocab-link "html.templates.fhtml" } " templating framework." +$nl +"Rendering components:" +{ $subsection render } +"Components render a named value, and the name of the value is passed in every time the component is rendered, rather than being associated with the component itself. Named values are taken from the current HTML form (see " { $link "html.forms" } ")." +$nl +"Component come in two varieties: singletons and tuples. Components with no configuration are singletons; they do not have to instantiated, rather the class word represents the component. Tuple components have to be instantiated and offer configuration options." +$nl +"Singleton components:" +{ $subsection hidden } +{ $subsection link } +{ $subsection inspector } +{ $subsection comparison } +{ $subsection html } +"Tuple components:" +{ $subsection field } +{ $subsection password } +{ $subsection textarea } +{ $subsection choice } +{ $subsection checkbox } +{ $subsection code } +{ $subsection farkup } +"Creating custom components:" +{ $subsection render* } +"Custom components can emit HTML using the " { $vocab-link "html.elements" } " vocabulary." ; + +ABOUT: "html.components" diff --git a/basis/html/components/components.factor b/basis/html/components/components.factor index a46f595459..b78e3473a7 100644 --- a/basis/html/components/components.factor +++ b/basis/html/components/components.factor @@ -146,6 +146,9 @@ M: code render* ! Farkup component TUPLE: farkup no-follow disable-images parsed ; +: ( -- farkup ) + farkup new ; + : string>boolean ( string -- boolean ) { { "true" [ t ] } diff --git a/basis/html/elements/elements-docs.factor b/basis/html/elements/elements-docs.factor new file mode 100644 index 0000000000..f6e15e46cd --- /dev/null +++ b/basis/html/elements/elements-docs.factor @@ -0,0 +1,29 @@ +IN: html.elements +USING: help.markup help.syntax io present ; + +ARTICLE: "html.elements" "HTML elements" +"The " { $vocab-link "html.elements" } " vocabulary provides words for writing HTML tags to the " { $link output-stream } " with a familiar look and feel in the code." +$nl +"HTML tags can be used in a number of different ways. The simplest is a tag with no attributes:" +{ $code "

\"someoutput\" write

" } +"In the above, " { $link

} " will output the opening tag with no attributes. and " { $link

} " will output the closing tag." +{ $code "

\"someoutput\" write

" } +"This time the opening tag does not have the '>'. Any attribute words used between the calls to " { $link

} " will write an attribute whose value is the top of the stack. Attribute values can be any object supported by the " { $link present } " word." +$nl +"Values for attributes can be used directly without any stack operations. Assuming we have a string on the stack, all three of the below will output a link:" +{ $code " \"Click me\" write " } +{ $code " \"click\" write " } +{ $code " \"click\" write " } +"Tags that have no ``closing'' equivalent have a trailing " { $snippet "tag/>" } " form:" +{ $code "" } +"For the full list of HTML tags and attributes, consult the word list for the " { $vocab-link "html.elements" } " vocabulary. In addition to HTML tag and attribute words, a few utilities are provided." +$nl +"Writing unescaped HTML to " { $vocab-link "html.streams" } ":" +{ $subsection write-html } +{ $subsection print-html } +"Writing some common HTML patterns:" +{ $subsection xhtml-preamble } +{ $subsection simple-page } +{ $subsection render-error } ; + +ABOUT: "html.elements" diff --git a/basis/html/elements/elements.factor b/basis/html/elements/elements.factor index ced2f700dc..c7281df54d 100644 --- a/basis/html/elements/elements.factor +++ b/basis/html/elements/elements.factor @@ -9,45 +9,6 @@ urls math math.parser combinators present fry ; IN: html.elements -! These words are used to provide a means of writing -! formatted HTML to standard output with a familiar 'html' look -! and feel in the code. -! -! HTML tags can be used in a number of different ways. The highest -! level involves a similar syntax to HTML: -! -!

"someoutput" write

-! -!

will output the opening tag and

will output the closing -! tag with no attributes. -! -!

"someoutput" write

-! -! This time the opening tag does not have the '>'. It pushes -! a namespace on the stack to hold the attributes and values. -! Any attribute words used will store the attribute and values -! in that namespace. Before the attribute word should come the -! value of that attribute. -! The finishing word will print out the operning tag including -! attributes. -! Any writes after this will appear after the opening tag. -! -! Values for attributes can be used directly without any stack -! operations: -! -! (url -- ) -! "Click me" write -! -! (url -- ) -! "click" write -! -! (url -- ) -! "click" write -! -! Tags that have no 'closing' equivalent have a trailing tag/> form: -! -! - SYMBOL: html : write-html ( str -- ) @@ -170,7 +131,7 @@ SYMBOL: html : xhtml-preamble ( -- ) "" write-html - "" write-html ; + "" write-html ; : simple-page ( title quot -- ) #! Call the quotation, with all output going to the diff --git a/basis/html/forms/forms-docs.factor b/basis/html/forms/forms-docs.factor new file mode 100644 index 0000000000..7a2134c996 --- /dev/null +++ b/basis/html/forms/forms-docs.factor @@ -0,0 +1,125 @@ +IN: html.forms +USING: help.markup help.syntax strings quotations kernel assocs ; + +HELP:
+{ $values { "form" form } } +{ $description "Creates a new form. Usually " { $link with-form } " is used instead." } ; + +HELP: form +{ $var-description "Variable holding current form. Bound by " { $link with-form } ", " { $link nest-form } " and " { $link begin-form } "." } +{ $class-description "The class of HTML forms. New instances are created by " { $link } "." } ; + +HELP: with-form +{ $values { "name" string } { "quot" quotation } } +{ $description "Runs the quotation in a new dynamic scope with the " { $link form } " variable rebound to the form stored in the value named " { $snippet "name" } "." } ; + +HELP: nest-form +{ $values { "name" string } { "quot" quotation } } +{ $description "Runs the quotation in a new dynamic scope with the " { $link form } " variable rebound to a new form, which is subsequently stored in the value named " { $snippet "name" } "." } +{ $examples + "The " { $vocab-link "webapps.pastebin" } " uses a form to display pastes; inside this form it nests another form for creating annotations, and fills in some default values for new annotations:" + { $code + "" + " [" + " validate-integer-id" + " \"id\" value paste from-object" + "" + " \"id\" value" + " \"new-annotation\" [" + " \"parent\" set-value" + " mode-names \"modes\" set-value" + " \"factor\" \"mode\" set-value" + " ] nest-form" + " ] >>init" + } +} ; + +HELP: begin-form +{ $description "Begins a new form." } ; + +HELP: value +{ $values { "name" string } { "value" object } } +{ $description "Gets a form value. This word is used to get form field values after validation." } ; + +HELP: set-value +{ $values { "value" object } { "name" string } } +{ $description "Sets a form value. This word is used to preset form field values before rendering." } ; + +HELP: from-object +{ $values { "object" object } } +{ $description "Sets the current form's values to the object's slot values." } +{ $examples + "Here is a typical action implementation, which selects a golf course object from the database with the ID specified in the HTTP request, and renders a form with values from this object:" + { $code + "" + "" + " [" + " validate-integer-id" + " \"id\" value " + " select-tuple from-object" + " ] >>init" + "" + " { golf \"view-course\" } >>template" + } +} ; + +HELP: to-object +{ $values { "destination" object } { "names" "a sequence of value names" } } +{ $description "Stores the given sequence of form values into the slots of the object having the same names. This word is used to extract form field values after validation." } ; + +HELP: with-each-value +{ $values { "name" string } { "quot" quotation } } +{ $description "Calls the quotation with each element of the value named " { $snippet "name" } "; the value must be a sequence. The quotation is called in a new dynamic scope with the " { $snippet "index" } " and " { $snippet "value" } " values set to the one-based index, and the sequence element in question, respectively." } +{ $notes "This word is used to implement the " { $snippet "t:each" } " tag of the " { $vocab-link "html.templates.chloe" } " templating system. It can also be called directly from " { $vocab-link "html.templates.fhtml" } " templates." } ; + +HELP: with-each-object +{ $description "Calls the quotation with each element of the value named " { $snippet "name" } "; the value must be a sequence. The quotation is called in a new dynamic scope where the object's slots become named values, as if " { $link from-object } " was called." } +{ $notes "This word is used to implement the " { $snippet "t:bind-each" } " tag of the " { $vocab-link "html.templates.chloe" } " templating system. It can also be called directly from " { $vocab-link "html.templates.fhtml" } " templates." } ; + +HELP: validation-failed? +{ $values { "?" "a boolean" } } +{ $description "Tests if validation of the current form failed." } ; + +HELP: validate-values +{ $values { "assoc" assoc } { "validators" "an assoc mapping value names to quotations" } } +{ $description "Validates values in the assoc by looking up the corresponding validation quotation, and storing the results in named values of the current form." } ; + +ARTICLE: "html.forms.forms" "HTML form infrastructure" +"The below words are used to implement the " { $vocab-link "furnace.actions" } " vocabulary. Calling them directly is rarely necessary." +$nl +"Creating a new form:" +{ $subsection } +"Variable holding current form:" +{ $subsection form } +"Working with forms:" +{ $subsection with-form } +{ $subsection begin-form } +"Validation:" +{ $subsection validation-error } +{ $subsection validation-failed? } +{ $subsection validate-values } ; + +ARTICLE: "html.forms.values" "HTML form values" +"Form values are a central concept in the Furnace framework. Web actions primarily concern themselves with validating values, marshalling values to a database, and setting values for display in a form." +$nl +"Getting and setting values:" +{ $subsection value } +{ $subsection set-value } +{ $subsection from-object } +{ $subsection to-object } +"Iterating over values; these words are used by " { $vocab-link "html.templates.chloe" } " to implement the " { $snippet "t:each" } " and " { $snippet "t:bind-each" } " tags:" +{ $subsection with-each-value } +{ $subsection with-each-object } +"Nesting a form inside another form as a value:" +{ $subsection nest-form } ; + +ARTICLE: "html.forms" "HTML forms" +"The " { $vocab-link "html.forms" } " vocabulary implements support for rendering and validating HTML forms. The definition of a " { $emphasis "form" } " is a bit more general than the content of an " { $snippet "" } " tag. Namely, a page which displays a database record without offering any editing capability is considered a form too; it consists entirely of read-only components." +$nl +"This vocabulary is an integral part of the " { $vocab-link "furnace" } " web framework. The " { $vocab-link "html.templates.chloe" } " vocabulary uses the HTML form words to implement various template tags. The words are also often used directly from web action implementations." +$nl +"This vocabulary can be used without either the Furnace framework or the HTTP server; for example, as part of a static HTML generation tool." +{ $subsection "html.forms.forms" } +{ $subsection "html.forms.values" } ; + +ABOUT: "html.forms" diff --git a/basis/html/forms/forms.factor b/basis/html/forms/forms.factor index 7dd4b6146b..c1c1aa3def 100644 --- a/basis/html/forms/forms.factor +++ b/basis/html/forms/forms.factor @@ -102,5 +102,5 @@ C: validation-error dup validation-error? [ form get t >>validation-failed drop ] when swap set-value ; -: validate-values ( assoc validators -- assoc' ) +: validate-values ( assoc validators -- ) swap '[ [ dup _ at ] dip validate-value ] assoc-each ; diff --git a/basis/html/streams/streams-docs.factor b/basis/html/streams/streams-docs.factor new file mode 100644 index 0000000000..7c5bea805d --- /dev/null +++ b/basis/html/streams/streams-docs.factor @@ -0,0 +1,32 @@ +IN: html.streams +USING: help.markup help.syntax kernel strings io io.styles +quotations ; + +HELP: browser-link-href +{ $values { "presented" object } { "href" string } } +{ $contract "Outputs a link to a page displaying a presentation of the given object. This word is called when " { $link write-object } " is called on " { $link html-stream } " instances." } ; + +HELP: html-stream +{ $class-description "A formatted output stream which emits HTML markup." } ; + +HELP: +{ $values { "stream" "an output stream" } { "html-stream" html-stream } } +{ $description "Creates a new formatted output stream which emits HTML markup on " { $snippet "stream" } "." } ; + +HELP: with-html-stream +{ $values { "quot" quotation } } +{ $description "Calls the quotation in a new dynamic scope with " { $link output-stream } " rebound to an " { $link html-stream } " wrapping the current " { $link output-stream } "." } +{ $examples + { $example + "[ \"Hello\" { { font-style bold } } format nl ] with-html-stream" + "Hello
" + } +} ; + +ARTICLE: "html.streams" "HTML streams" +"The " { $vocab-link "html.streams" } " vocabulary provides a stream which implements " { $link "styles" } " by writing HTML markup to the wrapped stream." +{ $subsection html-stream } +{ $subsection } +{ $subsection with-html-stream } ; + +ABOUT: "html.streams" diff --git a/basis/html/streams/streams.factor b/basis/html/streams/streams.factor index 7d90296fcb..7d0fe9b17c 100755 --- a/basis/html/streams/streams.factor +++ b/basis/html/streams/streams.factor @@ -25,7 +25,7 @@ TUPLE: html-stream stream last-div ; : a-div ( stream -- straem ) t >>last-div ; inline -: ( stream -- stream ) +: ( stream -- html-stream ) f html-stream boa ; ( path -- template ) +{ $values { "path" "a pathname string without the trailing " { $snippet ".xml" } " extension" } { "template" chloe } } +{ $description "Creates a new Chloe template object which can be passed to " { $link call-template } "." } ; + +HELP: required-attr +{ $values { "tag" tag } { "name" string } { "value" string } } +{ $description "Extracts an attribute from a tag." } +{ $errors "Throws an error if the attribute is not specified." } ; + +HELP: optional-attr +{ $values { "tag" tag } { "name" string } { "value" "a " { $link string } " or " { $link f } } } +{ $description "Extracts an attribute from a tag." } +{ $notes "Outputs " { $link f } " if the attribute is not specified." } ; + +HELP: compile-attr +{ $values { "value" "an attribute value" } } +{ $description "Compiles code which pushes an attribute value previously extracted by " { $link required-attr } " or " { $link optional-attr } " on the stack. If the attribute value begins with " { $snippet "@" } ", compiles into code which pushes the a form value." } ; + +HELP: CHLOE: +{ $syntax "name definition... ;" } +{ $values { "name" "the tag name" } { "definition" "a quotation with stack effect " { $snippet "( tag -- )" } } } +{ $description "Defines compilation semantics for the Chloe tag named " { $snippet "tag" } ". The definition body receives a " { $link tag } " on the stack." } ; + +HELP: CHLOE-SINGLETON: +{ $syntax "CHLOE-SINGLETON: name" } +{ $description "Defines a Chloe tag named " { $snippet "name" } " rendering an HTML component with singleton class word " { $snippet "name" } ". See " { $link "html.components" } "." } ; + +HELP: CHLOE-TUPLE: +{ $syntax "CHLOE-TUPLE: name" } +{ $description "Defines a Chloe tag named " { $snippet "name" } " rendering an HTML component with tuple class word " { $snippet "name" } ". See " { $link "html.components" } "." } ; + +HELP: reset-cache +{ $description "Resets the compiled template cache. Chloe automatically recompiles templates when their file changes on disk, however other when redefining Chloe tags or words which they call, the cache may have to be reset manually for the changes to take effect." } ; + +HELP: tag-stack +{ $var-description "During template compilation, holds the current nesting of XML element names. Can be used from " { $link POSTPONE: CHLOE: } " definitions to make a custom tag behave differently depending on how it is nested." } ; + +HELP: [write] +{ $values { "string" string } } +{ $description "Compiles code which writes the string when the template is called." } ; + +HELP: [code] +{ $values { "quot" quotation } } +{ $description "Compiles the quotation. It will be called when the template is called." } ; + +HELP: process-children +{ $values { "tag" tag } { "quot" "a quotation with stack effect " { $snippet "( compiled-tag -- )" } } } +{ $description "Compiles the tag. The quotation will be applied to the resulting quotation when the template is called." } +{ $examples "See " { $link "html.templates.chloe.extend.tags.example" } " for an example which uses this word to implement a custom control flow tag." } ; + +HELP: compile-children>string +{ $values { "tag" tag } } +{ $description "Compiles the tag so that the output it generates is written to a string, which is pushed on the stack when the template runs. A subsequent " { $link [code] } " call must be made with a quotation which consumes the string." } ; + +HELP: compile-with-scope +{ $values { "quot" quotation } } +{ $description "Calls the quotation and wraps any output it compiles in a " { $link with-scope } " form." } ; + +ARTICLE: "html.templates.chloe.tags.component" "Component Chloe tags" +"The following Chloe tags correspond exactly to " { $link "html.components" } ". Singleton component tags do not allow any attributes. Attributes of tuple component tags are mapped to tuple slot values of the component instance." +{ $table + { "Tag" "Component class" } + { { $snippet "t:checkbox" } { $link checkbox } } + { { $snippet "t:choice" } { $link choice } } + { { $snippet "t:code" } { $link code } } + { { $snippet "t:comparison" } { $link comparison } } + { { $snippet "t:farkup" } { $link farkup } } + { { $snippet "t:field" } { $link field } } + { { $snippet "t:hidden" } { $link hidden } } + { { $snippet "t:html" } { $link html } } + { { $snippet "t:inspector" } { $link inspector } } + { { $snippet "t:label" } { $link label } } + { { $snippet "t:link" } { $link link } } + { { $snippet "t:password" } { $link password } } + { { $snippet "t:textarea" } { $link textarea } } +} ; + +ARTICLE: "html.templates.chloe.tags.boilerplate" "Boilerplate Chloe tags" +"The following Chloe tags interface with the HTML templating " { $link "html.templates.boilerplate" } "." +$nl +"The tags marked with (*) are only available if the " { $vocab-link "furnace.chloe-tags" } " vocabulary is loaded." +{ $table + { { $snippet "t:title" } "Sets the title from a child template" } + { { $snippet "t:write-title" } "Renders the child's title from a master template" } + { { $snippet "t:style" } "Adds CSS markup from a child template" } + { { $snippet "t:write-style" } "Renders the children's CSS from a master template" } + { { $snippet "t:atom" } "Adds an Atom feed link from a child template (*)" } + { { $snippet "t:write-atom" } "Renders the children's list of Atom feed links (*)" } + { { $snippet "t:call-next-template" } "Calls the child template from a master template" } +} ; + +ARTICLE: "html.templates.chloe.tags.control" "Control-flow Chloe tags" +"While most control flow and logic should be embedded in the web actions themselves and not in the template, Chloe templates do support a minimal amount of control flow." +{ $table + { { $snippet "t:comment" } "All markup within a comment tag is ignored by the compiler." } + { { $snippet "t:bind" } { "Renders child content bound to a nested form named by the " { $snippet "t:name" } " attribute. See " { $link with-form } "." } } + { { $snippet "t:each" } { "Renders child content once for each element of the sequence in the value named by the " { $snippet "t:name" } " attribute. The sequence element and index are bound to the " { $snippet "value" } " and " { $snippet "index" } " values, respectively. See " { $link with-each-value } "." } } + { { $snippet "t:bind-each" } { "Renders child content once for each element of the sequence in the value named by the " { $snippet "t:name" } " attribute. The sequence element's slots are bound to values. See " { $link with-each-object } "." } } + { { $snippet "t:even" } { "Only valid inside a " { $snippet "t:each" } " or " { $snippet "t:bind-each" } ". Only renders child content if the " { $snippet "index" } " value is even." } } + { { $snippet "t:odd" } "As above, but only if the index value is odd." } + { { $snippet "t:if" } { "Renders child content if a boolean condition evaluates to true. The condition value is determined by the " { $snippet "t:code" } " or " { $snippet "t:value" } " attribute, exactly one of which must be specified. The former is a string of the form " { $snippet "vocabulary:word" } " denoting a word to execute with stack effect " { $snippet "( -- ? )" } ". The latter is a value name." } } +} ; + +ARTICLE: "html.templates.chloe.tags.form" "Chloe link and form tags" +"The following tags are only available if the " { $vocab-link "furnace.chloe-tags" } " vocabulary is loaded." +{ $table + { { $snippet "t:a" } { "Renders a link; extends the standard XHTML " { $snippet "a" } " tag by providing some integration with other web framework features. The following attributes are supported:" + { $list + { { $snippet "href" } " - a URL. If it begins with " { $snippet "$" } ", then it is interpreted as a responder-relative path." } + { { $snippet "rest" } " - a value to add at the end of the URL." } + { { $snippet "query" } " - a comma-separated list of value names defined in the current form which are to be passed to the link as query parameters." } + { { $snippet "value" } " - a value name holding a URL. If this attribute is specified, it overrides all others." } + } + "Any attributes not in the Chloe XML namespace are passed on to the generated " { $snippet "a" } " tag." + $nl + "An example:" + { $code + "" + " View" + "" + } + "The above might render as" + { $code + "" + " View" + "s" + } + } } + { { $snippet "t:form" } { + "Renders a form; extends the standard XHTML " { $snippet "form" } " tag by providing some integration with other web framework features, for example by adding hidden fields for authentication credentials and session management allowing those features to work with form submission transparently. The following attributes are supported:" + { $list + { { $snippet "t:method" } " - just like the " { $snippet "method" } " attribute of an HTML " { $snippet "form" } " tag, this can equal " { $snippet "get" } " or " { $snippet "post" } ". Unlike the HTML tag, the default is " { $snippet "post" } "." } + { { $snippet "t:action" } " - a URL. If it begins with " { $snippet "$" } ", then it is interpreted as a responder-relative path." } + { { $snippet "t:for" } " - a comma-separated list of form values which are to be inserted in the form as hidden fields. Other than being more concise, this is equivalent to nesting a series of " { $snippet "t:hidden" } " tags inside the form." } + } + "Any attributes not in the Chloe XML namespace are passed on to the generated " { $snippet "form" } " tag." + } } + { { $snippet "t:button" } { + "Shorthand for a form with a single button, whose label is the text child of the " { $snippet "t:button" } " tag. Attributes are processed as with the " { $snippet "t:form" } " tag, with the exception that any attributes not in the Chloe XML namespace are passed on to the generated " { $snippet "button" } " tag, rather than the " { $snippet "form" } " tag surrounding it." + $nl + "An example:" + { $code + "" + " class=\"link-button\"" + " Delete" + "" + } + } } +} ; + +ARTICLE: "html.templates.chloe.tags" "Standard Chloe tags" +"A Chloe template is an XML file with a mix of standard XHTML and Chloe tags." +$nl +"XHTML tags are rendered verbatim, except attribute values which begin with " { $snippet "@" } " are replaced with the corresponding " { $link "html.forms.values" } "." +$nl +"Chloe tags are defined in the " { $snippet "http://factorcode.org/chloe/1.0" } " namespace; by convention, it is bound with a prefix of " { $snippet "t" } ". The top-level tag must always be the " { $snippet "t:chloe" } " tag. A typical Chloe template looks like so:" +{ $code + "" + "" + "" + " ..." + "" +} +{ $subsection "html.templates.chloe.tags.component" } +{ $subsection "html.templates.chloe.tags.boilerplate" } +{ $subsection "html.templates.chloe.tags.control" } +{ $subsection "html.templates.chloe.tags.form" } ; + +ARTICLE: "html.templates.chloe.extend" "Extending Chloe" +"The " { $vocab-link "html.templates.chloe.syntax" } " and " { $vocab-link "html.templates.chloe.compiler" } " vocabularies contain the heart of the Chloe implementation." +$nl +"Chloe is implemented as a compiler which converts XML templates into Factor quotations. The template only has to be parsed and compiled once, and not on every HTTP request. This helps improve performance and memory usage." +$nl +"These vocabularies provide various hooks by which Chloe can be extended. First of all, new " { $link "html.components" } " can be wired in. If further flexibility is needed, entirely new tags can be defined by hooking into the Chloe compiler." +{ $subsection "html.templates.chloe.extend.components" } +{ $subsection "html.templates.chloe.extend.tags" } ; + +ARTICLE: "html.templates.chloe.extend.tags" "Extending Chloe with custom tags" +"Syntax for defining custom tags:" +{ $subsection POSTPONE: CHLOE: } +"A number of compiler words can be used from the " { $link POSTPONE: CHLOE: } " body to emit compiled template code." +$nl +"Extracting attributes from the XML tag:" +{ $subsection required-attr } +{ $subsection optional-attr } +{ $subsection compile-attr } +"Examining tag nesting:" +{ $subsection tag-stack } +"Generating code for printing strings and calling quotations:" +{ $subsection [write] } +{ $subsection [code] } +"Generating code from child elements:" +{ $subsection process-children } +{ $subsection compile-children>string } +{ $subsection compile-with-scope } +"Examples which illustrate some of the above:" +{ $subsection "html.templates.chloe.extend.tags.example" } ; + +ARTICLE: "html.templates.chloe.extend.tags.example" "Examples of custom Chloe tags" +"As a first example, let's develop a custom Chloe tag which simply renders a random number. The tag will be used as follows:" +{ $code + "" +} +"The " { $snippet "t:min" } " and " { $snippet "t:max" } " parameters are required, and " { $snippet "t:generator" } ", which can equal one of " { $snippet "default" } ", " { $snippet "system" } " or " { $snippet "secure" } ", is optional, with the default being " { $snippet "default" } "." +$nl +"Here is the " { $link POSTPONE: USING: } " form that we need for the below code to work:" +{ $code + "USING: combinators kernel math.parser math.ranges random" + "html.templates.chloe.compiler html.templates.chloe.syntax ;" +} +"We write a word which extracts the relevant attributes from an XML tag:" +{ $code + ": random-attrs ( tag -- min max generator )" + " [ \"min\" required-attr string>number ]" + " [ \"max\" required-attr string>number ]" + " [ \"generator\" optional-attr ]" + " tri ;" +} +"Next, we convert a random generator name into a random generator object:" +{ $code + ": string>random-generator ( string -- generator )" + " {" + " { \"default\" [ random-generator ] }" + " { \"system\" [ system-random-generator ] }" + " { \"secure\" [ secure-random-generator ] }" + " } case ;" +} +"Finally, we can write our Chloe tag:" +{ $code + "CHLOE: random" + " random-attrs string>random-generator" + " '[" + " _ _ _" + " [ [a,b] random present write ]" + " with-random-generator" + " ] [code] ;" +} +"For the second example, let's develop a Chloe tag which repeatedly renders its child several times, where the number comes from a form value. The tag will be used as follows:" +{ $code + "Hello world.
" +} +"This time, we cannot simply extract the " { $snippet "t:times" } " attribute at compile time since its value cannot be determined then. Instead, we execute " { $link compile-attr } " to generate code which pushes the value of that attribute on the stack. We then use " { $link process-children } " to compile child elements as a nested quotation which we apply " { $link times } " to." +{ $code + "CHLOE: repeat" + " [ \"times\" required-attr compile-attr ]" + " [ [ times ] process-children ]" + " bi ;" +} ; + +ARTICLE: "html.templates.chloe.extend.components.example" "An example of a custom Chloe component" +"As an example, let's develop a custom Chloe component which renders an image stored in a form value. Since the component does not require any configuration, we can define a singleton class:" +{ $code "SINGLETON: image" } +"Now we define a method on the " { $link render* } " generic word which renders the image using " { $vocab-link "html.elements" } ":" +{ $code "M: image render* 2drop ;" } +"Finally, we can define a Chloe component:" +{ $code "CHLOE-SINGLETON: image" } +"We can use it as follows, assuming the current form has a value named " { $snippet "image" } ":" +{ $code "" } ; + +ARTICLE: "html.templates.chloe.extend.components" "Extending Chloe with custom components" +"Custom HTML components implementing the " { $link render* } " word can be wired up with Chloe using the following syntax from " { $vocab-link "html.templates.chloe.components" } ":" +{ $subsection POSTPONE: CHLOE-SINGLETON: } +{ $subsection POSTPONE: CHLOE-TUPLE: } +{ $subsection "html.templates.chloe.extend.components.example" } ; + +ARTICLE: "html.templates.chloe" "Chloe templates" +"The " { $vocab-link "html.templates.chloe" } " vocabulary implements an XHTML templating engine. Unlike " { $vocab-link "html.templates.fhtml" } ", Chloe templates are always well-formed XML, and no Factor code can be embedded in them, enforcing proper separation of concerns. Chloe templates can be edited using standard XML editing tools; they are less flexible than FHTML, but often simpler as a result." +{ $subsection } +{ $subsection reset-cache } +{ $subsection "html.templates.chloe.tags" } +{ $subsection "html.templates.chloe.extend" } ; + +ABOUT: "html.templates.chloe" diff --git a/basis/html/templates/fhtml/fhtml-docs.factor b/basis/html/templates/fhtml/fhtml-docs.factor new file mode 100644 index 0000000000..3d2b2a2240 --- /dev/null +++ b/basis/html/templates/fhtml/fhtml-docs.factor @@ -0,0 +1,14 @@ +IN: html.templates.fhtml +USING: help.markup help.syntax ; + +HELP: ; + +ARTICLE: "html.templates.fhtml" "FHTML templates" +"The " { $vocab-link "html.templates.fhtml" } " vocabulary implements a templating engine which mixes markup with Factor code." +$nl +"FHTML provides an alternative to " { $vocab-link "html.templates.chloe" } " for situations where complex logic must be embedded in the presentation layer of a web application. While this is discouraged for larger applications, it is useful for prototyping as well as simpler applications." +$nl +"The entire syntax of an FHTML template can be summarized as thus: text outside of " { $snippet "<%" } " and " { $snippet "%>" } " is rendered literally. Text inside " { $snippet "<%" } " and " { $snippet "%>" } " is interpreted as Factor source code." +{ $subsection } ; + +ABOUT: "html.templates.fhtml" diff --git a/basis/html/templates/templates-docs.factor b/basis/html/templates/templates-docs.factor new file mode 100644 index 0000000000..ff53ca978a --- /dev/null +++ b/basis/html/templates/templates-docs.factor @@ -0,0 +1,89 @@ +IN: html.templates +USING: help.markup help.syntax io strings quotations xml.data +continuations urls ; + +HELP: template +{ $class-description "The class of HTML templates." } ; + +HELP: call-template* +{ $values { "template" template } } +{ $contract "Writes a template to " { $link output-stream } ", possibly using " { $vocab-link "html.forms" } " state." +$nl +"In addition to methods added by other vocabularies, this generic word has methods on the following classes:" +{ $list + { { $link string } " - the simplest type of template; simply written to " { $link output-stream } } + { { $link callable } " - a custom quotation, called to yield output" } + { { $link xml } " - written to " { $link output-stream } } + { "an input stream - copied to " { $link output-stream } } +} } ; + +HELP: call-template +{ $values { "template" template } } +{ $description "Writes a template to " { $link output-stream } ", possibly using " { $vocab-link "html.forms" } " state." +$nl +"This word calls " { $link call-template* } ", wrapping it in a " { $link recover } " form which improves error reporting by combining the underlying error with the template object." } ; + +HELP: set-title +{ $values { "string" string } } +{ $description "Sets the title of the current page. This is usually called by child templates, and a master template calls " { $link write-title } "." } ; + +HELP: write-title +{ $values { "string" string } } +{ $description "Writes the title of the current page, previously set by " { $link set-title } ". This is usually called by a master template after rendering a child template." } ; + +HELP: add-style +{ $values { "string" string } } +{ $description "Adds some CSS markup to the CSS stylesheet of a master template. Usually called by child templates which need to insert CSS style information in the " { $snippet "" } " tag of the resulting HTML page." } ; + +HELP: write-style +{ $description "Writes a CSS stylesheet assembled from " { $link add-style } " calls by child templates. Usually called by the master template to emit a CSS style in the " { $snippet "" } " tag of the resulting HTML page." } ; + +HELP: add-atom-feed +{ $values { "title" string } { "url" "a " { $link string } " or " { $link url } } } +{ $description "Adds an Atom feed link to the list of feeds in a master template. Usually called by child templates which need to insert an Atom feed link information in the " { $snippet "" } " tag of the resulting HTML page." } ; + +HELP: write-atom-feeds +{ $description "Writes a list of Atom feed links assembled from " { $link add-atom-feed } " calls by child templates. Usually called by the master template to emit a list of Atom feed links in the " { $snippet "" } " tag of the resulting HTML page." } ; + +HELP: nested-template? +{ $var-description "Set to a true value if the current call to " { $link call-template } " is nested inside a " { $link with-boilerplate } " and will therefore appear as part of another template. In this case, XML processing instructions and document type declarations should be omitted." } ; + +HELP: call-next-template +{ $description "Calls the next innermost child template from a master template. This is used to implement the " { $snippet "t:call-next-template" } " tag in the " { $vocab-link "html.templates.chloe" } " templating engine." } ; + +HELP: with-boilerplate +{ $values { "child" template } { "master" template } } +{ $description "Calls the child template, storing its output in a string, then calls the master template. The master template may call " { $link call-next-template } " to insert the output of the child template at any point; both templates may also use the master/child interface words documented in " { $link "html.templates.boilerplate" } "." } ; + +HELP: template-convert +{ $values { "template" template } { "output" "a pathname string" } } +{ $description "Calls the template and writes its output to a file with UTF8 encoding." } ; + +ARTICLE: "html.templates.boilerplate" "Boilerplate support" +"The following words define the interface between a templating engine and the " { $vocab-link "furnace.boilerplate" } " vocabulary." +$nl +"The master/child template interface follows a pattern where for each concept there is a word called by the child to store an entity, and another word to write the entity out; this solves the problem where certain HTML tags, such as " { $snippet "" } " and " { $snippet "<link>" } " must appear inside the " { $snippet "<head>" } " tag, even though those tags are usually precisely those that the child template will want to set." +{ $subsection set-title } +{ $subsection write-title } +{ $subsection add-style } +{ $subsection write-style } +{ $subsection add-atom-feed } +{ $subsection write-atom-feeds } +"Processing a master template with a child:" +{ $subsection with-boilerplate } +{ $subsection call-next-template } ; + +ARTICLE: "html.templates" "HTML template interface" +"The " { $vocab-link "html.templates" } " vocabulary implements an abstract interface to HTML templating engines. The " { $vocab-link "html.templates.fhtml" } " and " { $vocab-link "html.templates.chloe" } " vocabularies are two implementations of this." +$nl +"An HTML template is an instance of a mixin:" +{ $subsection template } +"HTML templates must also implement a method on a generic word:" +{ $subsection call-template* } +"Calling an HTML template:" +{ $subsection call-template } +"Usually HTML templates are invoked dynamically by the Furnace web framework and HTTP server. They can also be used in static HTML generation tools:" +{ $subsection template-convert } +{ $subsection "html.templates.boilerplate" } ; + +ABOUT: "html.templates" diff --git a/basis/html/templates/templates.factor b/basis/html/templates/templates.factor index de774f0864..57418a3e02 100644 --- a/basis/html/templates/templates.factor +++ b/basis/html/templates/templates.factor @@ -67,7 +67,7 @@ SYMBOL: next-template M: f call-template* drop call-next-template ; -: with-boilerplate ( body template -- ) +: with-boilerplate ( child master -- ) [ title [ <box> or ] change style [ SBUF" " clone or ] change From 018991f343751e9f41ecb5a15d69ad5f419a26c3 Mon Sep 17 00:00:00 2001 From: Slava Pestov <slava@slava-pestovs-macbook-pro.local> Date: Wed, 24 Sep 2008 00:45:28 -0500 Subject: [PATCH 13/16] More tags --- basis/channels/remote/tags.txt | 2 +- basis/channels/tags.txt | 2 +- basis/concurrency/combinators/tags.txt | 1 + basis/concurrency/conditions/tags.txt | 1 + basis/concurrency/count-downs/tags.txt | 1 + basis/concurrency/distributed/tags.txt | 2 +- basis/concurrency/exchangers/tags.txt | 1 + basis/concurrency/flags/tags.txt | 1 + basis/concurrency/futures/tags.txt | 1 + basis/concurrency/locks/tags.txt | 1 + basis/concurrency/mailboxes/tags.txt | 1 + basis/concurrency/messaging/tags.txt | 1 + basis/concurrency/promises/tags.txt | 1 + basis/concurrency/semaphores/tags.txt | 1 + basis/furnace/actions/tags.txt | 1 + basis/furnace/alloy/tags.txt | 1 + basis/furnace/asides/tags.txt | 1 + basis/furnace/auth/features/deactivate-user/tags.txt | 1 + basis/furnace/auth/features/edit-profile/tags.txt | 1 + basis/furnace/auth/features/recover-password/tags.txt | 1 + basis/furnace/auth/features/registration/tags.txt | 1 + basis/furnace/auth/login/permits/tags.txt | 1 + basis/furnace/auth/login/tags.txt | 1 + basis/furnace/auth/providers/db/tags.txt | 1 + basis/furnace/auth/providers/tags.txt | 1 + basis/furnace/auth/tags.txt | 1 + basis/furnace/boilerplate/tags.txt | 1 + basis/furnace/cache/tags.txt | 1 + basis/furnace/chloe-tags/tags.txt | 1 + basis/furnace/conversations/tags.txt | 1 + basis/furnace/db/tags.txt | 1 + basis/furnace/redirection/tags.txt | 1 + basis/furnace/referrer/tags.txt | 1 + basis/furnace/scopes/tags.txt | 1 + basis/furnace/sessions/tags.txt | 1 + basis/furnace/syndication/tags.txt | 1 + basis/furnace/tags.txt | 1 + basis/furnace/utilities/tags.txt | 1 + basis/http/server/dispatchers/tags.txt | 1 + basis/http/server/filters/tags.txt | 1 + basis/http/server/redirection/tags.txt | 1 + basis/http/server/remapping/tags.txt | 1 + basis/http/server/responses/tags.txt | 1 + basis/http/server/tags.txt | 2 +- basis/symbols/tags.txt | 1 + basis/validators/tags.txt | 1 + extra/webapps/blogs/tags.txt | 1 + extra/webapps/calculator/tags.txt | 1 + extra/webapps/counter/tags.txt | 1 + extra/webapps/pastebin/tags.txt | 1 + extra/webapps/planet/tags.txt | 1 + extra/webapps/todo/tags.txt | 1 + extra/webapps/user-admin/tags.txt | 1 + extra/webapps/wee-url/tags.txt | 1 + extra/webapps/wiki/tags.txt | 1 + 55 files changed, 55 insertions(+), 4 deletions(-) create mode 100644 basis/concurrency/combinators/tags.txt create mode 100644 basis/concurrency/conditions/tags.txt create mode 100644 basis/concurrency/count-downs/tags.txt create mode 100644 basis/concurrency/exchangers/tags.txt create mode 100644 basis/concurrency/flags/tags.txt create mode 100644 basis/concurrency/futures/tags.txt create mode 100644 basis/concurrency/locks/tags.txt create mode 100644 basis/concurrency/mailboxes/tags.txt create mode 100644 basis/concurrency/messaging/tags.txt create mode 100644 basis/concurrency/promises/tags.txt create mode 100644 basis/concurrency/semaphores/tags.txt create mode 100644 basis/furnace/actions/tags.txt create mode 100644 basis/furnace/alloy/tags.txt create mode 100644 basis/furnace/asides/tags.txt create mode 100644 basis/furnace/auth/features/deactivate-user/tags.txt create mode 100644 basis/furnace/auth/features/edit-profile/tags.txt create mode 100644 basis/furnace/auth/features/recover-password/tags.txt create mode 100644 basis/furnace/auth/features/registration/tags.txt create mode 100644 basis/furnace/auth/login/permits/tags.txt create mode 100644 basis/furnace/auth/login/tags.txt create mode 100644 basis/furnace/auth/providers/db/tags.txt create mode 100644 basis/furnace/auth/providers/tags.txt create mode 100644 basis/furnace/auth/tags.txt create mode 100644 basis/furnace/boilerplate/tags.txt create mode 100644 basis/furnace/cache/tags.txt create mode 100644 basis/furnace/chloe-tags/tags.txt create mode 100644 basis/furnace/conversations/tags.txt create mode 100644 basis/furnace/db/tags.txt create mode 100644 basis/furnace/redirection/tags.txt create mode 100644 basis/furnace/referrer/tags.txt create mode 100644 basis/furnace/scopes/tags.txt create mode 100644 basis/furnace/sessions/tags.txt create mode 100644 basis/furnace/syndication/tags.txt create mode 100644 basis/furnace/tags.txt create mode 100644 basis/furnace/utilities/tags.txt create mode 100644 basis/http/server/dispatchers/tags.txt create mode 100644 basis/http/server/filters/tags.txt create mode 100644 basis/http/server/redirection/tags.txt create mode 100644 basis/http/server/remapping/tags.txt create mode 100644 basis/http/server/responses/tags.txt create mode 100644 basis/symbols/tags.txt create mode 100644 basis/validators/tags.txt create mode 100644 extra/webapps/blogs/tags.txt create mode 100644 extra/webapps/calculator/tags.txt create mode 100644 extra/webapps/counter/tags.txt create mode 100644 extra/webapps/pastebin/tags.txt create mode 100644 extra/webapps/planet/tags.txt create mode 100644 extra/webapps/todo/tags.txt create mode 100644 extra/webapps/user-admin/tags.txt create mode 100644 extra/webapps/wee-url/tags.txt create mode 100644 extra/webapps/wiki/tags.txt diff --git a/basis/channels/remote/tags.txt b/basis/channels/remote/tags.txt index f4274299b1..ce745d18c6 100644 --- a/basis/channels/remote/tags.txt +++ b/basis/channels/remote/tags.txt @@ -1 +1 @@ -extensions +concurrency diff --git a/basis/channels/tags.txt b/basis/channels/tags.txt index f4274299b1..ce745d18c6 100644 --- a/basis/channels/tags.txt +++ b/basis/channels/tags.txt @@ -1 +1 @@ -extensions +concurrency diff --git a/basis/concurrency/combinators/tags.txt b/basis/concurrency/combinators/tags.txt new file mode 100644 index 0000000000..ce745d18c6 --- /dev/null +++ b/basis/concurrency/combinators/tags.txt @@ -0,0 +1 @@ +concurrency diff --git a/basis/concurrency/conditions/tags.txt b/basis/concurrency/conditions/tags.txt new file mode 100644 index 0000000000..ce745d18c6 --- /dev/null +++ b/basis/concurrency/conditions/tags.txt @@ -0,0 +1 @@ +concurrency diff --git a/basis/concurrency/count-downs/tags.txt b/basis/concurrency/count-downs/tags.txt new file mode 100644 index 0000000000..ce745d18c6 --- /dev/null +++ b/basis/concurrency/count-downs/tags.txt @@ -0,0 +1 @@ +concurrency diff --git a/basis/concurrency/distributed/tags.txt b/basis/concurrency/distributed/tags.txt index 50cfa263f6..b7861c6689 100644 --- a/basis/concurrency/distributed/tags.txt +++ b/basis/concurrency/distributed/tags.txt @@ -1,2 +1,2 @@ +concurrency enterprise -extensions diff --git a/basis/concurrency/exchangers/tags.txt b/basis/concurrency/exchangers/tags.txt new file mode 100644 index 0000000000..ce745d18c6 --- /dev/null +++ b/basis/concurrency/exchangers/tags.txt @@ -0,0 +1 @@ +concurrency diff --git a/basis/concurrency/flags/tags.txt b/basis/concurrency/flags/tags.txt new file mode 100644 index 0000000000..ce745d18c6 --- /dev/null +++ b/basis/concurrency/flags/tags.txt @@ -0,0 +1 @@ +concurrency diff --git a/basis/concurrency/futures/tags.txt b/basis/concurrency/futures/tags.txt new file mode 100644 index 0000000000..ce745d18c6 --- /dev/null +++ b/basis/concurrency/futures/tags.txt @@ -0,0 +1 @@ +concurrency diff --git a/basis/concurrency/locks/tags.txt b/basis/concurrency/locks/tags.txt new file mode 100644 index 0000000000..ce745d18c6 --- /dev/null +++ b/basis/concurrency/locks/tags.txt @@ -0,0 +1 @@ +concurrency diff --git a/basis/concurrency/mailboxes/tags.txt b/basis/concurrency/mailboxes/tags.txt new file mode 100644 index 0000000000..ce745d18c6 --- /dev/null +++ b/basis/concurrency/mailboxes/tags.txt @@ -0,0 +1 @@ +concurrency diff --git a/basis/concurrency/messaging/tags.txt b/basis/concurrency/messaging/tags.txt new file mode 100644 index 0000000000..ce745d18c6 --- /dev/null +++ b/basis/concurrency/messaging/tags.txt @@ -0,0 +1 @@ +concurrency diff --git a/basis/concurrency/promises/tags.txt b/basis/concurrency/promises/tags.txt new file mode 100644 index 0000000000..ce745d18c6 --- /dev/null +++ b/basis/concurrency/promises/tags.txt @@ -0,0 +1 @@ +concurrency diff --git a/basis/concurrency/semaphores/tags.txt b/basis/concurrency/semaphores/tags.txt new file mode 100644 index 0000000000..ce745d18c6 --- /dev/null +++ b/basis/concurrency/semaphores/tags.txt @@ -0,0 +1 @@ +concurrency diff --git a/basis/furnace/actions/tags.txt b/basis/furnace/actions/tags.txt new file mode 100644 index 0000000000..c0772185a0 --- /dev/null +++ b/basis/furnace/actions/tags.txt @@ -0,0 +1 @@ +web diff --git a/basis/furnace/alloy/tags.txt b/basis/furnace/alloy/tags.txt new file mode 100644 index 0000000000..c0772185a0 --- /dev/null +++ b/basis/furnace/alloy/tags.txt @@ -0,0 +1 @@ +web diff --git a/basis/furnace/asides/tags.txt b/basis/furnace/asides/tags.txt new file mode 100644 index 0000000000..c0772185a0 --- /dev/null +++ b/basis/furnace/asides/tags.txt @@ -0,0 +1 @@ +web diff --git a/basis/furnace/auth/features/deactivate-user/tags.txt b/basis/furnace/auth/features/deactivate-user/tags.txt new file mode 100644 index 0000000000..c0772185a0 --- /dev/null +++ b/basis/furnace/auth/features/deactivate-user/tags.txt @@ -0,0 +1 @@ +web diff --git a/basis/furnace/auth/features/edit-profile/tags.txt b/basis/furnace/auth/features/edit-profile/tags.txt new file mode 100644 index 0000000000..c0772185a0 --- /dev/null +++ b/basis/furnace/auth/features/edit-profile/tags.txt @@ -0,0 +1 @@ +web diff --git a/basis/furnace/auth/features/recover-password/tags.txt b/basis/furnace/auth/features/recover-password/tags.txt new file mode 100644 index 0000000000..c0772185a0 --- /dev/null +++ b/basis/furnace/auth/features/recover-password/tags.txt @@ -0,0 +1 @@ +web diff --git a/basis/furnace/auth/features/registration/tags.txt b/basis/furnace/auth/features/registration/tags.txt new file mode 100644 index 0000000000..c0772185a0 --- /dev/null +++ b/basis/furnace/auth/features/registration/tags.txt @@ -0,0 +1 @@ +web diff --git a/basis/furnace/auth/login/permits/tags.txt b/basis/furnace/auth/login/permits/tags.txt new file mode 100644 index 0000000000..c0772185a0 --- /dev/null +++ b/basis/furnace/auth/login/permits/tags.txt @@ -0,0 +1 @@ +web diff --git a/basis/furnace/auth/login/tags.txt b/basis/furnace/auth/login/tags.txt new file mode 100644 index 0000000000..c0772185a0 --- /dev/null +++ b/basis/furnace/auth/login/tags.txt @@ -0,0 +1 @@ +web diff --git a/basis/furnace/auth/providers/db/tags.txt b/basis/furnace/auth/providers/db/tags.txt new file mode 100644 index 0000000000..c0772185a0 --- /dev/null +++ b/basis/furnace/auth/providers/db/tags.txt @@ -0,0 +1 @@ +web diff --git a/basis/furnace/auth/providers/tags.txt b/basis/furnace/auth/providers/tags.txt new file mode 100644 index 0000000000..c0772185a0 --- /dev/null +++ b/basis/furnace/auth/providers/tags.txt @@ -0,0 +1 @@ +web diff --git a/basis/furnace/auth/tags.txt b/basis/furnace/auth/tags.txt new file mode 100644 index 0000000000..c0772185a0 --- /dev/null +++ b/basis/furnace/auth/tags.txt @@ -0,0 +1 @@ +web diff --git a/basis/furnace/boilerplate/tags.txt b/basis/furnace/boilerplate/tags.txt new file mode 100644 index 0000000000..c0772185a0 --- /dev/null +++ b/basis/furnace/boilerplate/tags.txt @@ -0,0 +1 @@ +web diff --git a/basis/furnace/cache/tags.txt b/basis/furnace/cache/tags.txt new file mode 100644 index 0000000000..c0772185a0 --- /dev/null +++ b/basis/furnace/cache/tags.txt @@ -0,0 +1 @@ +web diff --git a/basis/furnace/chloe-tags/tags.txt b/basis/furnace/chloe-tags/tags.txt new file mode 100644 index 0000000000..c0772185a0 --- /dev/null +++ b/basis/furnace/chloe-tags/tags.txt @@ -0,0 +1 @@ +web diff --git a/basis/furnace/conversations/tags.txt b/basis/furnace/conversations/tags.txt new file mode 100644 index 0000000000..c0772185a0 --- /dev/null +++ b/basis/furnace/conversations/tags.txt @@ -0,0 +1 @@ +web diff --git a/basis/furnace/db/tags.txt b/basis/furnace/db/tags.txt new file mode 100644 index 0000000000..c0772185a0 --- /dev/null +++ b/basis/furnace/db/tags.txt @@ -0,0 +1 @@ +web diff --git a/basis/furnace/redirection/tags.txt b/basis/furnace/redirection/tags.txt new file mode 100644 index 0000000000..c0772185a0 --- /dev/null +++ b/basis/furnace/redirection/tags.txt @@ -0,0 +1 @@ +web diff --git a/basis/furnace/referrer/tags.txt b/basis/furnace/referrer/tags.txt new file mode 100644 index 0000000000..c0772185a0 --- /dev/null +++ b/basis/furnace/referrer/tags.txt @@ -0,0 +1 @@ +web diff --git a/basis/furnace/scopes/tags.txt b/basis/furnace/scopes/tags.txt new file mode 100644 index 0000000000..c0772185a0 --- /dev/null +++ b/basis/furnace/scopes/tags.txt @@ -0,0 +1 @@ +web diff --git a/basis/furnace/sessions/tags.txt b/basis/furnace/sessions/tags.txt new file mode 100644 index 0000000000..c0772185a0 --- /dev/null +++ b/basis/furnace/sessions/tags.txt @@ -0,0 +1 @@ +web diff --git a/basis/furnace/syndication/tags.txt b/basis/furnace/syndication/tags.txt new file mode 100644 index 0000000000..c0772185a0 --- /dev/null +++ b/basis/furnace/syndication/tags.txt @@ -0,0 +1 @@ +web diff --git a/basis/furnace/tags.txt b/basis/furnace/tags.txt new file mode 100644 index 0000000000..c0772185a0 --- /dev/null +++ b/basis/furnace/tags.txt @@ -0,0 +1 @@ +web diff --git a/basis/furnace/utilities/tags.txt b/basis/furnace/utilities/tags.txt new file mode 100644 index 0000000000..c0772185a0 --- /dev/null +++ b/basis/furnace/utilities/tags.txt @@ -0,0 +1 @@ +web diff --git a/basis/http/server/dispatchers/tags.txt b/basis/http/server/dispatchers/tags.txt new file mode 100644 index 0000000000..c0772185a0 --- /dev/null +++ b/basis/http/server/dispatchers/tags.txt @@ -0,0 +1 @@ +web diff --git a/basis/http/server/filters/tags.txt b/basis/http/server/filters/tags.txt new file mode 100644 index 0000000000..c0772185a0 --- /dev/null +++ b/basis/http/server/filters/tags.txt @@ -0,0 +1 @@ +web diff --git a/basis/http/server/redirection/tags.txt b/basis/http/server/redirection/tags.txt new file mode 100644 index 0000000000..c0772185a0 --- /dev/null +++ b/basis/http/server/redirection/tags.txt @@ -0,0 +1 @@ +web diff --git a/basis/http/server/remapping/tags.txt b/basis/http/server/remapping/tags.txt new file mode 100644 index 0000000000..c0772185a0 --- /dev/null +++ b/basis/http/server/remapping/tags.txt @@ -0,0 +1 @@ +web diff --git a/basis/http/server/responses/tags.txt b/basis/http/server/responses/tags.txt new file mode 100644 index 0000000000..c0772185a0 --- /dev/null +++ b/basis/http/server/responses/tags.txt @@ -0,0 +1 @@ +web diff --git a/basis/http/server/tags.txt b/basis/http/server/tags.txt index b0881a9ec0..b822da1665 100644 --- a/basis/http/server/tags.txt +++ b/basis/http/server/tags.txt @@ -1,3 +1,3 @@ +web enterprise network -web diff --git a/basis/symbols/tags.txt b/basis/symbols/tags.txt new file mode 100644 index 0000000000..f4274299b1 --- /dev/null +++ b/basis/symbols/tags.txt @@ -0,0 +1 @@ +extensions diff --git a/basis/validators/tags.txt b/basis/validators/tags.txt new file mode 100644 index 0000000000..c0772185a0 --- /dev/null +++ b/basis/validators/tags.txt @@ -0,0 +1 @@ +web diff --git a/extra/webapps/blogs/tags.txt b/extra/webapps/blogs/tags.txt new file mode 100644 index 0000000000..c0772185a0 --- /dev/null +++ b/extra/webapps/blogs/tags.txt @@ -0,0 +1 @@ +web diff --git a/extra/webapps/calculator/tags.txt b/extra/webapps/calculator/tags.txt new file mode 100644 index 0000000000..c0772185a0 --- /dev/null +++ b/extra/webapps/calculator/tags.txt @@ -0,0 +1 @@ +web diff --git a/extra/webapps/counter/tags.txt b/extra/webapps/counter/tags.txt new file mode 100644 index 0000000000..c0772185a0 --- /dev/null +++ b/extra/webapps/counter/tags.txt @@ -0,0 +1 @@ +web diff --git a/extra/webapps/pastebin/tags.txt b/extra/webapps/pastebin/tags.txt new file mode 100644 index 0000000000..c0772185a0 --- /dev/null +++ b/extra/webapps/pastebin/tags.txt @@ -0,0 +1 @@ +web diff --git a/extra/webapps/planet/tags.txt b/extra/webapps/planet/tags.txt new file mode 100644 index 0000000000..c0772185a0 --- /dev/null +++ b/extra/webapps/planet/tags.txt @@ -0,0 +1 @@ +web diff --git a/extra/webapps/todo/tags.txt b/extra/webapps/todo/tags.txt new file mode 100644 index 0000000000..c0772185a0 --- /dev/null +++ b/extra/webapps/todo/tags.txt @@ -0,0 +1 @@ +web diff --git a/extra/webapps/user-admin/tags.txt b/extra/webapps/user-admin/tags.txt new file mode 100644 index 0000000000..c0772185a0 --- /dev/null +++ b/extra/webapps/user-admin/tags.txt @@ -0,0 +1 @@ +web diff --git a/extra/webapps/wee-url/tags.txt b/extra/webapps/wee-url/tags.txt new file mode 100644 index 0000000000..c0772185a0 --- /dev/null +++ b/extra/webapps/wee-url/tags.txt @@ -0,0 +1 @@ +web diff --git a/extra/webapps/wiki/tags.txt b/extra/webapps/wiki/tags.txt new file mode 100644 index 0000000000..c0772185a0 --- /dev/null +++ b/extra/webapps/wiki/tags.txt @@ -0,0 +1 @@ +web From 4b58f0b6230959d8086873a99040fd14c49fc126 Mon Sep 17 00:00:00 2001 From: Slava Pestov <slava@slava-pestovs-macbook-pro.local> Date: Wed, 24 Sep 2008 00:45:39 -0500 Subject: [PATCH 14/16] Document validators --- basis/validators/validators-docs.factor | 110 ++++++++++++++++++++++++ basis/validators/validators.factor | 6 +- 2 files changed, 113 insertions(+), 3 deletions(-) create mode 100644 basis/validators/validators-docs.factor diff --git a/basis/validators/validators-docs.factor b/basis/validators/validators-docs.factor new file mode 100644 index 0000000000..fc16c48ca0 --- /dev/null +++ b/basis/validators/validators-docs.factor @@ -0,0 +1,110 @@ +USING: help.markup help.syntax io.streams.string quotations +strings math parser-combinators.regexp ; +IN: validators + +HELP: v-captcha +{ $values { "str" string } } +{ $description "Throws a validation error if the string is non-empty. This is used to create bait fields for spam-bots to fill in." } ; + +HELP: v-credit-card +{ $values { "str" string } { "n" integer } } +{ $description "If the credit card number passes the Luhn algorithm, converts it to an integer, otherwise throws an error." } +{ $notes "See " { $url "http://en.wikipedia.org/wiki/Luhn_algorithm" } " for a description of this algorithm." } ; + +HELP: v-default +{ $values { "str" string } { "def" string } { "str/def" string } } +{ $description "If the input string is not specified, replaces it with the default value." } ; + +HELP: v-email +{ $values { "str" string } } +{ $description "Throws a validation error if the string is not a valid e-mail address, as determined by a regular expression." } ; + +HELP: v-integer +{ $values { "str" string } { "n" integer } } +{ $description "Converts the string into an integer, throwing a validation error if the string is not a valid integer." } ; + +HELP: v-min-length +{ $values { "str" string } { "n" integer } } +{ $description "Throws a validation error if the string is shorter than " { $snippet "n" } " characters." } ; + +HELP: v-max-length +{ $values { "str" string } { "n" integer } } +{ $description "Throws a validation error if the string is longer than " { $snippet "n" } " characters." } ; + +HELP: v-max-value +{ $values { "x" integer } { "n" integer } } +{ $description "Throws an error if " { $snippet "x" } " is larger than " { $snippet "n" } "." } ; + +HELP: v-min-value +{ $values { "x" integer } { "n" integer } } +{ $description "Throws an error if " { $snippet "x" } " is smaller than " { $snippet "n" } "." } ; + +HELP: v-mode +{ $values { "str" string } } +{ $description "Throws an error if " { $snippet "str" } " is not a valid XMode mode name." } ; + +HELP: v-number +{ $values { "str" string } { "n" real } } +{ $description "Converts the string into a real number, throwing a validation error if the string is not a valid real number." } ; + +HELP: v-one-line +{ $values { "str" string } } +{ $description "Throws a validation error if the string contains line breaks." } ; + +HELP: v-one-word +{ $values { "str" string } } +{ $description "Throws a validation error if the string contains word breaks." } ; + +HELP: v-optional +{ $values { "str" string } { "quot" quotation } { "result" string } } +{ $description "If the string is non-empty, applies the quotation to the string, otherwise outputs the empty string." } ; + +HELP: v-password +{ $values { "str" string } } +{ $description "A reasonable default validator for passwords." } ; + +HELP: v-regexp +{ $values { "str" string } { "what" string } { "regexp" regexp } } +{ $description "Throws a validation error that " { $snippet "what" } " failed if the string does not match the regular expression." } ; + +HELP: v-required +{ $values { "str" string } } +{ $description "Throws a validation error if the string is empty." } ; + +HELP: v-url +{ $values { "str" string } } +{ $description "Throws an error if the string is not a valid URL, as determined by a regular expression." } ; + +HELP: v-username +{ $values { "str" string } } +{ $description "A reasonable default validator for usernames." } ; + +ARTICLE: "validators" "Form validators" +"The " { $vocab-link "validators" } " vocabulary provides a set of words which are intended to be used with the form validation functionality offered by " { $vocab-link "furnace.actions" } ". They can also be used independently of the web framework." +$nl +"Note that validators which take numbers must be preceded by " { $link v-integer } " or " { $link v-number } " if the original input is a string." +$nl +"Higher-order validators which require additional parameters:" +{ $subsection v-default } +{ $subsection v-optional } +{ $subsection v-min-length } +{ $subsection v-max-length } +{ $subsection v-min-value } +{ $subsection v-max-value } +{ $subsection v-regexp } +"Simple validators:" +{ $subsection v-required } +{ $subsection v-number } +{ $subsection v-integer } +{ $subsection v-one-line } +{ $subsection v-one-word } +{ $subsection v-captcha } +"More complex validators:" +{ $subsection v-email } +{ $subsection v-url } +{ $subsection v-username } +{ $subsection v-password } +{ $subsection v-credit-card } +{ $subsection v-mode } ; + +ABOUT: "validators" diff --git a/basis/validators/validators.factor b/basis/validators/validators.factor index dab109e368..30e1eadc7a 100644 --- a/basis/validators/validators.factor +++ b/basis/validators/validators.factor @@ -6,13 +6,13 @@ unicode.categories arrays hashtables words classes quotations xmode.catalog ; IN: validators -: v-default ( str def -- str ) +: v-default ( str def -- str/def ) over empty? spin ? ; : v-required ( str -- str ) dup empty? [ "required" throw ] when ; -: v-optional ( str quot -- str ) +: v-optional ( str quot -- result ) over empty? [ 2drop f ] [ call ] if ; inline : v-min-length ( str n -- str ) @@ -91,7 +91,7 @@ IN: validators "not a valid syntax mode" throw ] unless ; -: luhn? ( n -- ? ) +: luhn? ( str -- ? ) string>digits <reversed> [ odd? [ 2 * 10 /mod + ] when ] map-index sum 10 mod 0 = ; From c03d4ff7d692b12521785dde9758af0845c06e4d Mon Sep 17 00:00:00 2001 From: Slava Pestov <slava@slava-pestovs-macbook-pro.local> Date: Wed, 24 Sep 2008 00:45:49 -0500 Subject: [PATCH 15/16] Better help.lint, fix some typos --- basis/help/cookbook/cookbook.factor | 6 +++--- basis/help/handbook/handbook.factor | 13 +++++++------ basis/help/lint/lint.factor | 20 ++++++++++++++------ basis/html/components/components.factor | 2 +- basis/html/forms/forms-docs.factor | 1 + basis/html/streams/streams-docs.factor | 1 + basis/html/templates/templates-docs.factor | 1 - 7 files changed, 27 insertions(+), 17 deletions(-) diff --git a/basis/help/cookbook/cookbook.factor b/basis/help/cookbook/cookbook.factor index aef6ce6809..9fb837a873 100755 --- a/basis/help/cookbook/cookbook.factor +++ b/basis/help/cookbook/cookbook.factor @@ -312,13 +312,13 @@ ARTICLE: "cookbook-pitfalls" "Pitfalls to avoid" { "When a source file uses two vocabularies which define words with the same name, the order of the vocabularies in the " { $link POSTPONE: USE: } " or " { $link POSTPONE: USING: } " forms is important. The parser prints warnings when vocabularies shadow words from other vocabularies; see " { $link "vocabulary-search-shadow" } ". The " { $vocab-link "qualified" } " vocabulary implements qualified naming, which can be used to resolve ambiguities." } { "If a literal object appears in a word definition, the object itself is pushed on the stack when the word executes, not a copy. If you intend to mutate this object, you must " { $link clone } " it first. See " { $link "syntax-literals" } "." } { "For a discussion of potential issues surrounding the " { $link f } " object, see " { $link "booleans" } "." } - { "Factor's object system is quite flexible. Careless usage of union, mixin and predicate classes can lead to similar problems to those caused by ``multiple inheritance'' in other languages. In particular, it is possible to have two classes such that they have a non-empty intersection and yet neither is a subclass of the other. If a generic word defines methods on two such classes, method precedence is undefined for objects that are instances of both classes. See " { $link "method-order" } " for details." } + { "Factor's object system is quite flexible. Careless usage of union, mixin and predicate classes can lead to similar problems to those caused by ``multiple inheritance'' in other languages. In particular, it is possible to have two classes such that they have a non-empty intersection and yet neither is a subclass of the other. If a generic word defines methods on two such classes, various disambiguation rules are applied to ensure method dispatch remains deterministic, however they may not be what you expect. See " { $link "method-order" } " for details." } { "Performance-sensitive code should have a static stack effect so that it can be compiled by the optimizing word compiler, which generates more efficient code than the non-optimizing quotation compiler. See " { $link "inference" } " and " { $link "compiler" } "." $nl "This means that methods defined on performance sensitive, frequently-called core generic words such as " { $link nth } " should have static stack effects which are consistent with each other, since a generic word will only have a static stack effect if all methods do." $nl - "Unit tests for the " { $vocab-link "inference" } " vocabulary can be used to ensure that any methods your vocabulary defines on core generic words have static stack effects:" - { $code "\"inference\" test" } + "Unit tests for the " { $vocab-link "stack-checker" } " vocabulary can be used to ensure that any methods your vocabulary defines on core generic words have static stack effects:" + { $code "\"stack-checker\" test" } "In general, you should strive to write code with inferable stack effects, even for sections of a program which are not performance sensitive; the " { $link infer. } " tool together with the optimizing compiler's error reporting can catch many bugs ahead of time." } { "Be careful when calling words which access variables from a " { $link make-assoc } " which constructs an assoc with arbitrary keys, since those keys might shadow variables." } { "If " { $link run-file } " throws a stack depth assertion, it means that the top-level form in the file left behind values on the stack. The stack depth is compared before and after loading a source file, since this type of situation is almost always an error. If you have a legitimate need to load a source file which returns data in some manner, define a word in the source file which produces this data on the stack and call the word after loading the file." } diff --git a/basis/help/handbook/handbook.factor b/basis/help/handbook/handbook.factor index 4e136d81c2..51750d772f 100755 --- a/basis/help/handbook/handbook.factor +++ b/basis/help/handbook/handbook.factor @@ -1,10 +1,10 @@ USING: help help.markup help.syntax help.definitions help.topics namespaces words sequences classes assocs vocabs kernel arrays prettyprint.backend kernel.private io generic math system -strings sbufs vectors byte-arrays -quotations io.streams.byte-array -classes.builtin parser lexer classes.predicate classes.union -classes.intersection classes.singleton classes.tuple ; +strings sbufs vectors byte-arrays quotations +io.streams.byte-array classes.builtin parser lexer +classes.predicate classes.union classes.intersection +classes.singleton classes.tuple tools.vocabs.browser ; IN: help.handbook ARTICLE: "conventions" "Conventions" @@ -139,7 +139,7 @@ ARTICLE: "collections" "Collections" { $subsection "heaps" } { $subsection "graphs" } { $subsection "buffers" } -"There are many other collections in " { $snippet "extra/" } ", such as " { $vocab-link "disjoint-sets" } ", " { $vocab-link "persistent-vectors" } ", and " { $vocab-link "tuple-arrays" } "." ; +"There are also many other vocabularies tagged " { $link T{ vocab-tag { name "collections" } } } " in the library." ; USING: io.encodings.utf8 io.encodings.utf16 io.encodings.binary io.encodings.ascii io.files ; @@ -244,7 +244,8 @@ ARTICLE: "handbook-language-reference" "Language reference" { $subsection "program-org" } { $subsection "numbers" } { $subsection "collections" } -{ $subsection "io" } ; +{ $subsection "io" } +"Vocabularies tagged " { $link T{ vocab-tag { name "extensions" } } } " implement various additional language abstractions." ; ARTICLE: "handbook-environment-reference" "Environment reference" { $subsection "prettyprint" } diff --git a/basis/help/lint/lint.factor b/basis/help/lint/lint.factor index d49262e7c8..be6206f59c 100755 --- a/basis/help/lint/lint.factor +++ b/basis/help/lint/lint.factor @@ -61,10 +61,10 @@ IN: help.lint : vocab-exists? ( name -- ? ) dup vocab swap "all-vocabs" get member? or ; -: check-modules ( word element -- ) - nip \ $vocab-link swap elements [ +: check-modules ( element -- ) + \ $vocab-link swap elements [ second - vocab-exists? [ "Missing vocabulary" throw ] unless + vocab-exists? [ "$vocab-link to non-existent vocabulary" throw ] unless ] each ; : check-rendering ( word element -- ) @@ -91,7 +91,7 @@ M: help-error error. 2dup check-examples 2dup check-values 2dup check-see-also - 2dup check-modules + 2dup nip check-modules 2dup drop check-rendering ] assert-depth 2drop ] check-something @@ -101,12 +101,20 @@ M: help-error error. : check-article ( article -- ) [ - [ dup check-rendering ] assert-depth drop + dup article-content [ + 2dup check-modules check-rendering + ] assert-depth 2drop ] check-something ; +: files>vocabs ( -- assoc ) + vocabs + [ [ [ vocab-docs-path ] keep ] H{ } map>assoc ] + [ [ [ vocab-source-path ] keep ] H{ } map>assoc ] + bi assoc-union ; + : group-articles ( -- assoc ) articles get keys - vocabs [ dup vocab-docs-path swap ] H{ } map>assoc + files>vocabs H{ } clone [ '[ dup >link where dup diff --git a/basis/html/components/components.factor b/basis/html/components/components.factor index b78e3473a7..18e1aad9eb 100644 --- a/basis/html/components/components.factor +++ b/basis/html/components/components.factor @@ -9,7 +9,7 @@ xmode.code2html lcs.diff2html farkup html.elements html.streams html.forms ; IN: html.components -GENERIC: render* ( value name render -- ) +GENERIC: render* ( value name renderer -- ) : render ( name renderer -- ) prepare-value diff --git a/basis/html/forms/forms-docs.factor b/basis/html/forms/forms-docs.factor index 7a2134c996..6556d2eac2 100644 --- a/basis/html/forms/forms-docs.factor +++ b/basis/html/forms/forms-docs.factor @@ -73,6 +73,7 @@ HELP: with-each-value { $notes "This word is used to implement the " { $snippet "t:each" } " tag of the " { $vocab-link "html.templates.chloe" } " templating system. It can also be called directly from " { $vocab-link "html.templates.fhtml" } " templates." } ; HELP: with-each-object +{ $values { "name" string } { "quot" quotation } } { $description "Calls the quotation with each element of the value named " { $snippet "name" } "; the value must be a sequence. The quotation is called in a new dynamic scope where the object's slots become named values, as if " { $link from-object } " was called." } { $notes "This word is used to implement the " { $snippet "t:bind-each" } " tag of the " { $vocab-link "html.templates.chloe" } " templating system. It can also be called directly from " { $vocab-link "html.templates.fhtml" } " templates." } ; diff --git a/basis/html/streams/streams-docs.factor b/basis/html/streams/streams-docs.factor index 7c5bea805d..d7638a2817 100644 --- a/basis/html/streams/streams-docs.factor +++ b/basis/html/streams/streams-docs.factor @@ -18,6 +18,7 @@ HELP: with-html-stream { $description "Calls the quotation in a new dynamic scope with " { $link output-stream } " rebound to an " { $link html-stream } " wrapping the current " { $link output-stream } "." } { $examples { $example + "USING: io io.styles html.streams ;" "[ \"Hello\" { { font-style bold } } format nl ] with-html-stream" "<span style='font-style: normal; font-weight: bold; '>Hello</span><br/>" } diff --git a/basis/html/templates/templates-docs.factor b/basis/html/templates/templates-docs.factor index ff53ca978a..3251b46b3e 100644 --- a/basis/html/templates/templates-docs.factor +++ b/basis/html/templates/templates-docs.factor @@ -28,7 +28,6 @@ HELP: set-title { $description "Sets the title of the current page. This is usually called by child templates, and a master template calls " { $link write-title } "." } ; HELP: write-title -{ $values { "string" string } } { $description "Writes the title of the current page, previously set by " { $link set-title } ". This is usually called by a master template after rendering a child template." } ; HELP: add-style From 4b19afdb4e0b4bec6bbd77ce18d218d025ffe9c5 Mon Sep 17 00:00:00 2001 From: Slava Pestov <slava@slava-pestovs-macbook-pro.local> Date: Wed, 24 Sep 2008 01:59:05 -0500 Subject: [PATCH 16/16] Fixing issues found by stricter help lint --- basis/ascii/ascii-docs.factor | 2 +- basis/cocoa/cocoa-docs.factor | 2 +- basis/compiler/generator/generator-docs.factor | 2 +- basis/io/buffers/buffers-docs.factor | 2 +- basis/io/styles/styles-docs.factor | 2 +- basis/logging/analysis/analysis-docs.factor | 2 +- basis/logging/logging-docs.factor | 2 +- core/strings/strings-docs.factor | 3 ++- extra/printf/printf-docs.factor | 2 +- extra/wordtimer/wordtimer-docs.factor | 2 +- 10 files changed, 11 insertions(+), 10 deletions(-) diff --git a/basis/ascii/ascii-docs.factor b/basis/ascii/ascii-docs.factor index 75af8a7102..6af697cf89 100755 --- a/basis/ascii/ascii-docs.factor +++ b/basis/ascii/ascii-docs.factor @@ -46,6 +46,6 @@ ARTICLE: "ascii" "ASCII character classes" { $subsection printable? } { $subsection control? } { $subsection quotable? } -"Modern applications should use Unicode 5.0 instead (" { $vocab-link "unicode" } ")." ; +"Modern applications should use Unicode 5.0 instead (" { $vocab-link "unicode.categories" } ")." ; ABOUT: "ascii" diff --git a/basis/cocoa/cocoa-docs.factor b/basis/cocoa/cocoa-docs.factor index 01b0809f37..a971288251 100644 --- a/basis/cocoa/cocoa-docs.factor +++ b/basis/cocoa/cocoa-docs.factor @@ -19,7 +19,7 @@ HELP: SUPER-> ARTICLE: "objc-calling" "Calling Objective C code" "Before an Objective C class can be used, it must be imported; by default, a small set of common classes are imported automatically, but additional classes can be imported as needed." { $subsection import-objc-class } -"Every imported Objective C class has as corresponding class word in the " { $vocab-link "objc-classes" } " vocabulary. Class words push the class object in the stack, allowing class methods to be invoked." +"Every imported Objective C class has as corresponding class word in the " { $vocab-link "cocoa.classes" } " vocabulary. Class words push the class object in the stack, allowing class methods to be invoked." $nl "Messages can be sent to classes and instances using a pair of parsing words:" { $subsection POSTPONE: -> } diff --git a/basis/compiler/generator/generator-docs.factor b/basis/compiler/generator/generator-docs.factor index 45238ab00a..5d485b13d4 100755 --- a/basis/compiler/generator/generator-docs.factor +++ b/basis/compiler/generator/generator-docs.factor @@ -4,7 +4,7 @@ kernel vectors arrays effects sequences ; IN: compiler.generator ARTICLE: "generator" "Compiled code generator" -"Most of the words in the " { $vocab-link "generator" } " vocabulary are internal to the compiler and user code has no reason to call them." +"Most of the words in the " { $vocab-link "compiler.generator" } " vocabulary are internal to the compiler and user code has no reason to call them." $nl "Debugging information can be enabled or disabled; this hook is used by " { $link "tools.deploy" } ":" { $subsection compiled-stack-traces? } diff --git a/basis/io/buffers/buffers-docs.factor b/basis/io/buffers/buffers-docs.factor index fbe352185c..5ab25b9c31 100755 --- a/basis/io/buffers/buffers-docs.factor +++ b/basis/io/buffers/buffers-docs.factor @@ -8,7 +8,7 @@ $nl $nl "Buffers are used to implement native I/O backends." $nl -"Buffer words are found in the " { $vocab-link "buffers" } " vocabulary." +"Buffer words are found in the " { $vocab-link "io.buffers" } " vocabulary." { $subsection buffer } { $subsection <buffer> } "Buffers must be manually deallocated by calling " { $link dispose } "." diff --git a/basis/io/styles/styles-docs.factor b/basis/io/styles/styles-docs.factor index 48b72255a7..febec6573a 100644 --- a/basis/io/styles/styles-docs.factor +++ b/basis/io/styles/styles-docs.factor @@ -36,7 +36,7 @@ ARTICLE: "presentations" "Presentations" ARTICLE: "styles" "Formatted output" "The " { $link stream-format } ", " { $link with-style } ", " { $link with-nesting } " and " { $link tabular-output } " words take a hashtable of style attributes. Output stream implementations are free to ignore style information." $nl -"Style hashtables are keyed by symbols from the " { $vocab-link "styles" } " vocabulary." +"Style hashtables are keyed by symbols from the " { $vocab-link "io.styles" } " vocabulary." { $subsection "character-styles" } { $subsection "paragraph-styles" } { $subsection "table-styles" } diff --git a/basis/logging/analysis/analysis-docs.factor b/basis/logging/analysis/analysis-docs.factor index 10b6924b52..98ad28e4f6 100644 --- a/basis/logging/analysis/analysis-docs.factor +++ b/basis/logging/analysis/analysis-docs.factor @@ -20,7 +20,7 @@ HELP: analyze-log { $description "Analyzes a log file and prints a formatted report. The " { $snippet "word-names" } " parameter is documented in " { $link analyze-entries } "." } ; ARTICLE: "logging.analysis" "Log analysis" -"The " { $vocab-link "logging.analysis" } " vocabulary builds on the " { $vocab-link "logging.parser" } " vocabulary. It parses log files and produces formatted summary reports. It is used by the " { $vocab-link "logger.insomniac" } " vocabulary to e-mail daily reports." +"The " { $vocab-link "logging.analysis" } " vocabulary builds on the " { $vocab-link "logging.parser" } " vocabulary. It parses log files and produces formatted summary reports. It is used by the " { $vocab-link "logging.insomniac" } " vocabulary to e-mail daily reports." $nl "Print log file summary:" { $subsection analyze-log } diff --git a/basis/logging/logging-docs.factor b/basis/logging/logging-docs.factor index f4bdbfc64d..7c14cae78e 100755 --- a/basis/logging/logging-docs.factor +++ b/basis/logging/logging-docs.factor @@ -100,7 +100,7 @@ ARTICLE: "logging.rotation" "Log rotation" "The " { $vocab-link "logging.insomniac" } " vocabulary automates log rotation." ; ARTICLE: "logging.server" "Log implementation" -"The " { $vocab-link "logging.server" } " vocabulary implements a concurrent log server using " { $vocab-link "concurrency" } ". User code never interacts with the server directly, instead it uses the words in the " { $link "logging" } " vocabulary. The server is used to synchronize access to log files and ensure that log rotation can proceed in an orderly fashion." +"The " { $vocab-link "logging.server" } " vocabulary implements a concurrent log server using " { $vocab-link "concurrency.messaging" } ". User code never interacts with the server directly, instead it uses the words in the " { $link "logging" } " vocabulary. The server is used to synchronize access to log files and ensure that log rotation can proceed in an orderly fashion." $nl "The " { $link log-message } " word sends a message to the server which results in the server executing an internal word:" { $subsection (log-message) } diff --git a/core/strings/strings-docs.factor b/core/strings/strings-docs.factor index 8d2a9080d4..88e47d5309 100755 --- a/core/strings/strings-docs.factor +++ b/core/strings/strings-docs.factor @@ -23,7 +23,8 @@ $nl "Since strings are sequences, basic string manipulation can be performed using sequence operations (" { $link "sequences" } "). More advanced functionality can be found in other vocabularies, including but not limited to:" { $list { { $vocab-link "ascii" } " - traditional ASCII character classes" } - { { $vocab-link "unicode" } " - Unicode 5.0-aware character classes, case conversion, word breaks, ..." } + { { $vocab-link "unicode.categories" } " - Unicode character classes" } + { { $vocab-link "unicode.case" } " - Unicode case conversion" } { { $vocab-link "regexp" } " - regular expressions" } { { $vocab-link "peg" } " - parser expression grammars" } } ; diff --git a/extra/printf/printf-docs.factor b/extra/printf/printf-docs.factor index fdecc2ad68..d59320e350 100755 --- a/extra/printf/printf-docs.factor +++ b/extra/printf/printf-docs.factor @@ -39,7 +39,7 @@ HELP: sprintf { $see-also printf } ; ARTICLE: "printf" "Formatted printing" -"The " { $vocab-link "printf" } " and " { $vocab-link "sprintf" } " words are used for formatted printing.\n" +"The " { $link printf } " and " { $link sprintf } " words are used for formatted printing.\n" "\n" "Several format specifications exist for handling arguments of different types, and specifying attributes for the result string, including such things as maximum width, padding, and decimals.\n" { $table diff --git a/extra/wordtimer/wordtimer-docs.factor b/extra/wordtimer/wordtimer-docs.factor index cfe6cfea49..bb64f8fed6 100644 --- a/extra/wordtimer/wordtimer-docs.factor +++ b/extra/wordtimer/wordtimer-docs.factor @@ -42,6 +42,6 @@ HELP: wordtimer-call ARTICLE: "wordtimer" "Word Timer" -"The " { $vocab-link "wordtimer" } " vocabulary measures accumulated execution time for words. If you just want to profile the accumulated time taken by all words in a vocab you can use " { $vocab-link "profile-vocab" } ". If you need more fine grained control then do the following: First annotate individual words with the " { $link add-timer } " word or whole vocabularies with " { $link add-timers } ". Then use " { $link wordtimer-call } " to invoke a quotation and print out the timings." ; +"The " { $vocab-link "wordtimer" } " vocabulary measures accumulated execution time for words. If you just want to profile the accumulated time taken by all words in a vocab you can use " { $link profile-vocab } ". If you need more fine grained control then do the following: First annotate individual words with the " { $link add-timer } " word or whole vocabularies with " { $link add-timers } ". Then use " { $link wordtimer-call } " to invoke a quotation and print out the timings." ; ABOUT: "wordtimer"
Summary:Paste by:Date:
Summary:Paste by:Date: