Compare commits

..

21 Commits

Author SHA1 Message Date
2875964efc Replacing temporal downloded folders for new themes. 2024-10-20 19:59:36 -05:00
7b86b2cfeb Replacing in memory process from GtSubProcess instead of TaskIt futures. 2024-08-02 14:19:00 -05:00
af81f92399 Using GtSubProcess to work on memory and avoid external files creation. 2024-08-02 13:29:56 -05:00
b500a65c00 Renaming. 2024-04-03 10:15:32 -05:00
83ea8d4310 Renaming. 2024-04-01 13:16:55 -05:00
2d811e9f38 Default server shared with the one serving MiniDocs. 2024-03-30 18:06:16 -05:00
a8d12ec46f Implementing components. #defaultView needs to be debugged. 2024-03-30 13:40:50 -05:00
c609595272 Starting implementation of default app view body. 2024-03-30 10:41:25 -05:00
81298aefba Starting implementation of default app view body. 2024-03-30 10:24:17 -05:00
72e0c775e5 Default view as a code block. 2024-03-29 22:25:37 -05:00
f3a1927615 Starting default views. 2024-03-29 21:46:34 -05:00
a96dd95359 Default shared server with MiniDocs to create App views/(sub)routes. 2024-03-29 20:27:48 -05:00
8833341eee Starting BreaApps. 2024-03-29 20:11:27 -05:00
bbda57b908 Replacing GrafoscopioUtils for MiniDocs as a dependency. 2024-03-29 19:13:57 -05:00
f0dfea31b5 Testing future collections. 2023-12-10 13:44:11 -05:00
ef3218a343 Renabling themes downloading. 2023-12-09 18:20:38 -05:00
f29ea2d014 Reenabling themes download. 2023-12-09 18:19:18 -05:00
b0498bfcc5 Disabling Noha's Fork to make Brea installable. 2021-05-08 17:41:33 -05:00
5b04df81b7 Merge 6055fd04f4 2020-12-19 11:24:36 -05:00
9f28bccc1e Support for BreaOperators 2020-12-19 11:24:21 -05:00
6055fd04f4 Merge pull request 'Improving Windows support.' (#2) from Windows into master 2020-12-18 13:54:40 -05:00
17 changed files with 1188 additions and 1140 deletions

View File

@ -16,42 +16,27 @@ BaselineOfBrea >> baseline: spec [
for: #common for: #common
do: [ do: [
"Dependencies" "Dependencies"
self grafoscopioUtils: spec. self miniDocs: spec.
spec spec
baseline: 'NeoJSON' with: [ spec repository: 'github://svenvc/NeoJSON/repository' ]; baseline: 'TaskIt' with: [ spec repository: 'github://pharo-contributions/taskit:v1.0' ]
baseline: 'Mustache' with: [ spec repository: 'github://noha/mustache/repository' ]; "[ spec repository: 'github://noha/taskit:add-all-future' ]"
baseline: 'TaskIt' with: [ spec repository: 'github://noha/taskit:add-all-future' ]. "Disabling Noha's Fork to make Brea installable.".
"Packages" "Packages"
spec package: 'Brea' with: [ spec requires: #('NeoJSON' 'Mustache' 'TaskIt' 'Grafoscopio-Utils') ]. spec package: 'Brea' with: [ spec requires: #('MiniDocs' 'TaskIt') ].
] ]
] ]
{ #category : #baselines } { #category : #baselines }
BaselineOfBrea >> grafoscopioUtils: spec [ BaselineOfBrea >> miniDocs: spec [
"I load the configuration of this package using a external Gitea repository." | repo |
"While more Git independient providers are implemented in Monticello, I will use Iceberg repo := ExoRepo new
to download the repository and load it from a local directory" repository: 'https://code.tupale.co/Offray/MiniDocs'.
repo
| location localRepo | onConflict: [ :ex | ex useLoaded ];
"Dependencies" onUpgrade: [ :ex | ex useLoaded ];
onDowngrade: [ :ex | ex useLoaded ];
"Local and remote repo definition" onWarningLog;
location := FileLocator localDirectory / 'iceberg' / 'Offray' / 'GrafoscopioUtils'.
location exists ifFalse: [
(IceRepositoryCreator new
location: location;
remote: (IceGitRemote url: 'https://code.tupale.co/Offray/GrafoscopioUtils.git');
createRepository)
register
].
"Package loading"
localRepo := 'gitlocal://', location fullName.
Metacello new
repository: localRepo;
baseline: 'GrafoscopioUtils';
load. load.
spec baseline: 'GrafoscopioUtils' with: [ spec repository: localRepo ]. spec baseline: 'MiniDocs' with: [ spec repository: 'gitlocal://', repo local fullName ]
spec package: 'Grafoscopio-Utils' with: [ spec repository: localRepo ].
] ]

View File

@ -1,21 +1,21 @@
" "
A BreaQueryTest is a test class for testing the behavior of BreaQuery A BreaQueryTest is a test class for testing the behavior of BreaQuery
" "
Class { Class {
#name : #BreaQueryTest, #name : #BreaOperatorTest,
#superclass : #TestCase, #superclass : #TestCase,
#category : #'Brea-Tests' #category : #'Brea-Tests'
} }
{ #category : #tests } { #category : #tests }
BreaQueryTest >> testSTONSerialization [ BreaOperatorTest >> testSTONSerialization [
| original store deserialized | | original store deserialized |
original := BreaQuery new original := BreaOperator new
name: 'plus'; name: 'plus';
inputs: {'a' -> 3. 'b' -> 4} asDictionary; inputs: {'a' -> 3. 'b' -> 4} asDictionary;
codeBlock: [ :x :y | x + y ]. codeBlock: [ :x :y | x + y ].
store := STON toString: original. store := STON toString: original.
deserialized := (STONReader on: store readStream) next. deserialized := (STONReader on: store readStream) next.
self assert: original execute equals: deserialized execute self assert: original execute equals: deserialized execute
] ]

View File

@ -1,203 +1,204 @@
" "
A BreaPageTest is a test class for testing the behavior of BreaPage A BreaPageTest is a test class for testing the behavior of BreaPage
" "
Class { Class {
#name : #BreaPageTest, #name : #BreaPageTest,
#superclass : #TestCase, #superclass : #TestCase,
#category : #'Brea-Tests' #category : #'Brea-Tests'
} }
{ #category : #initialization } { #category : #initialization }
BreaPageTest >> createHTMLTemplateFile [ BreaPageTest >> createHTMLTemplateFile [
| testFile contents | | testFile contents |
testFile := FileLocator temp / 'template.mus.html'. testFile := FileLocator temp / 'template.mus.html'.
testFile ensureCreateFile. testFile ensureCreateFile.
contents := contents :=
'<!DOCTYPE html> '<!DOCTYPE html>
<html lang="en"> <html lang="en">
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>{{title}}</title> <title>{{title}}</title>
</head> </head>
<body> <body>
<h1>{{title}}</h1> <h1>{{title}}</h1>
<p> <p>
{{#show}} You should see me. {{/show}} {{#show}} You should see me. {{/show}}
</p> </p>
<p> <p>
{{#unhide}} You should not see me. {{/unhide}} {{#unhide}} You should not see me. {{/unhide}}
</p> </p>
{{{ contents }}} {{{ contents }}}
</body> </body>
</html>'. </html>'.
MarkupFile exportAsFileOn: testFile containing: contents. MarkupFile exportAsFileOn: testFile containing: contents.
] ]
{ #category : #initialization } { #category : #initialization }
BreaPageTest >> createJSONFile [ BreaPageTest >> createJSONFile [
| testFile contents | | testFile contents |
testFile := self jsonTestFile. testFile := self jsonTestFile.
testFile ensureCreateFile. testFile ensureCreateFile.
contents := '{ "title": "This is a test", "show": true, "unhide": false }'. contents := '{ "title": "This is a test", "show": true, "unhide": false }'.
MarkupFile exportAsFileOn: testFile containing: contents. MarkupFile exportAsFileOn: testFile containing: contents.
] ]
{ #category : #initialization } { #category : #initialization }
BreaPageTest >> createMarkdownFile [ BreaPageTest >> createMarkdownFile [
| testFile contents | | testFile contents |
testFile := self markdownTestFile. testFile := self markdownTestFile.
testFile ensureCreateFile. testFile ensureCreateFile.
contents := contents :=
'--- '---
title: This is a test title: This is a test
show: true show: true
unhide: false unhide: false
--- ---
# Level one header # Level one header
And paragraph contents with _emphasis_ and **strong emphasis**.'. And paragraph contents with _emphasis_ and **strong emphasis**.'.
MarkupFile exportAsFileOn: testFile containing: contents. MarkupFile exportAsFileOn: testFile containing: contents.
] ]
{ #category : #'as yet unclassified' } { #category : #'as yet unclassified' }
BreaPageTest >> htmlBodyContents [ BreaPageTest >> htmlBodyContents [
^ '<h1 id="level-one-header">Level one header</h1> ^ '<h1 id="level-one-header">Level one header</h1>
<p>And paragraph contents with <em>emphasis</em> and <strong>strong emphasis</strong>.</p> <p>And paragraph contents with <em>emphasis</em> and <strong>strong emphasis</strong>.</p>
' '
] ]
{ #category : #'as yet unclassified' } { #category : #'as yet unclassified' }
BreaPageTest >> htmlOutput [ BreaPageTest >> htmlOutput [
^ '<!DOCTYPE html> ^ '<!DOCTYPE html>
<html lang="en"> <html lang="en">
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>This is a test</title> <title>This is a test</title>
</head> </head>
<body> <body>
<h1>This is a test</h1> <h1>This is a test</h1>
<p> <p>
You should see me. You should see me.
</p> </p>
<p> <p>
</p> </p>
', self htmlBodyContents, ', self htmlBodyContents,
' '
</body> </body>
</html>' </html>'
] ]
{ #category : #'as yet unclassified' } { #category : #'as yet unclassified' }
BreaPageTest >> jsonTestFile [ BreaPageTest >> jsonTestFile [
^ FileLocator temp / 'test1.json'. ^ FileLocator temp / 'test1.json'.
] ]
{ #category : #'as yet unclassified' } { #category : #'as yet unclassified' }
BreaPageTest >> markdownTestFile [ BreaPageTest >> markdownTestFile [
^ FileLocator temp / 'test.md'. ^ FileLocator temp / 'test.md'.
] ]
{ #category : #'as yet unclassified' } { #category : #'as yet unclassified' }
BreaPageTest >> setUp [ BreaPageTest >> setUp [
"I create disposable simple files for testing purposes." "I create disposable simple files for testing purposes."
super setUp. super setUp.
self createMarkdownFile. self createMarkdownFile.
self createHTMLTemplateFile. self createHTMLTemplateFile.
] self createJSONFile
]
{ #category : #tests }
BreaPageTest >> testJSONMetadataExtraction [ { #category : #tests }
BreaPageTest >> testJSONMetadataExtraction [
| page testMetadata |
testMetadata := {'title' -> 'This is a test' . 'show' -> true. 'unhide' -> false} asDictionary. | page testMetadata |
page := BreaPage new. testMetadata := {'title' -> 'This is a test' . 'show' -> true. 'unhide' -> false} asDictionary.
page page := BreaPage new.
shortName: 'test1'; page
folder: FileLocator temp. shortName: 'test1';
self assert: page metadata equals: testMetadata folder: FileLocator temp.
] self assert: page metadata equals: testMetadata
]
{ #category : #tests }
BreaPageTest >> testJSONPopulateMetadata [ { #category : #tests }
BreaPageTest >> testJSONPopulateMetadata [
| page testMetadata |
testMetadata := {'title' -> 'This is a test' . 'show' -> true. 'unhide' -> false} asDictionary. | page testMetadata |
page := BreaPage new. testMetadata := {'title' -> 'This is a test' . 'show' -> true. 'unhide' -> false} asDictionary.
page page := BreaPage new.
shortName: 'test1'; page
folder: FileLocator temp. shortName: 'test1';
page templateData at: 'extra' put: 'value'. folder: FileLocator temp.
self assert: page populateMetadata equals: (testMetadata at: 'extra' put: 'value'; yourself) page templateData at: 'extra' put: 'value'.
] self assert: page populateMetadata equals: (testMetadata at: 'extra' put: 'value'; yourself)
]
{ #category : #tests }
BreaPageTest >> testMarkdownContentExtraction [ { #category : #tests }
BreaPageTest >> testMarkdownContentExtraction [
| page |
page := BreaPage new. | page |
page page := BreaPage new.
shortName: 'test'; page
folder: FileLocator temp. shortName: 'test';
self assert: page contents equals: self markdownTestFile contents. folder: FileLocator temp.
] self assert: page contents equals: self markdownTestFile contents.
]
{ #category : #tests }
BreaPageTest >> testMarkdownHTMLExport [ { #category : #tests }
BreaPageTest >> testMarkdownHTMLExport [
| page |
page := BreaPage new. | page |
page page := BreaPage new.
shortName: 'test'; page
folder: FileLocator temp; shortName: 'test';
template: 'template.mus.html'; folder: FileLocator temp;
bodyTag: 'contents'. template: 'template.mus.html';
self assert: (page exportAsHTML contents) equals: self htmlOutput. bodyTag: 'contents'.
] self assert: (page exportAsHTML contents) equals: self htmlOutput.
]
{ #category : #tests }
BreaPageTest >> testMarkdownMetadataExtraction [ { #category : #tests }
BreaPageTest >> testMarkdownMetadataExtraction [
| page testMetadata |
testMetadata := {'title' -> 'This is a test' . 'show' -> true. 'unhide' -> false} asDictionary. | page testMetadata |
page := BreaPage new. testMetadata := {'title' -> 'This is a test' . 'show' -> true. 'unhide' -> false} asDictionary.
page page := BreaPage new.
shortName: 'test'; page
folder: FileLocator temp. shortName: 'test';
self assert: page metadata equals: testMetadata folder: FileLocator temp.
] self assert: page metadata equals: testMetadata
]
{ #category : #tests }
BreaPageTest >> testMarkdownPopulateBody [ { #category : #tests }
BreaPageTest >> testMarkdownPopulateBody [
| page |
page := BreaPage new. | page |
page page := BreaPage new.
shortName: 'test'; page
folder: FileLocator temp; shortName: 'test';
bodyTag: 'contents'. folder: FileLocator temp;
page populateTaggedBody. bodyTag: 'contents'.
self assert: (page templateData at: 'contents') equals: self htmlBodyContents. page populateTaggedBody.
] self assert: (page templateData at: 'contents') equals: self htmlBodyContents.
]
{ #category : #tests }
BreaPageTest >> testMarkdownPopulateMetadata [ { #category : #tests }
BreaPageTest >> testMarkdownPopulateMetadata [
| page testMetadata |
testMetadata := {'title' -> 'This is a test' . 'show' -> true. 'unhide' -> false} asDictionary. | page testMetadata |
page := BreaPage new. testMetadata := {'title' -> 'This is a test' . 'show' -> true. 'unhide' -> false} asDictionary.
page page := BreaPage new.
shortName: 'test'; page
folder: FileLocator temp. shortName: 'test';
page templateData at: 'extra' put: 'value'. folder: FileLocator temp.
self assert: page populateMetadata equals: (testMetadata at: 'extra' put: 'value'; yourself) page templateData at: 'extra' put: 'value'.
] self assert: page populateMetadata equals: (testMetadata at: 'extra' put: 'value'; yourself)
]

View File

@ -1 +1 @@
Package { #name : #'Brea-Tests' } Package { #name : #'Brea-Tests' }

View File

@ -1,51 +0,0 @@
"
I model an Airtable (https://airtable.com/) database (or Base as they call it).
"
Class {
#name : #Airtable,
#superclass : #Object,
#instVars : [
'id',
'apiKey'
],
#category : #Brea
}
{ #category : #accessing }
Airtable >> apiKey [
^ apiKey
]
{ #category : #accessing }
Airtable >> apiKey: aString [
apiKey := aString
]
{ #category : #accessing }
Airtable >> id [
^ id
]
{ #category : #accessing }
Airtable >> id: aString [
id := aString
]
{ #category : #'as yet unclassified' }
Airtable >> rawRecords [
(self id isNil or: [ self apiKey isNil ]) ifTrue: [ ^ self ].
^ ZnClient new
url: (self id);
headerAt: 'Authorization' put: 'Bearer ', (self apiKey);
get.
]
{ #category : #'as yet unclassified' }
Airtable >> records [
^ ((NeoJSONReader fromString: (self rawRecords)) at: 'records')
select: [ :each | (each at: 'fields') isNotEmpty ]
]

View File

@ -1,118 +1,118 @@
" "
I model information of the items published on Internet Archive (https://archive.org/). I model information of the items published on Internet Archive (https://archive.org/).
" "
Class { Class {
#name : #ArchiveOrgItem, #name : #ArchiveOrgItem,
#superclass : #Object, #superclass : #Object,
#instVars : [ #instVars : [
'id', 'id',
'metadata' 'metadata'
], ],
#category : #Brea #category : #Brea
} }
{ #category : #utility } { #category : #utility }
ArchiveOrgItem >> archive [ ArchiveOrgItem >> archive [
^ 'https://archive.org' ^ 'https://archive.org'
] ]
{ #category : #utilities } { #category : #utilities }
ArchiveOrgItem >> createHtmlImageGalleryList [ ArchiveOrgItem >> createHtmlImageGalleryList [
"IMPORTANT: This is just a draft snipped. Should become a proper test o be deleted." "IMPORTANT: This is just a draft snipped. Should become a proper test o be deleted."
self metadata ifNil: [ self getMetadata ]. self metadata ifNil: [ self getMetadata ].
^ ' ^ '
<div id="nanogallery2" <div id="nanogallery2"
/* gallery settings */ /* gallery settings */
data-nanogallery2 = ''{ data-nanogallery2 = ''{
"thumbnailHeight": 150, "thumbnailHeight": 150,
"thumbnailWidth": 150, "thumbnailWidth": 150,
"itemsBaseURL": "', self galleryItemsBaseUrl ,'" "itemsBaseURL": "', self galleryItemsBaseUrl ,'"
}'' > }'' >
<!-- gallery content --> <!-- gallery content -->
<a href = "primera 3.jpg" data-ngThumb = "primera 3_thumb.jpg" > </a> <a href = "primera 3.jpg" data-ngThumb = "primera 3_thumb.jpg" > </a>
<a href = "segunda.jpg" data-ngThumb = "segunda_thumb.jpg" > </a> <a href = "segunda.jpg" data-ngThumb = "segunda_thumb.jpg" > </a>
</div>' </div>'
] ]
{ #category : #utilities } { #category : #utilities }
ArchiveOrgItem >> embeddedUrl [ ArchiveOrgItem >> embeddedUrl [
^ 'https://archive.org/embed/', self id. ^ 'https://archive.org/embed/', self id.
] ]
{ #category : #utilities } { #category : #utilities }
ArchiveOrgItem >> galleryItemsBaseUrl [ ArchiveOrgItem >> galleryItemsBaseUrl [
"I create the place where all image would be located for creating a custom image gallery, "I create the place where all image would be located for creating a custom image gallery,
according with the requirements for nanogallery2." according with the requirements for nanogallery2."
^ 'https://', (self metadata at: 'd2'), (self metadata at: 'dir'), '/'. ^ 'https://', (self metadata at: 'd2'), (self metadata at: 'dir'), '/'.
] ]
{ #category : #operation } { #category : #operation }
ArchiveOrgItem >> getMetadata [ ArchiveOrgItem >> getMetadata [
self id ifNil: [ ^ self ]. self id ifNil: [ ^ self ].
self metadata: (NeoJSONReader fromString: (self archive, '/metadata/', self id) asUrl retrieveContents) self metadata: (NeoJSONReader fromString: (self archive, '/metadata/', self id) asUrl retrieveContents)
] ]
{ #category : #accessing } { #category : #accessing }
ArchiveOrgItem >> id [ ArchiveOrgItem >> id [
^ id ^ id
] ]
{ #category : #accessing } { #category : #accessing }
ArchiveOrgItem >> id: anObject [ ArchiveOrgItem >> id: anObject [
id := anObject id := anObject
] ]
{ #category : #utilities } { #category : #utilities }
ArchiveOrgItem >> imagesGalleryList [ ArchiveOrgItem >> imagesGalleryList [
self metadata ifNil: [ self getMetadata ]. self metadata ifNil: [ self getMetadata ].
^ (self metadata at: 'files') select: [ :file | (file at: 'format') = 'JPEG Thumb' ] ^ (self metadata at: 'files') select: [ :file | (file at: 'format') = 'JPEG Thumb' ]
] ]
{ #category : #utilities } { #category : #utilities }
ArchiveOrgItem >> imagesGalleryListAsDictionary [ ArchiveOrgItem >> imagesGalleryListAsDictionary [
| galleryImages result | | galleryImages result |
self imagesGalleryList ifNil: [ ^ self ]. self imagesGalleryList ifNil: [ ^ self ].
galleryImages := OrderedCollection new. galleryImages := OrderedCollection new.
self imagesGalleryList do: [ :imgMetadata | self imagesGalleryList do: [ :imgMetadata |
galleryImages galleryImages
add: (Dictionary new add: (Dictionary new
at: 'imgOriginal' put: (imgMetadata at: 'original'); at: 'imgOriginal' put: (imgMetadata at: 'original');
at: 'imgThumb' put: (imgMetadata at: 'name'); at: 'imgThumb' put: (imgMetadata at: 'name');
yourself) ]. yourself) ].
result := { 'archiveItemImages' -> galleryImages } asDictionary. result := { 'archiveItemImages' -> galleryImages } asDictionary.
^ result ^ result
] ]
{ #category : #accessing } { #category : #accessing }
ArchiveOrgItem >> metadata [ ArchiveOrgItem >> metadata [
^ metadata ^ metadata
] ]
{ #category : #accessing } { #category : #accessing }
ArchiveOrgItem >> metadata: anObject [ ArchiveOrgItem >> metadata: anObject [
metadata := anObject metadata := anObject
] ]
{ #category : #utilities } { #category : #utilities }
ArchiveOrgItem >> subjectTags [ ArchiveOrgItem >> subjectTags [
self id ifNil: [ ^ self ]. self id ifNil: [ ^ self ].
self metadata ifNil: [ self getMetadata ]. self metadata ifNil: [ self getMetadata ].
^ (self metadata at: 'metadata') at: 'subject' ^ (self metadata at: 'metadata') at: 'subject'
] ]
{ #category : #utilities } { #category : #utilities }
ArchiveOrgItem >> subjectTagsAsDictionary [ ArchiveOrgItem >> subjectTagsAsDictionary [
| tagList result | | tagList result |
self imagesGalleryList ifNil: [ ^ self ]. self imagesGalleryList ifNil: [ ^ self ].
tagList := OrderedCollection new. tagList := OrderedCollection new.
self subjectTags do: [ :tag | self subjectTags do: [ :tag |
tagList tagList
add: (Dictionary new add: (Dictionary new
at: 'tag' put: tag; at: 'tag' put: tag;
yourself) ]. yourself) ].
result := { 'tagList' -> tagList } asDictionary. result := { 'tagList' -> tagList } asDictionary.
^ result ^ result
] ]

View File

@ -1,20 +1,20 @@
Extension { #name : #BlockClosure } Extension { #name : #BlockClosure }
{ #category : #'*Brea' } { #category : #'*Brea' }
BlockClosure class >> fromSton: stonReader [ BlockClosure class >> fromSton: stonReader [
^ self compilerClass new ^ self compilerClass new
source: stonReader parseListSingleton; source: stonReader parseListSingleton;
evaluate evaluate
] ]
{ #category : #'*Brea' } { #category : #'*Brea' }
BlockClosure >> stonContainSubObjects [ BlockClosure >> stonContainSubObjects [
^ false ^ false
] ]
{ #category : #'*Brea' } { #category : #'*Brea' }
BlockClosure >> stonOn: stonWriter [ BlockClosure >> stonOn: stonWriter [
self isClean self isClean
ifTrue: [ stonWriter writeObject: self listSingleton: self printString ] ifTrue: [ stonWriter writeObject: self listSingleton: self printString ]
ifFalse: [ stonWriter error: 'Only clean block can be serialized' ] ifFalse: [ stonWriter error: 'Only clean block can be serialized' ]
] ]

View File

@ -0,0 +1,104 @@
Class {
#name : #BreaApp,
#superclass : #Object,
#instVars : [
'name',
'folder',
'host',
'componets'
],
#category : #Brea
}
{ #category : #accessing }
BreaApp >> add: anObject [
anObject class = String ifFalse: [ ].
self body
nextPutAll: (Pandoc htmlStringToMarkdown: anObject); cr.
]
{ #category : #accessing }
BreaApp >> appName [
^ self name asCamelCase
]
{ #category : #accessing }
BreaApp >> at: key put: anObject [
self components at: key put: anObject.
]
{ #category : #accessing }
BreaApp >> components [
^ componets ifNil: [ componets := OrderedDictionary new]
]
{ #category : #accessing }
BreaApp >> componentsWebView [
| response |
response := '' writeStream.
self components ifEmpty: [ ^ response contents ].
self components valuesDo: [ :component |
response
nextPutAll: component webView; cr
].
^ response contents
]
{ #category : #accessing }
BreaApp >> defaultView [
^ '<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="color-scheme" content="light dark" />
<link rel="stylesheet" href="css/pico.min.css">
<title>', self name, '</title>
</head>
<body>
<main class="container">
', self componentsWebView,'
</main>
</body>
</html>'
]
{ #category : #accessing }
BreaApp >> folder [
^ folder
]
{ #category : #accessing }
BreaApp >> folder: aFileDirectory [
folder := aFileDirectory
]
{ #category : #accessing }
BreaApp >> name [
^ name
]
{ #category : #accessing }
BreaApp >> name: aString [
name := aString
]
{ #category : #accessing }
BreaApp >> parentFolder: anObject [
self folder: anObject / self name asCamelCase
]
{ #category : #accessing }
BreaApp >> preview [
| defaultRoute |
defaultRoute := 'http://localhost:',self webHost server port asString, '/', self appName.
self webHost
GET: self appName -> [ self defaultView ].
GoogleChrome openWindowOn: defaultRoute
]
{ #category : #accessing }
BreaApp >> webHost [
^ host ifNil: [ host := Teapot allInstances detect: [ :each | each server isRunning ] ifNone: [ host := Teapot on. host server start ]]
]

View File

@ -1,78 +1,78 @@
" "
I model the file where contents (data and/or metadata) for the Brea CSM pages are stored. I model the file where contents (data and/or metadata) for the Brea CSM pages are stored.
" "
Class { Class {
#name : #BreaFile, #name : #BreaFile,
#superclass : #Object, #superclass : #Object,
#instVars : [ #instVars : [
'folder', 'folder',
'name' 'name'
], ],
#category : #Brea #category : #Brea
} }
{ #category : #'instance creation' } { #category : #'instance creation' }
BreaFile class >> fromShortName: nameString andFolder: aFileLocation [ BreaFile class >> fromShortName: nameString andFolder: aFileLocation [
"I create a new BreaFile assigning priorities to the filename discovery according to "I create a new BreaFile assigning priorities to the filename discovery according to
their extension currently present in a particular folder." their extension currently present in a particular folder."
| extensions | | extensions |
extensions := #('md' 'json' 'yaml'). extensions := #('md' 'json' 'yaml').
extensions do: [ :ext | | markupFile filename | extensions do: [ :ext | | markupFile filename |
filename := nameString, '.', ext. filename := nameString, '.', ext.
markupFile := aFileLocation / filename. markupFile := aFileLocation / filename.
markupFile exists ifTrue: [ ^ self new name: filename; folder: aFileLocation ]. markupFile exists ifTrue: [ ^ self new name: filename; folder: aFileLocation ].
]. ].
^ nil. ^ nil.
] ]
{ #category : #accessing } { #category : #accessing }
BreaFile >> contentString [ BreaFile >> contentString [
self name ifNil: [ ^ nil ]. self name ifNil: [ ^ nil ].
(self name endsWith: '.md') ifTrue: [ ^ self contents contents ]. (self name endsWith: '.md') ifTrue: [ ^ self contents contents ].
(self name endsWith: '.json') ifTrue: [ ^ self contents asString ]. (self name endsWith: '.json') ifTrue: [ ^ self contents asString ].
] ]
{ #category : #accessing } { #category : #accessing }
BreaFile >> contents [ BreaFile >> contents [
| file | | file |
self name ifNil: [ ^ nil ]. self name ifNil: [ ^ nil ].
file := self folder / self name. file := self folder / self name.
(self name endsWith: '.md') ifTrue: [ ^ Markdown fromFile: file ]. (self name endsWith: '.md') ifTrue: [ ^ Markdown fromFile: file ].
(self name endsWith: '.json') ifTrue: [ ^ NeoJSONObject fromString: file contents ] (self name endsWith: '.json') ifTrue: [ ^ NeoJSONObject fromString: file contents ]
] ]
{ #category : #accessing } { #category : #accessing }
BreaFile >> file [ BreaFile >> file [
self folder ifNil: [ ^ self ]. self folder ifNil: [ ^ self ].
self name ifNil: [ ^ self ]. self name ifNil: [ ^ self ].
^ self folder / self name. ^ self folder / self name.
] ]
{ #category : #accessing } { #category : #accessing }
BreaFile >> folder [ BreaFile >> folder [
^ folder ^ folder
] ]
{ #category : #accessing } { #category : #accessing }
BreaFile >> folder: anObject [ BreaFile >> folder: anObject [
folder := anObject folder := anObject
] ]
{ #category : #accessing } { #category : #accessing }
BreaFile >> metadata [ BreaFile >> metadata [
self name ifNil: [ ^ nil ]. self name ifNil: [ ^ nil ].
(self name endsWith: '.md') ifTrue: [ ^ self contents metadata ]. (self name endsWith: '.md') ifTrue: [ ^ self contents metadata ].
(self name endsWith: '.json') ifTrue: [ ^ self contents asDictionary ]. (self name endsWith: '.json') ifTrue: [ ^ self contents asDictionary ].
] ]
{ #category : #accessing } { #category : #accessing }
BreaFile >> name [ BreaFile >> name [
^ name ^ name
] ]
{ #category : #accessing } { #category : #accessing }
BreaFile >> name: anObject [ BreaFile >> name: anObject [
name := anObject name := anObject
] ]

View File

@ -1,95 +1,95 @@
" "
I represent a operation that can be done on data inputs to produce and output by executing I represent a operation that can be done on data inputs to produce and output by executing
a code block. a code block.
I can be used by BreaThemes to produce outpus reflected in a particular set of theme pages. I can be used by BreaThemes to produce outpus reflected in a particular set of theme pages.
- (for bonus points) how to create instances. - (for bonus points) how to create instances.
One simple example is simply gorgeous. One simple example is simply gorgeous.
Internal Representation and Key Implementation Points. Internal Representation and Key Implementation Points.
Instance Variables Instance Variables
codeBlock: <Object> codeBlock: <Object>
inputs: <Object> inputs: <Object>
name: <Object> name: <Object>
Implementation Points Implementation Points
" "
Class { Class {
#name : #BreaQuery, #name : #BreaOperator,
#superclass : #Object, #superclass : #Object,
#instVars : [ #instVars : [
'name', 'name',
'inputs', 'inputs',
'codeBlock', 'codeBlock',
'cleanedInputs' 'cleanedInputs'
], ],
#category : #Brea #category : #Brea
} }
{ #category : #converting } { #category : #converting }
BreaQuery >> asSton [ BreaOperator >> asSton [
^ STON toStringPretty: self ^ STON toStringPretty: self
] ]
{ #category : #converting } { #category : #converting }
BreaQuery >> cleanInputs [ BreaOperator >> cleanInputs [
self cleanedInputs ifNil: [ ^ self ]. self cleanedInputs ifNil: [ ^ self ].
self cleanedInputs ifTrue: [ self cleanedInputs ifTrue: [
self inputs keysAndValuesDo: [ :k :v | | currentValue | self inputs keysAndValuesDo: [ :k :v | | currentValue |
currentValue := self inputs at: k. currentValue := self inputs at: k.
self inputs at: k put: currentValue class new self inputs at: k put: currentValue class new
] ]
]. ].
] ]
{ #category : #accessing } { #category : #accessing }
BreaQuery >> cleanedInputs [ BreaOperator >> cleanedInputs [
^ cleanedInputs ^ cleanedInputs
] ]
{ #category : #accessing } { #category : #accessing }
BreaQuery >> cleanedInputs: aBoolean [ BreaOperator >> cleanedInputs: aBoolean [
"I tell if the inputs should be cleaned when the query is serialized as STON, for "I tell if the inputs should be cleaned when the query is serialized as STON, for
example when they contain sensible information, like API keys or passwords" example when they contain sensible information, like API keys or passwords"
cleanedInputs := aBoolean cleanedInputs := aBoolean
] ]
{ #category : #accessing } { #category : #accessing }
BreaQuery >> codeBlock [ BreaOperator >> codeBlock [
^ codeBlock ^ codeBlock
] ]
{ #category : #accessing } { #category : #accessing }
BreaQuery >> codeBlock: anObject [ BreaOperator >> codeBlock: anObject [
codeBlock := anObject codeBlock := anObject
] ]
{ #category : #execution } { #category : #execution }
BreaQuery >> execute [ BreaOperator >> execute [
^ self codeBlock valueWithArguments: self inputs values. ^ self codeBlock valueWithArguments: self inputs values.
] ]
{ #category : #accessing } { #category : #accessing }
BreaQuery >> inputs [ BreaOperator >> inputs [
^ inputs ^ inputs
] ]
{ #category : #accessing } { #category : #accessing }
BreaQuery >> inputs: anOrderedDictionary [ BreaOperator >> inputs: anOrderedDictionary [
inputs := anOrderedDictionary inputs := anOrderedDictionary
] ]
{ #category : #accessing } { #category : #accessing }
BreaQuery >> name [ BreaOperator >> name [
^ name ^ name
] ]
{ #category : #accessing } { #category : #accessing }
BreaQuery >> name: anObject [ BreaOperator >> name: anObject [
name := anObject name := anObject
] ]

View File

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

View File

@ -1,225 +1,229 @@
" "
I model a web theme. I model a web theme.
For the Collaborators Part: State my main collaborators and one line about how I interact with them. For the Collaborators Part: State my main collaborators and one line about how I interact with them.
Public API and Key Messages Public API and Key Messages
- message one - message one
- message two - message two
- (for bonus points) how to create instances. - (for bonus points) how to create instances.
One simple example is simply gorgeous. One simple example is simply gorgeous.
Internal Representation and Key Implementation Points. Internal Representation and Key Implementation Points.
Instance Variables Instance Variables
name: <Object> name: <Object>
preview: <Object> preview: <Object>
provider: <Object> provider: <Object>
url: <Object> url: <Object>
Implementation Points Implementation Points
" "
Class { Class {
#name : #BreaTheme, #name : #BreaTheme,
#superclass : #Object, #superclass : #Object,
#instVars : [ #instVars : [
'name', 'name',
'folder', 'folder',
'provider', 'provider',
'url', 'url',
'preview', 'preview',
'license', 'license',
'queries', 'operators'
'customizations' ],
], #category : #Brea
#category : #Brea }
}
{ #category : #accessing }
{ #category : #accessing } BreaTheme class >> availablePacks [
BreaTheme class >> availablePacks [ ^ self downloadLinks keys
^ self downloadLinks keys ]
]
{ #category : #utilities }
{ #category : #utilities } BreaTheme class >> downloadLinks [
BreaTheme class >> downloadLinks [ "Keys are the theme names and values are the url where it can be downloaded
"Keys are the theme names and values are the url where it can be downloaded as a zip file.
as a zip file. For the moment we work only with HTML5Up themes, but more could be added
For the moment we work only with HTML5Up themes, but more could be added and the code should be refactored accordingly."
and the code should be refactored accordingly." | result providerUrl |
| result providerUrl | result := Dictionary new.
result := Dictionary new. providerUrl := 'https://html5up.net'.
providerUrl := 'https://html5up.net'. result
result at: 'Paradigm Shift' put: providerUrl, '/paradigm-shift/download';
at: 'Paradigm Shift' put: providerUrl, '/paradigm-shift/download'; at: 'Massively' put: providerUrl, '/massively/download';
at: 'Massively' put: providerUrl, '/massively/download'; at: 'Ethereal' put: providerUrl, '/ethereal/download';
at: 'Ethereal' put: providerUrl, '/ethereal/download'; at: 'Story' put: providerUrl, '/story/download';
at: 'Story' put: providerUrl, '/story/download'; at: 'Dimension' put: providerUrl, '/dimension/download';
at: 'Dimension' put: providerUrl, '/dimension/download'; at: 'Editorial' put: providerUrl, '/editorial/download';
at: 'Editorial' put: providerUrl, '/editorial/download'; at: 'Forty' put: providerUrl, '/forty/download';
at: 'Forty' put: providerUrl, '/forty/download'; at: 'Stellar' put: providerUrl, '/stellar/download';
at: 'Stellar' put: providerUrl, '/stellar/download'; at: 'Multiverse' put: providerUrl, '/multiverse/download';
at: 'Multiverse' put: providerUrl, '/multiverse/download'; at: 'Phantom' put: providerUrl, '/phantom/download';
at: 'Phantom' put: providerUrl, '/phantom/download'; at: 'Hyperspace' put: providerUrl, '/hyperspace/download';
at: 'Hyperspace' put: providerUrl, '/hyperspace/download'; at: 'Future Imperfect' put: providerUrl, '/future-imperfect/download';
at: 'Future Imperfect' put: providerUrl, '/future-imperfect/download'; at: 'Solid State' put: providerUrl, '/solid-state/download';
at: 'Solid State' put: providerUrl, '/solid-state/download'; at: 'Identity' put: providerUrl, '/identity/download';
at: 'Identity' put: providerUrl, '/identity/download'; at: 'Lens' put: providerUrl, '/lens/download';
at: 'Lens' put: providerUrl, '/lens/download'; at: 'Fractal' put: providerUrl, '/fractal/download';
at: 'Fractal' put: providerUrl, '/fractal/download'; at: 'Eventually' put: providerUrl, '/eventually/download';
at: 'Eventually' put: providerUrl, '/eventually/download'; at: 'Spectral' put: providerUrl, '/spectral/download';
at: 'Spectral' put: providerUrl, '/spectral/download'; at: 'Phonon' put: providerUrl, '/photon/download';
at: 'Phonon' put: providerUrl, '/photon/download'; at: 'Highlights' put: providerUrl, '/highlights/download';
at: 'Highlights' put: providerUrl, '/highlights/download'; at: 'Landed' put: providerUrl, '/landed/download';
at: 'Landed' put: providerUrl, '/landed/download'; at: 'Strata' put: providerUrl, '/strata/download';
at: 'Strata' put: providerUrl, '/strata/download'; at: 'Read Only' put: providerUrl, '/read-only/download';
at: 'Read Only' put: providerUrl, '/read-only/download'; at: 'Alpha' put: providerUrl, '/alpha/download';
at: 'Alpha' put: providerUrl, '/alpha/download'; at: 'Directive' put: providerUrl, '/directive/download';
at: 'Directive' put: providerUrl, '/directive/download'; at: 'Aerial' put: providerUrl, '/aerial/download';
at: 'Aerial' put: providerUrl, '/aerial/download'; at: 'Twenty' put: providerUrl, '/twenty/download';
at: 'Twenty' put: providerUrl, '/twenty/download'; at: 'Big Picture' put: providerUrl, '/big-picture/download';
at: 'Big Picture' put: providerUrl, '/big-picture/download'; at: 'Tessellate' put: providerUrl, '/tessellate/download';
at: 'Tessellate' put: providerUrl, '/tessellate/download'; at: 'Overflow' put: providerUrl, 'overflow/download';
at: 'Overflow' put: providerUrl, 'overflow/download'; at: 'Prologue' put: providerUrl, '/prologue/download';
at: 'Prologue' put: providerUrl, '/prologue/download'; at: 'Helios' put: providerUrl, '/helios/download';
at: 'Helios' put: providerUrl, '/helios/download'; at: 'Telephasic' put: providerUrl, '/telephasic/download';
at: 'Telephasic' put: providerUrl, '/telephasic/download'; at: 'Strongly Typed' put: providerUrl, '/strongly-typed/download';
at: 'Strongly Typed' put: providerUrl, '/strongly-typed/download'; at: 'Parallelism' put: providerUrl, '/parallelism/download';
at: 'Parallelism' put: providerUrl, '/parallelism/download'; at: 'Escape Velocity' put: providerUrl, '/escape-velocity/download';
at: 'Escape Velocity' put: providerUrl, '/escape-velocity/download'; at: 'Astral' put: providerUrl, '/astral/download';
at: 'Astral' put: providerUrl, '/astral/download'; at: 'Striped' put: providerUrl, '/striped/download';
at: 'Striped' put: providerUrl, '/striped/download'; at: 'Dopetrope' put: providerUrl, '/dopetrope/download';
at: 'Dopetrope' put: providerUrl, '/dopetrope/download'; at: 'Miniport' put: providerUrl, '/miniport/download';
at: 'Miniport' put: providerUrl, '/miniport/download'; at: 'TXT' put: providerUrl, '/txt/download';
at: 'TXT' put: providerUrl, '/txt/download'; at: 'Verti' put: providerUrl, '/verti/download';
at: 'Verti' put: providerUrl, '/verti/download'; at: 'Zerofour' put: providerUrl, '/zerofour/download';
at: 'Zerofour' put: providerUrl, '/zerofour/download'; at: 'Arcana' put: providerUrl, '/arcana/download';
at: 'Arcana' put: providerUrl, '/arcana/download'; at: 'Halcyonic' put: providerUrl, '/halcyonic/download';
at: 'Halcyonic' put: providerUrl, '/halcyonic/download'; at: 'Minimaxing' put: providerUrl, '/minimaxing/download'.
at: 'Minimaxing' put: providerUrl, '/minimaxing/download'. ^ result
^ result ]
]
{ #category : #operation }
{ #category : #operation } BreaTheme >> addOperator: aBreaQuery [
BreaTheme >> addQuery: aBreaQuery [ self operators add: aBreaQuery cleanInputs
self queries add: aBreaQuery cleanInputs ]
]
{ #category : #operation }
{ #category : #operation } BreaTheme >> asSton [
BreaTheme >> asSton [ ^ STON toStringPretty: self
^ STON toStringPretty: self ]
]
{ #category : #utilities }
{ #category : #utilities } BreaTheme >> dashedName [
BreaTheme >> dashedName [ ^ self name asDashedLowercase
^ self name asDashedLowercase ]
]
{ #category : #operation }
{ #category : #operation } BreaTheme >> downloadInto: aFolder [
BreaTheme >> downloadInto: aFolder [ | tempName zippedFile |
| tempName zippedFile | self url ifNil: [ ^ self ].
self url ifNil: [ ^ self ]. tempName := self name.
tempName := self name. zippedFile := aFolder / self dashedName , 'zip'.
zippedFile := aFolder / self dashedName , 'zip'. aFolder ensureCreateDirectory.
aFolder ensureCreateDirectory. GrafoscopioUtils
GrafoscopioUtils downloadingFrom: self url withMessage: 'Downloading ', tempName, '...' into: zippedFile.
downloadingFrom: self url withMessage: 'Downloading ', tempName, '...' into: zippedFile. self folder: aFolder.
self folder: aFolder. ^ zippedFile
^ zippedFile ]
]
{ #category : #accessing }
{ #category : #accessing } BreaTheme >> folder [
BreaTheme >> folder [ ^ folder
^ folder ]
]
{ #category : #accessing }
{ #category : #accessing } BreaTheme >> folder: anObject [
BreaTheme >> folder: anObject [ folder := anObject
folder := anObject ]
]
{ #category : #installation }
{ #category : #installation } BreaTheme >> installInto: aFolder [
BreaTheme >> installInto: aFolder [ | zippedFile |
| zippedFile | self url ifNil: [ ^ self ].
self url ifNil: [ ^ self ]. zippedFile := FileLocator temp / 'download'.
zippedFile := self downloadInto: FileLocator temp. zippedFile ensureDelete.
(ZipArchive new readFrom: zippedFile) extractAllTo: aFolder. ZnClient new
^ aFolder url: self url;
] downloadTo: FileLocator temp.
(ZipArchive new readFrom: zippedFile) extractAllTo: aFolder.
{ #category : #accessing } self folder: aFolder.
BreaTheme >> license [ ^ aFolder
^ license ]
]
{ #category : #accessing }
{ #category : #accessing } BreaTheme >> license [
BreaTheme >> license: anObject [ ^ license
license := anObject ]
]
{ #category : #accessing }
{ #category : #operation } BreaTheme >> license: anObject [
BreaTheme >> loadConfiguration [ license := anObject
| config | ]
config := self folder / 'brea.yaml'.
config exists { #category : #operation }
ifTrue: [ ^ PPYAMLGrammar new parse: config contents ] BreaTheme >> loadConfiguration [
ifFalse: [ self inform: | config |
'No configuration file found. A "brea.yaml" file should be located in the theme root folder. config := self folder / 'brea.yaml'.
please run "#updateCustomizations" after defining a theme name from the config exists
"BreaTheme availablePacks". ifTrue: [ ^ PPYAMLGrammar new parse: config contents ]
If no configuration is defined for such theme name you can create and empty configuration ifFalse: [ self inform:
file by running "#createBaseConfiguration" and filing out the "brea.yaml" fields. 'No configuration file found. A "brea.yaml" file should be located in the theme root folder.
For more information or help ask at https://t.me/grafoscopio .' ] please run "#updateCustomizations" after defining a theme name from the
] "BreaTheme availablePacks".
If no configuration is defined for such theme name you can create and empty configuration
{ #category : #accessing } file by running "#createBaseConfiguration" and filing out the "brea.yaml" fields.
BreaTheme >> name [ For more information or help ask at https://t.me/grafoscopio .' ]
^ name ifNil: [ name = 'unamed' ] ]
]
{ #category : #accessing }
{ #category : #accessing } BreaTheme >> name [
BreaTheme >> name: anObject [ ^ name ifNil: [ name = 'unamed' ]
name := anObject ]
]
{ #category : #accessing }
{ #category : #accessing } BreaTheme >> name: anObject [
BreaTheme >> preview [ name := anObject
^ preview ]
]
{ #category : #accessing }
{ #category : #accessing } BreaTheme >> operators [
BreaTheme >> preview: anObject [ ^ operators ifNil: [ operators := OrderedCollection new ]
preview := anObject ]
]
{ #category : #accessing }
{ #category : #accessing } BreaTheme >> operators: cleanedBreaQueriesCollection [
BreaTheme >> provider [ operators := cleanedBreaQueriesCollection
^ provider ]
]
{ #category : #accessing }
{ #category : #accessing } BreaTheme >> preview [
BreaTheme >> provider: anObject [ ^ preview
provider := anObject ]
]
{ #category : #accessing }
{ #category : #accessing } BreaTheme >> preview: anObject [
BreaTheme >> queries [ preview := anObject
^ queries ifNil: [ queries := OrderedCollection new ] ]
]
{ #category : #accessing }
{ #category : #accessing } BreaTheme >> provider [
BreaTheme >> queries: cleanedBreaQueriesCollection [ ^ provider
queries := cleanedBreaQueriesCollection ]
]
{ #category : #accessing }
{ #category : #accessing } BreaTheme >> provider: anObject [
BreaTheme >> url [ provider := anObject
^ url ifNil: [ url := self class downloadLinks at: self name. ] ]
]
{ #category : #accessing }
{ #category : #accessing } BreaTheme >> url [
BreaTheme >> url: anObject [ ^ url ifNil: [ url := self class downloadLinks at: self name. ]
url := anObject ]
]
{ #category : #accessing }
BreaTheme >> url: anObject [
url := anObject
]

View File

@ -1,22 +1,22 @@
" "
I provide common utilities for the use with the Brea CMS. I provide common utilities for the use with the Brea CMS.
" "
Class { Class {
#name : #BreaUtils, #name : #BreaUtils,
#superclass : #Object, #superclass : #Object,
#category : #Brea #category : #Brea
} }
{ #category : #'as yet unclassified' } { #category : #'as yet unclassified' }
BreaUtils class >> installSkeleton [ BreaUtils class >> installSkeleton [
"I populate the folder and files structures for Brea documentation and customizations." "I populate the folder and files structures for Brea documentation and customizations."
| skeleton destination | | skeleton destination |
GrafoscopioUtils GrafoscopioUtils
downloadingFrom: 'https://mutabit.com/repos.fossil/brea/zip' downloadingFrom: 'https://mutabit.com/repos.fossil/brea/zip'
withMessage: 'Dowloading files skeleton' withMessage: 'Dowloading files skeleton'
into: FileLocator temp. into: FileLocator temp.
skeleton := ZipArchive new readFrom: FileLocator temp / 'zip'. skeleton := ZipArchive new readFrom: FileLocator temp / 'zip'.
destination := FileLocator home / '.local/share/Brea'. destination := FileLocator home / '.local/share/Brea'.
destination ensureCreateDirectory. destination ensureCreateDirectory.
skeleton extractAllTo: destination. skeleton extractAllTo: destination.
] ]

View File

@ -1,13 +1,13 @@
" "
I store metadata for this package. These meta data are used by other tools such as the SmalllintManifestChecker and the critics Browser I store metadata for this package. These meta data are used by other tools such as the SmalllintManifestChecker and the critics Browser
" "
Class { Class {
#name : #ManifestBrea, #name : #ManifestBrea,
#superclass : #PackageManifest, #superclass : #PackageManifest,
#category : #'Brea-Manifest' #category : #'Brea-Manifest'
} }
{ #category : #'code-critics' } { #category : #'code-critics' }
ManifestBrea class >> ruleRBStringConcatenationRuleV1FalsePositive [ ManifestBrea class >> ruleRBStringConcatenationRuleV1FalsePositive [
^ #(#(#(#RGMethodDefinition #(#BreaPage #contents #false)) #'2020-08-28T20:08:20.291489-05:00') #(#(#RGMethodDefinition #(#BreaFile #fromShortName:andFolder: #false)) #'2020-11-06T20:59:12.94748-05:00') #(#(#RGMethodDefinition #(#'BreaFile class' #fromShortName:andFolder: #true)) #'2020-11-06T21:02:25.564981-05:00') ) ^ #(#(#(#RGMethodDefinition #(#BreaPage #contents #false)) #'2020-08-28T20:08:20.291489-05:00') #(#(#RGMethodDefinition #(#BreaFile #fromShortName:andFolder: #false)) #'2020-11-06T20:59:12.94748-05:00') #(#(#RGMethodDefinition #(#'BreaFile class' #fromShortName:andFolder: #true)) #'2020-11-06T21:02:25.564981-05:00') )
] ]

View File

@ -0,0 +1,6 @@
Extension { #name : #String }
{ #category : #'*Brea' }
String >> webView [
^ (Pandoc htmlStringToMarkdown: self) accentedCharactersCorrection
]

View File

@ -0,0 +1,6 @@
Extension { #name : #Teapot }
{ #category : #'*Brea' }
Teapot >> dynamicRoutes [
^ dynamicRouter routes
]

View File

@ -1 +1 @@
Package { #name : #Brea } Package { #name : #Brea }