|
|
@ -1,12 +1,18 @@
|
|
|
|
#lang racket/base
|
|
|
|
#lang racket/base
|
|
|
|
(require (for-syntax racket/base "setup.rkt" "private/splice.rkt"))
|
|
|
|
(require (for-syntax
|
|
|
|
(require txexpr/base xml/path sugar/define sugar/coerce sugar/test racket/string)
|
|
|
|
racket/base
|
|
|
|
(require "private/file-utils.rkt"
|
|
|
|
"setup.rkt")
|
|
|
|
|
|
|
|
racket/match
|
|
|
|
|
|
|
|
txexpr/base
|
|
|
|
|
|
|
|
xml/path
|
|
|
|
|
|
|
|
sugar/define
|
|
|
|
|
|
|
|
sugar/coerce
|
|
|
|
|
|
|
|
sugar/test
|
|
|
|
|
|
|
|
"private/file-utils.rkt"
|
|
|
|
"setup.rkt"
|
|
|
|
"setup.rkt"
|
|
|
|
"cache.rkt"
|
|
|
|
"cache.rkt"
|
|
|
|
"pagetree.rkt"
|
|
|
|
"pagetree.rkt"
|
|
|
|
"tag.rkt"
|
|
|
|
"tag.rkt")
|
|
|
|
"private/splice.rkt")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
(define is-meta-value? hash?)
|
|
|
|
(define is-meta-value? hash?)
|
|
|
|
(define is-doc-value? txexpr?)
|
|
|
|
(define is-doc-value? txexpr?)
|
|
|
@ -22,15 +28,15 @@
|
|
|
|
((coerce/symbol? (or/c is-meta-value? is-doc-value? pagenode? pathish?)) (symbol?) . ->* . (or/c #f txexpr-elements?))
|
|
|
|
((coerce/symbol? (or/c is-meta-value? is-doc-value? pagenode? pathish?)) (symbol?) . ->* . (or/c #f txexpr-elements?))
|
|
|
|
(define metas-result (and (not (is-doc-value? value-source)) (select-from-metas key value-source caller)))
|
|
|
|
(define metas-result (and (not (is-doc-value? value-source)) (select-from-metas key value-source caller)))
|
|
|
|
(define doc-result (and (not (is-meta-value? value-source)) (select-from-doc key value-source caller)))
|
|
|
|
(define doc-result (and (not (is-meta-value? value-source)) (select-from-doc key value-source caller)))
|
|
|
|
(define result (filter values (apply append (map ->list (list metas-result doc-result)))))
|
|
|
|
(match (filter values (apply append (map ->list (list metas-result doc-result))))
|
|
|
|
(and (pair? result) result))
|
|
|
|
[(? pair? res) res]
|
|
|
|
|
|
|
|
[_ #false]))
|
|
|
|
|
|
|
|
|
|
|
|
(define+provide/contract (select key value-source)
|
|
|
|
(define+provide/contract (select key value-source)
|
|
|
|
(coerce/symbol? (or/c is-meta-value? is-doc-value? pagenode? pathish?) . -> . (or/c #f txexpr-element?))
|
|
|
|
(coerce/symbol? (or/c is-meta-value? is-doc-value? pagenode? pathish?) . -> . (or/c #f txexpr-element?))
|
|
|
|
(define result (select* key value-source 'select))
|
|
|
|
(match (select* key value-source 'select)
|
|
|
|
(and (pair? result) (car result)))
|
|
|
|
[(cons res _) res]
|
|
|
|
|
|
|
|
[_ #false]))
|
|
|
|
|
|
|
|
|
|
|
|
(module-test-external
|
|
|
|
(module-test-external
|
|
|
|
(check-equal? (select* 'key '#hash((key . "value"))) '("value"))
|
|
|
|
(check-equal? (select* 'key '#hash((key . "value"))) '("value"))
|
|
|
@ -52,31 +58,28 @@
|
|
|
|
(check-false (select* 'absent-key doc))
|
|
|
|
(check-false (select* 'absent-key doc))
|
|
|
|
(check-false (select 'absent-key doc))))
|
|
|
|
(check-false (select 'absent-key doc))))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
(define+provide/contract (select-from-metas key metas-source [caller 'select-from-metas])
|
|
|
|
(define+provide/contract (select-from-metas key metas-source [caller 'select-from-metas])
|
|
|
|
;; output contract is a single txexpr-element
|
|
|
|
;; output contract is a single txexpr-element
|
|
|
|
;; because metas is a hash, and a hash has only one value for a key.
|
|
|
|
;; because metas is a hash, and a hash has only one value for a key.
|
|
|
|
((coerce/symbol? (or/c is-meta-value? pagenode? pathish?)) (symbol?) . ->* . (or/c #f txexpr-element?))
|
|
|
|
((coerce/symbol? (or/c is-meta-value? pagenode? pathish?)) (symbol?) . ->* . (or/c #f txexpr-element?))
|
|
|
|
(define metas (if (is-meta-value? metas-source)
|
|
|
|
(hash-ref (match metas-source
|
|
|
|
metas-source
|
|
|
|
[(? is-meta-value? ms) ms]
|
|
|
|
(get-metas metas-source caller)))
|
|
|
|
[_ (get-metas metas-source caller)]) key #false))
|
|
|
|
(and (hash-has-key? metas key) (hash-ref metas key)))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
(module-test-external
|
|
|
|
(module-test-external
|
|
|
|
(let ([metas '#hash((key . "value"))])
|
|
|
|
(let ([metas '#hash((key . "value"))])
|
|
|
|
(check-equal? (select-from-metas 'key metas) "value")
|
|
|
|
(check-equal? (select-from-metas 'key metas) "value")
|
|
|
|
(check-false (select-from-metas 'absent-key metas))))
|
|
|
|
(check-false (select-from-metas 'absent-key metas))))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
(define+provide/contract (select-from-doc key doc-source [caller 'select-from-doc])
|
|
|
|
(define+provide/contract (select-from-doc key doc-source [caller 'select-from-doc])
|
|
|
|
;; output contract is a list of elements
|
|
|
|
;; output contract is a list of elements
|
|
|
|
;; because doc is a txexpr, and a txexpr can have multiple values for a key
|
|
|
|
;; because doc is a txexpr, and a txexpr can have multiple values for a key
|
|
|
|
((coerce/symbol? (or/c is-doc-value? pagenode? pathish?)) (symbol?) . ->* . (or/c #f txexpr-elements?))
|
|
|
|
((coerce/symbol? (or/c is-doc-value? pagenode? pathish?)) (symbol?) . ->* . (or/c #f txexpr-elements?))
|
|
|
|
(define doc (if (is-doc-value? doc-source)
|
|
|
|
(match (se-path*/list (list key) (match doc-source
|
|
|
|
doc-source
|
|
|
|
[(? is-doc-value?) doc-source]
|
|
|
|
(get-doc doc-source caller)))
|
|
|
|
[_ (get-doc doc-source caller)]))
|
|
|
|
(define result (se-path*/list (list key) doc))
|
|
|
|
[(? pair? result) result]
|
|
|
|
(and (pair? result) result))
|
|
|
|
[_ #false]))
|
|
|
|
|
|
|
|
|
|
|
|
(module-test-external
|
|
|
|
(module-test-external
|
|
|
|
(check-equal? (select-from-doc 'key '(root (key "value"))) '("value"))
|
|
|
|
(check-equal? (select-from-doc 'key '(root (key "value"))) '("value"))
|
|
|
@ -85,27 +88,23 @@
|
|
|
|
(check-equal? (select-from-doc 'key doc) '("value"))
|
|
|
|
(check-equal? (select-from-doc 'key doc) '("value"))
|
|
|
|
(check-false (select-from-doc 'absent-key doc))))
|
|
|
|
(check-false (select-from-doc 'absent-key doc))))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
(define (convert+validate-path pagenode-or-path caller)
|
|
|
|
(define (convert+validate-path pagenode-or-path caller)
|
|
|
|
(let* ([path (if (pagenode? pagenode-or-path)
|
|
|
|
(define path (if (pagenode? pagenode-or-path)
|
|
|
|
(build-path (current-project-root) (symbol->string pagenode-or-path))
|
|
|
|
(build-path (current-project-root) (symbol->string pagenode-or-path))
|
|
|
|
pagenode-or-path)]
|
|
|
|
pagenode-or-path))
|
|
|
|
[path (or (get-source path) path)])
|
|
|
|
(define src-path (or (get-source path) path))
|
|
|
|
(unless (file-exists? path)
|
|
|
|
(unless (file-exists? src-path)
|
|
|
|
(raise-argument-error caller "existing Pollen source, or name of its output path" path))
|
|
|
|
(raise-argument-error caller "existing Pollen source, or name of its output path" src-path))
|
|
|
|
path))
|
|
|
|
src-path)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
(define+provide/contract (get-metas pagenode-or-path [caller 'get-metas])
|
|
|
|
(define+provide/contract (get-metas pagenode-or-path [caller 'get-metas])
|
|
|
|
(((or/c pagenode? pathish?)) (symbol?) . ->* . is-meta-value?)
|
|
|
|
(((or/c pagenode? pathish?)) (symbol?) . ->* . is-meta-value?)
|
|
|
|
(cached-metas (convert+validate-path pagenode-or-path caller)))
|
|
|
|
(cached-metas (convert+validate-path pagenode-or-path caller)))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
(define+provide/contract (get-doc pagenode-or-path [caller 'get-doc])
|
|
|
|
(define+provide/contract (get-doc pagenode-or-path [caller 'get-doc])
|
|
|
|
(((or/c pagenode? pathish?)) (symbol?) . ->* . (or/c is-doc-value? string?))
|
|
|
|
(((or/c pagenode? pathish?)) (symbol?) . ->* . (or/c is-doc-value? string?))
|
|
|
|
(cached-doc (convert+validate-path pagenode-or-path caller)))
|
|
|
|
(cached-doc (convert+validate-path pagenode-or-path caller)))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
;; This `@` definition is here to provide a hook for the docs.
|
|
|
|
;; This `@` definition is here to provide a hook for the docs.
|
|
|
|
;; But this is just default tag behavior, and thus would work without the definition.
|
|
|
|
;; But this is just default tag behavior, and thus would work without the definition.
|
|
|
|
;; Which is why the splicing tag can be renamed:
|
|
|
|
;; Which is why the splicing tag can be renamed:
|
|
|
@ -125,7 +124,6 @@
|
|
|
|
(SPLICING-TAG . BODY)
|
|
|
|
(SPLICING-TAG . BODY)
|
|
|
|
(SPLICING-TAG)))]))
|
|
|
|
(SPLICING-TAG)))]))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
(provide for/splice for*/splice)
|
|
|
|
(provide for/splice for*/splice)
|
|
|
|
|
|
|
|
|
|
|
|
(define-syntax (for/splice/base stx)
|
|
|
|
(define-syntax (for/splice/base stx)
|
|
|
@ -141,6 +139,5 @@
|
|
|
|
(syntax-case stx ()
|
|
|
|
(syntax-case stx ()
|
|
|
|
[(_ . BODY) (syntax-property #'(for/splice/base . BODY) 'form #'for*/list)]))
|
|
|
|
[(_ . BODY) (syntax-property #'(for/splice/base . BODY) 'form #'for*/list)]))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
(provide when/block) ; bw compat
|
|
|
|
(provide when/block) ; bw compat
|
|
|
|
(define-syntax when/block (make-rename-transformer #'when/splice))
|
|
|
|
(define-syntax when/block (make-rename-transformer #'when/splice))
|