263 lines
7.2 KiB
Smalltalk
263 lines
7.2 KiB
Smalltalk
"
|
|
I model a wiki page of a Brea site.
|
|
I am modelled after common wiki pages, where a document in a light markup laguage
|
|
is converted in HTML and is expected to access document history (I am helped by
|
|
FossilRepo for that).
|
|
I can be used for other types of publications, like blog post though.
|
|
"
|
|
Class {
|
|
#name : #BreaPage,
|
|
#superclass : #Object,
|
|
#instVars : [
|
|
'shortName',
|
|
'template',
|
|
'templateData',
|
|
'bodyTag',
|
|
'splitters',
|
|
'subpages',
|
|
'metadata',
|
|
'folder',
|
|
'file'
|
|
],
|
|
#category : #Brea
|
|
}
|
|
|
|
{ #category : #operation }
|
|
BreaPage >> bodyContentsAsHTML [
|
|
| sourcePage |
|
|
self contentsFile ifNil: [ ^ self ].
|
|
Smalltalk os isWindows ifTrue: [
|
|
^ Pandoc markdownToHtml: self file file
|
|
].
|
|
sourcePage := FileLocator temp / 'wikiPage.md'.
|
|
MarkupFile exportAsFileOn: sourcePage containing: self contents.
|
|
^ Pandoc markdownToHtml: sourcePage
|
|
]
|
|
|
|
{ #category : #accessing }
|
|
BreaPage >> bodyTag [
|
|
^ bodyTag
|
|
]
|
|
|
|
{ #category : #accessing }
|
|
BreaPage >> bodyTag: aString [
|
|
"I represent the Mustache Template tag used to denote the body part of a page.
|
|
While the metadata is self describing via YAML metadata blocks in Markddown, so
|
|
they map where ever they are needed in a template, the Markdown file that will be converted
|
|
in HTML via a template doesn't know which part should occupy once the conversion is done.
|
|
I provide such knowledge. So if a page template puts the body content under the mustache tag
|
|
{{content}}, I should use bodyTag: 'content'.
|
|
bodyTag: is template dependant."
|
|
bodyTag := aString
|
|
]
|
|
|
|
{ #category : #accessing }
|
|
BreaPage >> contents [
|
|
| result |
|
|
self contentsFile ifNil: [ ^ nil ].
|
|
result := '' writeStream.
|
|
result nextPutAll: self contentsFile contentString.
|
|
self subpages ifNotNil: [
|
|
self subpages do: [ :sp | | markdownTempFile |
|
|
markdownTempFile := self folder / (sp, '.md').
|
|
result nextPutAll: (Markdown fromFile: markdownTempFile) contents.
|
|
]
|
|
].
|
|
^ result contents.
|
|
]
|
|
|
|
{ #category : #operation }
|
|
BreaPage >> contentsFile [
|
|
|
|
self folder ifNil: [ ^ self ].
|
|
self shortName ifNil: [ ^ self ].
|
|
^ BreaFile fromShortName: self shortName andFolder: self folder.
|
|
]
|
|
|
|
{ #category : #'as yet unclassified' }
|
|
BreaPage >> exportAsHTML [
|
|
| htmlContents allActions actionsArray semaphore result |
|
|
self shortName ifNil: [ ^ self ].
|
|
self template ifNil: [ ^ self ].
|
|
actionsArray := { [ self populateMetadata ] future. }.
|
|
self splitters ifNotEmpty: [ actionsArray := actionsArray copyWith: [ self split ] future ].
|
|
self bodyTag ifNotNil: [
|
|
actionsArray := actionsArray copyWith: [ self populateBodyAs: self bodyTag ] future ].
|
|
allActions := TKTFuture fromCollectionOfFutures: actionsArray.
|
|
semaphore := Semaphore new.
|
|
allActions onSuccessDo: [ :values |
|
|
result := values last.
|
|
semaphore signal.
|
|
].
|
|
semaphore wait.
|
|
htmlContents := (MustacheTemplate on: result templateFile contents) value: result templateData.
|
|
^ MarkupFile exportAsFileOn: self folder / (self shortName, '.html' ) containing: htmlContents
|
|
]
|
|
|
|
{ #category : #accessing }
|
|
BreaPage >> file [
|
|
(self shortName isNil or: [ self folder isNil ]) ifTrue: [ ^ nil ].
|
|
^ file ifNil: [ ^ BreaFile fromShortName: self shortName andFolder: self folder ]
|
|
]
|
|
|
|
{ #category : #accessing }
|
|
BreaPage >> file: anObject [
|
|
file := anObject
|
|
]
|
|
|
|
{ #category : #accessing }
|
|
BreaPage >> folder [
|
|
^ folder
|
|
]
|
|
|
|
{ #category : #accessing }
|
|
BreaPage >> folder: folderFileReference [
|
|
folder := folderFileReference
|
|
]
|
|
|
|
{ #category : #'as yet unclassified' }
|
|
BreaPage >> htmlContents [
|
|
self shortName ifNil: [ ^ self ].
|
|
self template ifNil: [ ^ self ].
|
|
^ (MustacheTemplate on: self templateFile contents) value: self templateData.
|
|
]
|
|
|
|
{ #category : #accessing }
|
|
BreaPage >> metadata [
|
|
^ metadata ifNil: [ self contentsFile metadata ]
|
|
]
|
|
|
|
{ #category : #accessing }
|
|
BreaPage >> metadata: aDictionary [
|
|
"External place where page metadata is located (on Internet or the local file system) in JSON format.
|
|
If nil, is suposed that is placed in the Markdown file with the page contents."
|
|
metadata := aDictionary
|
|
]
|
|
|
|
{ #category : #'as yet unclassified' }
|
|
BreaPage >> populateBodyAs: key [
|
|
| allActions result semaphore |
|
|
|
|
allActions := TKTFuture all: {
|
|
[ self bodyContentsAsHTML ] future.
|
|
}.
|
|
semaphore := Semaphore new.
|
|
allActions onSuccessDo: [ :values |
|
|
result := values last.
|
|
semaphore signal ].
|
|
semaphore wait.
|
|
self templateData at: key put: result contents.
|
|
^ self.
|
|
]
|
|
|
|
{ #category : #'as yet unclassified' }
|
|
BreaPage >> populateExternalMetadata [
|
|
self metadata ifNil: [ ^ self ].
|
|
self
|
|
]
|
|
|
|
{ #category : #operation }
|
|
BreaPage >> populateMetadata [
|
|
| metadataTemp |
|
|
self metadata
|
|
ifNotNil: [ metadataTemp := self metadata ]
|
|
ifNil: [ metadataTemp := self contentsFile metadata].
|
|
metadataTemp keysAndValuesDo: [ :key :value |
|
|
self templateData at: key put: value ].
|
|
^ templateData
|
|
]
|
|
|
|
{ #category : #operation }
|
|
BreaPage >> populateTaggedBody [
|
|
self bodyTag ifNil: [ ^ self ].
|
|
^ self populateBodyAs: self bodyTag.
|
|
]
|
|
|
|
{ #category : #accessing }
|
|
BreaPage >> shortName [
|
|
^ shortName
|
|
]
|
|
|
|
{ #category : #accessing }
|
|
BreaPage >> shortName: aString [
|
|
"The name of the file tha contains the light markup to produce the web page, without file extension.
|
|
By default I work with Markdown files."
|
|
shortName := aString
|
|
]
|
|
|
|
{ #category : #'as yet unclassified' }
|
|
BreaPage >> split [
|
|
self splitters ifEmpty: [ ^ self ].
|
|
self splitters keysAndValuesDo: [ :key :value | self split: key with: value ].
|
|
]
|
|
|
|
{ #category : #'as yet unclassified' }
|
|
BreaPage >> split: key with: subkey [
|
|
"I split a comma separated collection of subkeys stored in the 'key' field and name each one as 'subkey'
|
|
to put it indiviudally in a Mustache template."
|
|
| allSubkeys cleaned data |
|
|
allSubkeys := (self populateMetadata at: key) splitOn: ','.
|
|
cleaned := allSubkeys collect: [ :item | item withBlanksCondensed ].
|
|
data := OrderedCollection new.
|
|
cleaned do: [ :item |
|
|
data add: { subkey -> item } asDictionary ].
|
|
self populateMetadata at: key put: data; yourself.
|
|
]
|
|
|
|
{ #category : #'as yet unclassified' }
|
|
BreaPage >> splitterAt: key with: subkey [
|
|
self splitters at: key put: subkey
|
|
]
|
|
|
|
{ #category : #accessing }
|
|
BreaPage >> splitters [
|
|
^ splitters ifNil: [ splitters := Dictionary new ]
|
|
]
|
|
|
|
{ #category : #accessing }
|
|
BreaPage >> splitters: aDictionary [
|
|
"I model the pattern where a Mustache template contains something like
|
|
{{# key}} {{value}} {{/ key}} and has data that needs to be split before injecting it in the template."
|
|
splitters := aDictionary
|
|
]
|
|
|
|
{ #category : #accessing }
|
|
BreaPage >> subpages [
|
|
^ subpages
|
|
]
|
|
|
|
{ #category : #accessing }
|
|
BreaPage >> subpages: shortNamesList [
|
|
"I am used when a page is composed of other subpages (for example with link aliases) that are shared
|
|
accross several pages."
|
|
subpages := shortNamesList
|
|
]
|
|
|
|
{ #category : #accessing }
|
|
BreaPage >> template [
|
|
^ template
|
|
]
|
|
|
|
{ #category : #accessing }
|
|
BreaPage >> template: mustacheFileName [
|
|
"Usually templates and their pages are located in the same folder."
|
|
template := mustacheFileName
|
|
]
|
|
|
|
{ #category : #accessing }
|
|
BreaPage >> templateData [
|
|
^ templateData ifNil: [ templateData := Dictionary new ]
|
|
]
|
|
|
|
{ #category : #accessing }
|
|
BreaPage >> templateData: aDictionary [
|
|
templateData := aDictionary
|
|
]
|
|
|
|
{ #category : #'as yet unclassified' }
|
|
BreaPage >> templateFile [
|
|
self folder ifNil: [ ^ self ].
|
|
self template ifNil: [ ^ self ].
|
|
^ self folder / self template
|
|
]
|