Merge pull request 'Improving Windows support.' (#2) from Windows into master
This commit is contained in:
commit
6055fd04f4
@ -1,203 +1,203 @@
|
||||
"
|
||||
A BreaPageTest is a test class for testing the behavior of BreaPage
|
||||
"
|
||||
Class {
|
||||
#name : #BreaPageTest,
|
||||
#superclass : #TestCase,
|
||||
#category : #'Brea-Tests'
|
||||
}
|
||||
|
||||
{ #category : #initialization }
|
||||
BreaPageTest >> createHTMLTemplateFile [
|
||||
| testFile contents |
|
||||
testFile := FileLocator temp / 'template.mus.html'.
|
||||
testFile ensureCreateFile.
|
||||
contents :=
|
||||
'<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>{{title}}</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>{{title}}</h1>
|
||||
<p>
|
||||
{{#show}} You should see me. {{/show}}
|
||||
</p>
|
||||
<p>
|
||||
{{#unhide}} You should not see me. {{/unhide}}
|
||||
</p>
|
||||
{{{ contents }}}
|
||||
</body>
|
||||
</html>'.
|
||||
|
||||
MarkupFile exportAsFileOn: testFile containing: contents.
|
||||
|
||||
]
|
||||
|
||||
{ #category : #initialization }
|
||||
BreaPageTest >> createJSONFile [
|
||||
| testFile contents |
|
||||
testFile := self jsonTestFile.
|
||||
testFile ensureCreateFile.
|
||||
contents := '{ "title": "This is a test", "show": true, "unhide": false }'.
|
||||
MarkupFile exportAsFileOn: testFile containing: contents.
|
||||
|
||||
]
|
||||
|
||||
{ #category : #initialization }
|
||||
BreaPageTest >> createMarkdownFile [
|
||||
| testFile contents |
|
||||
testFile := self markdownTestFile.
|
||||
testFile ensureCreateFile.
|
||||
contents :=
|
||||
'---
|
||||
title: This is a test
|
||||
show: true
|
||||
unhide: false
|
||||
|
||||
---
|
||||
|
||||
# Level one header
|
||||
|
||||
And paragraph contents with _emphasis_ and **strong emphasis**.'.
|
||||
|
||||
MarkupFile exportAsFileOn: testFile containing: contents.
|
||||
|
||||
]
|
||||
|
||||
{ #category : #'as yet unclassified' }
|
||||
BreaPageTest >> htmlBodyContents [
|
||||
^ '<h1 id="level-one-header">Level one header</h1>
|
||||
<p>And paragraph contents with <em>emphasis</em> and <strong>strong emphasis</strong>.</p>
|
||||
'
|
||||
]
|
||||
|
||||
{ #category : #'as yet unclassified' }
|
||||
BreaPageTest >> htmlOutput [
|
||||
^ '<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>This is a test</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>This is a test</h1>
|
||||
<p>
|
||||
You should see me.
|
||||
</p>
|
||||
<p>
|
||||
|
||||
</p>
|
||||
', self htmlBodyContents,
|
||||
'
|
||||
</body>
|
||||
</html>'
|
||||
]
|
||||
|
||||
{ #category : #'as yet unclassified' }
|
||||
BreaPageTest >> jsonTestFile [
|
||||
^ FileLocator temp / 'test1.json'.
|
||||
]
|
||||
|
||||
{ #category : #'as yet unclassified' }
|
||||
BreaPageTest >> markdownTestFile [
|
||||
^ FileLocator temp / 'test.md'.
|
||||
]
|
||||
|
||||
{ #category : #'as yet unclassified' }
|
||||
BreaPageTest >> setUp [
|
||||
"I create disposable simple files for testing purposes."
|
||||
super setUp.
|
||||
self createMarkdownFile.
|
||||
self createHTMLTemplateFile.
|
||||
]
|
||||
|
||||
{ #category : #tests }
|
||||
BreaPageTest >> testJSONMetadataExtraction [
|
||||
|
||||
| page testMetadata |
|
||||
testMetadata := {'title' -> 'This is a test' . 'show' -> true. 'unhide' -> false} asDictionary.
|
||||
page := BreaPage new.
|
||||
page
|
||||
shortName: 'test1';
|
||||
folder: FileLocator temp.
|
||||
self assert: page metadata equals: testMetadata
|
||||
]
|
||||
|
||||
{ #category : #tests }
|
||||
BreaPageTest >> testJSONPopulateMetadata [
|
||||
|
||||
| page testMetadata |
|
||||
testMetadata := {'title' -> 'This is a test' . 'show' -> true. 'unhide' -> false} asDictionary.
|
||||
page := BreaPage new.
|
||||
page
|
||||
shortName: 'test1';
|
||||
folder: FileLocator temp.
|
||||
page templateData at: 'extra' put: 'value'.
|
||||
self assert: page populateMetadata equals: (testMetadata at: 'extra' put: 'value'; yourself)
|
||||
]
|
||||
|
||||
{ #category : #tests }
|
||||
BreaPageTest >> testMarkdownContentExtraction [
|
||||
|
||||
| page |
|
||||
page := BreaPage new.
|
||||
page
|
||||
shortName: 'test';
|
||||
folder: FileLocator temp.
|
||||
self assert: page contents equals: self markdownTestFile contents.
|
||||
]
|
||||
|
||||
{ #category : #tests }
|
||||
BreaPageTest >> testMarkdownHTMLExport [
|
||||
|
||||
| page |
|
||||
page := BreaPage new.
|
||||
page
|
||||
shortName: 'test';
|
||||
folder: FileLocator temp;
|
||||
template: 'template.mus.html';
|
||||
bodyTag: 'contents'.
|
||||
self assert: (page exportAsHTML contents) equals: self htmlOutput.
|
||||
]
|
||||
|
||||
{ #category : #tests }
|
||||
BreaPageTest >> testMarkdownMetadataExtraction [
|
||||
|
||||
| page testMetadata |
|
||||
testMetadata := {'title' -> 'This is a test' . 'show' -> true. 'unhide' -> false} asDictionary.
|
||||
page := BreaPage new.
|
||||
page
|
||||
shortName: 'test';
|
||||
folder: FileLocator temp.
|
||||
self assert: page metadata equals: testMetadata
|
||||
]
|
||||
|
||||
{ #category : #tests }
|
||||
BreaPageTest >> testMarkdownPopulateBody [
|
||||
|
||||
| page |
|
||||
page := BreaPage new.
|
||||
page
|
||||
shortName: 'test';
|
||||
folder: FileLocator temp;
|
||||
bodyTag: 'contents'.
|
||||
page populateTaggedBody.
|
||||
self assert: (page templateData at: 'contents') equals: self htmlBodyContents.
|
||||
]
|
||||
|
||||
{ #category : #tests }
|
||||
BreaPageTest >> testMarkdownPopulateMetadata [
|
||||
|
||||
| page testMetadata |
|
||||
testMetadata := {'title' -> 'This is a test' . 'show' -> true. 'unhide' -> false} asDictionary.
|
||||
page := BreaPage new.
|
||||
page
|
||||
shortName: 'test';
|
||||
folder: FileLocator temp.
|
||||
page templateData at: 'extra' put: 'value'.
|
||||
self assert: page populateMetadata equals: (testMetadata at: 'extra' put: 'value'; yourself)
|
||||
]
|
||||
"
|
||||
A BreaPageTest is a test class for testing the behavior of BreaPage
|
||||
"
|
||||
Class {
|
||||
#name : #BreaPageTest,
|
||||
#superclass : #TestCase,
|
||||
#category : #'Brea-Tests'
|
||||
}
|
||||
|
||||
{ #category : #initialization }
|
||||
BreaPageTest >> createHTMLTemplateFile [
|
||||
| testFile contents |
|
||||
testFile := FileLocator temp / 'template.mus.html'.
|
||||
testFile ensureCreateFile.
|
||||
contents :=
|
||||
'<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>{{title}}</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>{{title}}</h1>
|
||||
<p>
|
||||
{{#show}} You should see me. {{/show}}
|
||||
</p>
|
||||
<p>
|
||||
{{#unhide}} You should not see me. {{/unhide}}
|
||||
</p>
|
||||
{{{ contents }}}
|
||||
</body>
|
||||
</html>'.
|
||||
|
||||
MarkupFile exportAsFileOn: testFile containing: contents.
|
||||
|
||||
]
|
||||
|
||||
{ #category : #initialization }
|
||||
BreaPageTest >> createJSONFile [
|
||||
| testFile contents |
|
||||
testFile := self jsonTestFile.
|
||||
testFile ensureCreateFile.
|
||||
contents := '{ "title": "This is a test", "show": true, "unhide": false }'.
|
||||
MarkupFile exportAsFileOn: testFile containing: contents.
|
||||
|
||||
]
|
||||
|
||||
{ #category : #initialization }
|
||||
BreaPageTest >> createMarkdownFile [
|
||||
| testFile contents |
|
||||
testFile := self markdownTestFile.
|
||||
testFile ensureCreateFile.
|
||||
contents :=
|
||||
'---
|
||||
title: This is a test
|
||||
show: true
|
||||
unhide: false
|
||||
|
||||
---
|
||||
|
||||
# Level one header
|
||||
|
||||
And paragraph contents with _emphasis_ and **strong emphasis**.'.
|
||||
|
||||
MarkupFile exportAsFileOn: testFile containing: contents.
|
||||
|
||||
]
|
||||
|
||||
{ #category : #'as yet unclassified' }
|
||||
BreaPageTest >> htmlBodyContents [
|
||||
^ '<h1 id="level-one-header">Level one header</h1>
|
||||
<p>And paragraph contents with <em>emphasis</em> and <strong>strong emphasis</strong>.</p>
|
||||
'
|
||||
]
|
||||
|
||||
{ #category : #'as yet unclassified' }
|
||||
BreaPageTest >> htmlOutput [
|
||||
^ '<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>This is a test</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>This is a test</h1>
|
||||
<p>
|
||||
You should see me.
|
||||
</p>
|
||||
<p>
|
||||
|
||||
</p>
|
||||
', self htmlBodyContents,
|
||||
'
|
||||
</body>
|
||||
</html>'
|
||||
]
|
||||
|
||||
{ #category : #'as yet unclassified' }
|
||||
BreaPageTest >> jsonTestFile [
|
||||
^ FileLocator temp / 'test1.json'.
|
||||
]
|
||||
|
||||
{ #category : #'as yet unclassified' }
|
||||
BreaPageTest >> markdownTestFile [
|
||||
^ FileLocator temp / 'test.md'.
|
||||
]
|
||||
|
||||
{ #category : #'as yet unclassified' }
|
||||
BreaPageTest >> setUp [
|
||||
"I create disposable simple files for testing purposes."
|
||||
super setUp.
|
||||
self createMarkdownFile.
|
||||
self createHTMLTemplateFile.
|
||||
]
|
||||
|
||||
{ #category : #tests }
|
||||
BreaPageTest >> testJSONMetadataExtraction [
|
||||
|
||||
| page testMetadata |
|
||||
testMetadata := {'title' -> 'This is a test' . 'show' -> true. 'unhide' -> false} asDictionary.
|
||||
page := BreaPage new.
|
||||
page
|
||||
shortName: 'test1';
|
||||
folder: FileLocator temp.
|
||||
self assert: page metadata equals: testMetadata
|
||||
]
|
||||
|
||||
{ #category : #tests }
|
||||
BreaPageTest >> testJSONPopulateMetadata [
|
||||
|
||||
| page testMetadata |
|
||||
testMetadata := {'title' -> 'This is a test' . 'show' -> true. 'unhide' -> false} asDictionary.
|
||||
page := BreaPage new.
|
||||
page
|
||||
shortName: 'test1';
|
||||
folder: FileLocator temp.
|
||||
page templateData at: 'extra' put: 'value'.
|
||||
self assert: page populateMetadata equals: (testMetadata at: 'extra' put: 'value'; yourself)
|
||||
]
|
||||
|
||||
{ #category : #tests }
|
||||
BreaPageTest >> testMarkdownContentExtraction [
|
||||
|
||||
| page |
|
||||
page := BreaPage new.
|
||||
page
|
||||
shortName: 'test';
|
||||
folder: FileLocator temp.
|
||||
self assert: page contents equals: self markdownTestFile contents.
|
||||
]
|
||||
|
||||
{ #category : #tests }
|
||||
BreaPageTest >> testMarkdownHTMLExport [
|
||||
|
||||
| page |
|
||||
page := BreaPage new.
|
||||
page
|
||||
shortName: 'test';
|
||||
folder: FileLocator temp;
|
||||
template: 'template.mus.html';
|
||||
bodyTag: 'contents'.
|
||||
self assert: (page exportAsHTML contents) equals: self htmlOutput.
|
||||
]
|
||||
|
||||
{ #category : #tests }
|
||||
BreaPageTest >> testMarkdownMetadataExtraction [
|
||||
|
||||
| page testMetadata |
|
||||
testMetadata := {'title' -> 'This is a test' . 'show' -> true. 'unhide' -> false} asDictionary.
|
||||
page := BreaPage new.
|
||||
page
|
||||
shortName: 'test';
|
||||
folder: FileLocator temp.
|
||||
self assert: page metadata equals: testMetadata
|
||||
]
|
||||
|
||||
{ #category : #tests }
|
||||
BreaPageTest >> testMarkdownPopulateBody [
|
||||
|
||||
| page |
|
||||
page := BreaPage new.
|
||||
page
|
||||
shortName: 'test';
|
||||
folder: FileLocator temp;
|
||||
bodyTag: 'contents'.
|
||||
page populateTaggedBody.
|
||||
self assert: (page templateData at: 'contents') equals: self htmlBodyContents.
|
||||
]
|
||||
|
||||
{ #category : #tests }
|
||||
BreaPageTest >> testMarkdownPopulateMetadata [
|
||||
|
||||
| page testMetadata |
|
||||
testMetadata := {'title' -> 'This is a test' . 'show' -> true. 'unhide' -> false} asDictionary.
|
||||
page := BreaPage new.
|
||||
page
|
||||
shortName: 'test';
|
||||
folder: FileLocator temp.
|
||||
page templateData at: 'extra' put: 'value'.
|
||||
self assert: page populateMetadata equals: (testMetadata at: 'extra' put: 'value'; yourself)
|
||||
]
|
||||
|
@ -1,21 +1,21 @@
|
||||
"
|
||||
A BreaQueryTest is a test class for testing the behavior of BreaQuery
|
||||
"
|
||||
Class {
|
||||
#name : #BreaQueryTest,
|
||||
#superclass : #TestCase,
|
||||
#category : #'Brea-Tests'
|
||||
}
|
||||
|
||||
{ #category : #tests }
|
||||
BreaQueryTest >> testSTONSerialization [
|
||||
|
||||
| original store deserialized |
|
||||
original := BreaQuery new
|
||||
name: 'plus';
|
||||
inputs: {'a' -> 3. 'b' -> 4} asDictionary;
|
||||
codeBlock: [ :x :y | x + y ].
|
||||
store := STON toString: original.
|
||||
deserialized := (STONReader on: store readStream) next.
|
||||
self assert: original execute equals: deserialized execute
|
||||
]
|
||||
"
|
||||
A BreaQueryTest is a test class for testing the behavior of BreaQuery
|
||||
"
|
||||
Class {
|
||||
#name : #BreaQueryTest,
|
||||
#superclass : #TestCase,
|
||||
#category : #'Brea-Tests'
|
||||
}
|
||||
|
||||
{ #category : #tests }
|
||||
BreaQueryTest >> testSTONSerialization [
|
||||
|
||||
| original store deserialized |
|
||||
original := BreaQuery new
|
||||
name: 'plus';
|
||||
inputs: {'a' -> 3. 'b' -> 4} asDictionary;
|
||||
codeBlock: [ :x :y | x + y ].
|
||||
store := STON toString: original.
|
||||
deserialized := (STONReader on: store readStream) next.
|
||||
self assert: original execute equals: deserialized execute
|
||||
]
|
||||
|
@ -1 +1 @@
|
||||
Package { #name : #'Brea-Tests' }
|
||||
Package { #name : #'Brea-Tests' }
|
||||
|
@ -1,51 +1,51 @@
|
||||
"
|
||||
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 ]
|
||||
|
||||
]
|
||||
"
|
||||
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 ]
|
||||
|
||||
]
|
||||
|
@ -1,118 +1,118 @@
|
||||
"
|
||||
I model information of the items published on Internet Archive (https://archive.org/).
|
||||
"
|
||||
Class {
|
||||
#name : #ArchiveOrgItem,
|
||||
#superclass : #Object,
|
||||
#instVars : [
|
||||
'id',
|
||||
'metadata'
|
||||
],
|
||||
#category : #Brea
|
||||
}
|
||||
|
||||
{ #category : #utility }
|
||||
ArchiveOrgItem >> archive [
|
||||
^ 'https://archive.org'
|
||||
]
|
||||
|
||||
{ #category : #utilities }
|
||||
ArchiveOrgItem >> createHtmlImageGalleryList [
|
||||
"IMPORTANT: This is just a draft snipped. Should become a proper test o be deleted."
|
||||
self metadata ifNil: [ self getMetadata ].
|
||||
^ '
|
||||
<div id="nanogallery2"
|
||||
/* gallery settings */
|
||||
data-nanogallery2 = ''{
|
||||
"thumbnailHeight": 150,
|
||||
"thumbnailWidth": 150,
|
||||
"itemsBaseURL": "', self galleryItemsBaseUrl ,'"
|
||||
}'' >
|
||||
|
||||
<!-- gallery content -->
|
||||
<a href = "primera 3.jpg" data-ngThumb = "primera 3_thumb.jpg" > </a>
|
||||
<a href = "segunda.jpg" data-ngThumb = "segunda_thumb.jpg" > </a>
|
||||
</div>'
|
||||
]
|
||||
|
||||
{ #category : #utilities }
|
||||
ArchiveOrgItem >> embeddedUrl [
|
||||
|
||||
^ 'https://archive.org/embed/', self id.
|
||||
]
|
||||
|
||||
{ #category : #utilities }
|
||||
ArchiveOrgItem >> galleryItemsBaseUrl [
|
||||
"I create the place where all image would be located for creating a custom image gallery,
|
||||
according with the requirements for nanogallery2."
|
||||
|
||||
^ 'https://', (self metadata at: 'd2'), (self metadata at: 'dir'), '/'.
|
||||
]
|
||||
|
||||
{ #category : #operation }
|
||||
ArchiveOrgItem >> getMetadata [
|
||||
self id ifNil: [ ^ self ].
|
||||
self metadata: (NeoJSONReader fromString: (self archive, '/metadata/', self id) asUrl retrieveContents)
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
ArchiveOrgItem >> id [
|
||||
^ id
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
ArchiveOrgItem >> id: anObject [
|
||||
id := anObject
|
||||
]
|
||||
|
||||
{ #category : #utilities }
|
||||
ArchiveOrgItem >> imagesGalleryList [
|
||||
self metadata ifNil: [ self getMetadata ].
|
||||
^ (self metadata at: 'files') select: [ :file | (file at: 'format') = 'JPEG Thumb' ]
|
||||
]
|
||||
|
||||
{ #category : #utilities }
|
||||
ArchiveOrgItem >> imagesGalleryListAsDictionary [
|
||||
| galleryImages result |
|
||||
self imagesGalleryList ifNil: [ ^ self ].
|
||||
galleryImages := OrderedCollection new.
|
||||
self imagesGalleryList do: [ :imgMetadata |
|
||||
galleryImages
|
||||
add: (Dictionary new
|
||||
at: 'imgOriginal' put: (imgMetadata at: 'original');
|
||||
at: 'imgThumb' put: (imgMetadata at: 'name');
|
||||
yourself) ].
|
||||
result := { 'archiveItemImages' -> galleryImages } asDictionary.
|
||||
^ result
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
ArchiveOrgItem >> metadata [
|
||||
^ metadata
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
ArchiveOrgItem >> metadata: anObject [
|
||||
metadata := anObject
|
||||
]
|
||||
|
||||
{ #category : #utilities }
|
||||
ArchiveOrgItem >> subjectTags [
|
||||
self id ifNil: [ ^ self ].
|
||||
self metadata ifNil: [ self getMetadata ].
|
||||
^ (self metadata at: 'metadata') at: 'subject'
|
||||
]
|
||||
|
||||
{ #category : #utilities }
|
||||
ArchiveOrgItem >> subjectTagsAsDictionary [
|
||||
| tagList result |
|
||||
self imagesGalleryList ifNil: [ ^ self ].
|
||||
tagList := OrderedCollection new.
|
||||
self subjectTags do: [ :tag |
|
||||
tagList
|
||||
add: (Dictionary new
|
||||
at: 'tag' put: tag;
|
||||
yourself) ].
|
||||
result := { 'tagList' -> tagList } asDictionary.
|
||||
^ result
|
||||
]
|
||||
"
|
||||
I model information of the items published on Internet Archive (https://archive.org/).
|
||||
"
|
||||
Class {
|
||||
#name : #ArchiveOrgItem,
|
||||
#superclass : #Object,
|
||||
#instVars : [
|
||||
'id',
|
||||
'metadata'
|
||||
],
|
||||
#category : #Brea
|
||||
}
|
||||
|
||||
{ #category : #utility }
|
||||
ArchiveOrgItem >> archive [
|
||||
^ 'https://archive.org'
|
||||
]
|
||||
|
||||
{ #category : #utilities }
|
||||
ArchiveOrgItem >> createHtmlImageGalleryList [
|
||||
"IMPORTANT: This is just a draft snipped. Should become a proper test o be deleted."
|
||||
self metadata ifNil: [ self getMetadata ].
|
||||
^ '
|
||||
<div id="nanogallery2"
|
||||
/* gallery settings */
|
||||
data-nanogallery2 = ''{
|
||||
"thumbnailHeight": 150,
|
||||
"thumbnailWidth": 150,
|
||||
"itemsBaseURL": "', self galleryItemsBaseUrl ,'"
|
||||
}'' >
|
||||
|
||||
<!-- gallery content -->
|
||||
<a href = "primera 3.jpg" data-ngThumb = "primera 3_thumb.jpg" > </a>
|
||||
<a href = "segunda.jpg" data-ngThumb = "segunda_thumb.jpg" > </a>
|
||||
</div>'
|
||||
]
|
||||
|
||||
{ #category : #utilities }
|
||||
ArchiveOrgItem >> embeddedUrl [
|
||||
|
||||
^ 'https://archive.org/embed/', self id.
|
||||
]
|
||||
|
||||
{ #category : #utilities }
|
||||
ArchiveOrgItem >> galleryItemsBaseUrl [
|
||||
"I create the place where all image would be located for creating a custom image gallery,
|
||||
according with the requirements for nanogallery2."
|
||||
|
||||
^ 'https://', (self metadata at: 'd2'), (self metadata at: 'dir'), '/'.
|
||||
]
|
||||
|
||||
{ #category : #operation }
|
||||
ArchiveOrgItem >> getMetadata [
|
||||
self id ifNil: [ ^ self ].
|
||||
self metadata: (NeoJSONReader fromString: (self archive, '/metadata/', self id) asUrl retrieveContents)
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
ArchiveOrgItem >> id [
|
||||
^ id
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
ArchiveOrgItem >> id: anObject [
|
||||
id := anObject
|
||||
]
|
||||
|
||||
{ #category : #utilities }
|
||||
ArchiveOrgItem >> imagesGalleryList [
|
||||
self metadata ifNil: [ self getMetadata ].
|
||||
^ (self metadata at: 'files') select: [ :file | (file at: 'format') = 'JPEG Thumb' ]
|
||||
]
|
||||
|
||||
{ #category : #utilities }
|
||||
ArchiveOrgItem >> imagesGalleryListAsDictionary [
|
||||
| galleryImages result |
|
||||
self imagesGalleryList ifNil: [ ^ self ].
|
||||
galleryImages := OrderedCollection new.
|
||||
self imagesGalleryList do: [ :imgMetadata |
|
||||
galleryImages
|
||||
add: (Dictionary new
|
||||
at: 'imgOriginal' put: (imgMetadata at: 'original');
|
||||
at: 'imgThumb' put: (imgMetadata at: 'name');
|
||||
yourself) ].
|
||||
result := { 'archiveItemImages' -> galleryImages } asDictionary.
|
||||
^ result
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
ArchiveOrgItem >> metadata [
|
||||
^ metadata
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
ArchiveOrgItem >> metadata: anObject [
|
||||
metadata := anObject
|
||||
]
|
||||
|
||||
{ #category : #utilities }
|
||||
ArchiveOrgItem >> subjectTags [
|
||||
self id ifNil: [ ^ self ].
|
||||
self metadata ifNil: [ self getMetadata ].
|
||||
^ (self metadata at: 'metadata') at: 'subject'
|
||||
]
|
||||
|
||||
{ #category : #utilities }
|
||||
ArchiveOrgItem >> subjectTagsAsDictionary [
|
||||
| tagList result |
|
||||
self imagesGalleryList ifNil: [ ^ self ].
|
||||
tagList := OrderedCollection new.
|
||||
self subjectTags do: [ :tag |
|
||||
tagList
|
||||
add: (Dictionary new
|
||||
at: 'tag' put: tag;
|
||||
yourself) ].
|
||||
result := { 'tagList' -> tagList } asDictionary.
|
||||
^ result
|
||||
]
|
||||
|
@ -1,20 +1,20 @@
|
||||
Extension { #name : #BlockClosure }
|
||||
|
||||
{ #category : #'*Brea' }
|
||||
BlockClosure class >> fromSton: stonReader [
|
||||
^ self compilerClass new
|
||||
source: stonReader parseListSingleton;
|
||||
evaluate
|
||||
]
|
||||
|
||||
{ #category : #'*Brea' }
|
||||
BlockClosure >> stonContainSubObjects [
|
||||
^ false
|
||||
]
|
||||
|
||||
{ #category : #'*Brea' }
|
||||
BlockClosure >> stonOn: stonWriter [
|
||||
self isClean
|
||||
ifTrue: [ stonWriter writeObject: self listSingleton: self printString ]
|
||||
ifFalse: [ stonWriter error: 'Only clean block can be serialized' ]
|
||||
]
|
||||
Extension { #name : #BlockClosure }
|
||||
|
||||
{ #category : #'*Brea' }
|
||||
BlockClosure class >> fromSton: stonReader [
|
||||
^ self compilerClass new
|
||||
source: stonReader parseListSingleton;
|
||||
evaluate
|
||||
]
|
||||
|
||||
{ #category : #'*Brea' }
|
||||
BlockClosure >> stonContainSubObjects [
|
||||
^ false
|
||||
]
|
||||
|
||||
{ #category : #'*Brea' }
|
||||
BlockClosure >> stonOn: stonWriter [
|
||||
self isClean
|
||||
ifTrue: [ stonWriter writeObject: self listSingleton: self printString ]
|
||||
ifFalse: [ stonWriter error: 'Only clean block can be serialized' ]
|
||||
]
|
||||
|
@ -1,71 +1,78 @@
|
||||
"
|
||||
I model the file where contents (data and/or metadata) for the Brea CSM pages are stored.
|
||||
"
|
||||
Class {
|
||||
#name : #BreaFile,
|
||||
#superclass : #Object,
|
||||
#instVars : [
|
||||
'folder',
|
||||
'name'
|
||||
],
|
||||
#category : #Brea
|
||||
}
|
||||
|
||||
{ #category : #'instance creation' }
|
||||
BreaFile class >> fromShortName: nameString andFolder: aFileLocation [
|
||||
"I create a new BreaFile assigning priorities to the filename discovery according to
|
||||
their extension currently present in a particular folder."
|
||||
| extensions |
|
||||
|
||||
extensions := #('md' 'json' 'yaml').
|
||||
extensions do: [ :ext | | markupFile filename |
|
||||
filename := nameString, '.', ext.
|
||||
markupFile := aFileLocation / filename.
|
||||
markupFile exists ifTrue: [ ^ self new name: filename; folder: aFileLocation ].
|
||||
].
|
||||
^ nil.
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
BreaFile >> contentString [
|
||||
|
||||
self name ifNil: [ ^ nil ].
|
||||
(self name endsWith: '.md') ifTrue: [ ^ self contents contents ].
|
||||
(self name endsWith: '.json') ifTrue: [ ^ self contents asString ].
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
BreaFile >> contents [
|
||||
| file |
|
||||
self name ifNil: [ ^ nil ].
|
||||
file := self folder / self name.
|
||||
(self name endsWith: '.md') ifTrue: [ ^ Markdown fromFile: file ].
|
||||
(self name endsWith: '.json') ifTrue: [ ^ NeoJSONObject fromString: file contents ]
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
BreaFile >> folder [
|
||||
^ folder
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
BreaFile >> folder: anObject [
|
||||
folder := anObject
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
BreaFile >> metadata [
|
||||
self name ifNil: [ ^ nil ].
|
||||
(self name endsWith: '.md') ifTrue: [ ^ self contents metadata ].
|
||||
(self name endsWith: '.json') ifTrue: [ ^ self contents asDictionary ].
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
BreaFile >> name [
|
||||
^ name
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
BreaFile >> name: anObject [
|
||||
name := anObject
|
||||
]
|
||||
"
|
||||
I model the file where contents (data and/or metadata) for the Brea CSM pages are stored.
|
||||
"
|
||||
Class {
|
||||
#name : #BreaFile,
|
||||
#superclass : #Object,
|
||||
#instVars : [
|
||||
'folder',
|
||||
'name'
|
||||
],
|
||||
#category : #Brea
|
||||
}
|
||||
|
||||
{ #category : #'instance creation' }
|
||||
BreaFile class >> fromShortName: nameString andFolder: aFileLocation [
|
||||
"I create a new BreaFile assigning priorities to the filename discovery according to
|
||||
their extension currently present in a particular folder."
|
||||
| extensions |
|
||||
|
||||
extensions := #('md' 'json' 'yaml').
|
||||
extensions do: [ :ext | | markupFile filename |
|
||||
filename := nameString, '.', ext.
|
||||
markupFile := aFileLocation / filename.
|
||||
markupFile exists ifTrue: [ ^ self new name: filename; folder: aFileLocation ].
|
||||
].
|
||||
^ nil.
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
BreaFile >> contentString [
|
||||
|
||||
self name ifNil: [ ^ nil ].
|
||||
(self name endsWith: '.md') ifTrue: [ ^ self contents contents ].
|
||||
(self name endsWith: '.json') ifTrue: [ ^ self contents asString ].
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
BreaFile >> contents [
|
||||
| file |
|
||||
self name ifNil: [ ^ nil ].
|
||||
file := self folder / self name.
|
||||
(self name endsWith: '.md') ifTrue: [ ^ Markdown fromFile: file ].
|
||||
(self name endsWith: '.json') ifTrue: [ ^ NeoJSONObject fromString: file contents ]
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
BreaFile >> file [
|
||||
self folder ifNil: [ ^ self ].
|
||||
self name ifNil: [ ^ self ].
|
||||
^ self folder / self name.
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
BreaFile >> folder [
|
||||
^ folder
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
BreaFile >> folder: anObject [
|
||||
folder := anObject
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
BreaFile >> metadata [
|
||||
self name ifNil: [ ^ nil ].
|
||||
(self name endsWith: '.md') ifTrue: [ ^ self contents metadata ].
|
||||
(self name endsWith: '.json') ifTrue: [ ^ self contents asDictionary ].
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
BreaFile >> name [
|
||||
^ name
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
BreaFile >> name: anObject [
|
||||
name := anObject
|
||||
]
|
||||
|
@ -1,259 +1,262 @@
|
||||
"
|
||||
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 ].
|
||||
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 all: 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
|
||||
]
|
||||
"
|
||||
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 all: 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
|
||||
]
|
||||
|
@ -1,95 +1,95 @@
|
||||
"
|
||||
I represent a operation that can be done on data inputs to produce and output by executing
|
||||
a code block.
|
||||
|
||||
I can be used by BreaThemes to produce outpus reflected in a particular set of theme pages.
|
||||
|
||||
|
||||
- (for bonus points) how to create instances.
|
||||
|
||||
One simple example is simply gorgeous.
|
||||
|
||||
Internal Representation and Key Implementation Points.
|
||||
|
||||
Instance Variables
|
||||
codeBlock: <Object>
|
||||
inputs: <Object>
|
||||
name: <Object>
|
||||
|
||||
|
||||
Implementation Points
|
||||
"
|
||||
Class {
|
||||
#name : #BreaQuery,
|
||||
#superclass : #Object,
|
||||
#instVars : [
|
||||
'name',
|
||||
'inputs',
|
||||
'codeBlock',
|
||||
'cleanedInputs'
|
||||
],
|
||||
#category : #Brea
|
||||
}
|
||||
|
||||
{ #category : #converting }
|
||||
BreaQuery >> asSton [
|
||||
^ STON toStringPretty: self
|
||||
]
|
||||
|
||||
{ #category : #converting }
|
||||
BreaQuery >> cleanInputs [
|
||||
self cleanedInputs ifNil: [ ^ self ].
|
||||
self cleanedInputs ifTrue: [
|
||||
self inputs keysAndValuesDo: [ :k :v | | currentValue |
|
||||
currentValue := self inputs at: k.
|
||||
self inputs at: k put: currentValue class new
|
||||
]
|
||||
].
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
BreaQuery >> cleanedInputs [
|
||||
^ cleanedInputs
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
BreaQuery >> cleanedInputs: aBoolean [
|
||||
"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"
|
||||
cleanedInputs := aBoolean
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
BreaQuery >> codeBlock [
|
||||
^ codeBlock
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
BreaQuery >> codeBlock: anObject [
|
||||
codeBlock := anObject
|
||||
]
|
||||
|
||||
{ #category : #execution }
|
||||
BreaQuery >> execute [
|
||||
^ self codeBlock valueWithArguments: self inputs values.
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
BreaQuery >> inputs [
|
||||
^ inputs
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
BreaQuery >> inputs: anOrderedDictionary [
|
||||
inputs := anOrderedDictionary
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
BreaQuery >> name [
|
||||
^ name
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
BreaQuery >> name: anObject [
|
||||
name := anObject
|
||||
]
|
||||
"
|
||||
I represent a operation that can be done on data inputs to produce and output by executing
|
||||
a code block.
|
||||
|
||||
I can be used by BreaThemes to produce outpus reflected in a particular set of theme pages.
|
||||
|
||||
|
||||
- (for bonus points) how to create instances.
|
||||
|
||||
One simple example is simply gorgeous.
|
||||
|
||||
Internal Representation and Key Implementation Points.
|
||||
|
||||
Instance Variables
|
||||
codeBlock: <Object>
|
||||
inputs: <Object>
|
||||
name: <Object>
|
||||
|
||||
|
||||
Implementation Points
|
||||
"
|
||||
Class {
|
||||
#name : #BreaQuery,
|
||||
#superclass : #Object,
|
||||
#instVars : [
|
||||
'name',
|
||||
'inputs',
|
||||
'codeBlock',
|
||||
'cleanedInputs'
|
||||
],
|
||||
#category : #Brea
|
||||
}
|
||||
|
||||
{ #category : #converting }
|
||||
BreaQuery >> asSton [
|
||||
^ STON toStringPretty: self
|
||||
]
|
||||
|
||||
{ #category : #converting }
|
||||
BreaQuery >> cleanInputs [
|
||||
self cleanedInputs ifNil: [ ^ self ].
|
||||
self cleanedInputs ifTrue: [
|
||||
self inputs keysAndValuesDo: [ :k :v | | currentValue |
|
||||
currentValue := self inputs at: k.
|
||||
self inputs at: k put: currentValue class new
|
||||
]
|
||||
].
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
BreaQuery >> cleanedInputs [
|
||||
^ cleanedInputs
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
BreaQuery >> cleanedInputs: aBoolean [
|
||||
"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"
|
||||
cleanedInputs := aBoolean
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
BreaQuery >> codeBlock [
|
||||
^ codeBlock
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
BreaQuery >> codeBlock: anObject [
|
||||
codeBlock := anObject
|
||||
]
|
||||
|
||||
{ #category : #execution }
|
||||
BreaQuery >> execute [
|
||||
^ self codeBlock valueWithArguments: self inputs values.
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
BreaQuery >> inputs [
|
||||
^ inputs
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
BreaQuery >> inputs: anOrderedDictionary [
|
||||
inputs := anOrderedDictionary
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
BreaQuery >> name [
|
||||
^ name
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
BreaQuery >> name: anObject [
|
||||
name := anObject
|
||||
]
|
||||
|
@ -1,225 +1,225 @@
|
||||
"
|
||||
I model a web theme.
|
||||
|
||||
For the Collaborators Part: State my main collaborators and one line about how I interact with them.
|
||||
|
||||
Public API and Key Messages
|
||||
|
||||
- message one
|
||||
- message two
|
||||
- (for bonus points) how to create instances.
|
||||
|
||||
One simple example is simply gorgeous.
|
||||
|
||||
Internal Representation and Key Implementation Points.
|
||||
|
||||
Instance Variables
|
||||
name: <Object>
|
||||
preview: <Object>
|
||||
provider: <Object>
|
||||
url: <Object>
|
||||
|
||||
|
||||
Implementation Points
|
||||
"
|
||||
Class {
|
||||
#name : #BreaTheme,
|
||||
#superclass : #Object,
|
||||
#instVars : [
|
||||
'name',
|
||||
'folder',
|
||||
'provider',
|
||||
'url',
|
||||
'preview',
|
||||
'license',
|
||||
'queries',
|
||||
'customizations'
|
||||
],
|
||||
#category : #Brea
|
||||
}
|
||||
|
||||
{ #category : #accessing }
|
||||
BreaTheme class >> availablePacks [
|
||||
^ self downloadLinks keys
|
||||
]
|
||||
|
||||
{ #category : #utilities }
|
||||
BreaTheme class >> downloadLinks [
|
||||
"Keys are the theme names and values are the url where it can be downloaded
|
||||
as a zip file.
|
||||
For the moment we work only with HTML5Up themes, but more could be added
|
||||
and the code should be refactored accordingly."
|
||||
| result providerUrl |
|
||||
result := Dictionary new.
|
||||
providerUrl := 'https://html5up.net'.
|
||||
result
|
||||
at: 'Paradigm Shift' put: providerUrl, '/paradigm-shift/download';
|
||||
at: 'Massively' put: providerUrl, '/massively/download';
|
||||
at: 'Ethereal' put: providerUrl, '/ethereal/download';
|
||||
at: 'Story' put: providerUrl, '/story/download';
|
||||
at: 'Dimension' put: providerUrl, '/dimension/download';
|
||||
at: 'Editorial' put: providerUrl, '/editorial/download';
|
||||
at: 'Forty' put: providerUrl, '/forty/download';
|
||||
at: 'Stellar' put: providerUrl, '/stellar/download';
|
||||
at: 'Multiverse' put: providerUrl, '/multiverse/download';
|
||||
at: 'Phantom' put: providerUrl, '/phantom/download';
|
||||
at: 'Hyperspace' put: providerUrl, '/hyperspace/download';
|
||||
at: 'Future Imperfect' put: providerUrl, '/future-imperfect/download';
|
||||
at: 'Solid State' put: providerUrl, '/solid-state/download';
|
||||
at: 'Identity' put: providerUrl, '/identity/download';
|
||||
at: 'Lens' put: providerUrl, '/lens/download';
|
||||
at: 'Fractal' put: providerUrl, '/fractal/download';
|
||||
at: 'Eventually' put: providerUrl, '/eventually/download';
|
||||
at: 'Spectral' put: providerUrl, '/spectral/download';
|
||||
at: 'Phonon' put: providerUrl, '/photon/download';
|
||||
at: 'Highlights' put: providerUrl, '/highlights/download';
|
||||
at: 'Landed' put: providerUrl, '/landed/download';
|
||||
at: 'Strata' put: providerUrl, '/strata/download';
|
||||
at: 'Read Only' put: providerUrl, '/read-only/download';
|
||||
at: 'Alpha' put: providerUrl, '/alpha/download';
|
||||
at: 'Directive' put: providerUrl, '/directive/download';
|
||||
at: 'Aerial' put: providerUrl, '/aerial/download';
|
||||
at: 'Twenty' put: providerUrl, '/twenty/download';
|
||||
at: 'Big Picture' put: providerUrl, '/big-picture/download';
|
||||
at: 'Tessellate' put: providerUrl, '/tessellate/download';
|
||||
at: 'Overflow' put: providerUrl, 'overflow/download';
|
||||
at: 'Prologue' put: providerUrl, '/prologue/download';
|
||||
at: 'Helios' put: providerUrl, '/helios/download';
|
||||
at: 'Telephasic' put: providerUrl, '/telephasic/download';
|
||||
at: 'Strongly Typed' put: providerUrl, '/strongly-typed/download';
|
||||
at: 'Parallelism' put: providerUrl, '/parallelism/download';
|
||||
at: 'Escape Velocity' put: providerUrl, '/escape-velocity/download';
|
||||
at: 'Astral' put: providerUrl, '/astral/download';
|
||||
at: 'Striped' put: providerUrl, '/striped/download';
|
||||
at: 'Dopetrope' put: providerUrl, '/dopetrope/download';
|
||||
at: 'Miniport' put: providerUrl, '/miniport/download';
|
||||
at: 'TXT' put: providerUrl, '/txt/download';
|
||||
at: 'Verti' put: providerUrl, '/verti/download';
|
||||
at: 'Zerofour' put: providerUrl, '/zerofour/download';
|
||||
at: 'Arcana' put: providerUrl, '/arcana/download';
|
||||
at: 'Halcyonic' put: providerUrl, '/halcyonic/download';
|
||||
at: 'Minimaxing' put: providerUrl, '/minimaxing/download'.
|
||||
^ result
|
||||
]
|
||||
|
||||
{ #category : #operation }
|
||||
BreaTheme >> addQuery: aBreaQuery [
|
||||
self queries add: aBreaQuery cleanInputs
|
||||
]
|
||||
|
||||
{ #category : #operation }
|
||||
BreaTheme >> asSton [
|
||||
^ STON toStringPretty: self
|
||||
]
|
||||
|
||||
{ #category : #utilities }
|
||||
BreaTheme >> dashedName [
|
||||
^ self name asDashedLowercase
|
||||
]
|
||||
|
||||
{ #category : #operation }
|
||||
BreaTheme >> downloadInto: aFolder [
|
||||
| tempName zippedFile |
|
||||
self url ifNil: [ ^ self ].
|
||||
tempName := self name.
|
||||
zippedFile := aFolder / self dashedName , 'zip'.
|
||||
aFolder ensureCreateDirectory.
|
||||
GrafoscopioUtils
|
||||
downloadingFrom: self url withMessage: 'Downloading ', tempName, '...' into: zippedFile.
|
||||
self folder: aFolder.
|
||||
^ zippedFile
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
BreaTheme >> folder [
|
||||
^ folder
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
BreaTheme >> folder: anObject [
|
||||
folder := anObject
|
||||
]
|
||||
|
||||
{ #category : #installation }
|
||||
BreaTheme >> installInto: aFolder [
|
||||
| zippedFile |
|
||||
self url ifNil: [ ^ self ].
|
||||
zippedFile := self downloadInto: aFolder.
|
||||
(ZipArchive new readFrom: zippedFile) extractAllTo: aFolder.
|
||||
^ aFolder
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
BreaTheme >> license [
|
||||
^ license
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
BreaTheme >> license: anObject [
|
||||
license := anObject
|
||||
]
|
||||
|
||||
{ #category : #operation }
|
||||
BreaTheme >> loadConfiguration [
|
||||
| config |
|
||||
config := self folder / 'brea.yaml'.
|
||||
config exists
|
||||
ifTrue: [ ^ PPYAMLGrammar new parse: config contents ]
|
||||
ifFalse: [ self inform:
|
||||
'No configuration file found. A "brea.yaml" file should be located in the theme root folder.
|
||||
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
|
||||
file by running "#createBaseConfiguration" and filing out the "brea.yaml" fields.
|
||||
For more information or help ask at https://t.me/grafoscopio .' ]
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
BreaTheme >> name [
|
||||
^ name ifNil: [ name = 'unamed' ]
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
BreaTheme >> name: anObject [
|
||||
name := anObject
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
BreaTheme >> preview [
|
||||
^ preview
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
BreaTheme >> preview: anObject [
|
||||
preview := anObject
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
BreaTheme >> provider [
|
||||
^ provider
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
BreaTheme >> provider: anObject [
|
||||
provider := anObject
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
BreaTheme >> queries [
|
||||
^ queries ifNil: [ queries := OrderedCollection new ]
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
BreaTheme >> queries: cleanedBreaQueriesCollection [
|
||||
queries := cleanedBreaQueriesCollection
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
BreaTheme >> url [
|
||||
^ url ifNil: [ url := self class downloadLinks at: self name. ]
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
BreaTheme >> url: anObject [
|
||||
url := anObject
|
||||
]
|
||||
"
|
||||
I model a web theme.
|
||||
|
||||
For the Collaborators Part: State my main collaborators and one line about how I interact with them.
|
||||
|
||||
Public API and Key Messages
|
||||
|
||||
- message one
|
||||
- message two
|
||||
- (for bonus points) how to create instances.
|
||||
|
||||
One simple example is simply gorgeous.
|
||||
|
||||
Internal Representation and Key Implementation Points.
|
||||
|
||||
Instance Variables
|
||||
name: <Object>
|
||||
preview: <Object>
|
||||
provider: <Object>
|
||||
url: <Object>
|
||||
|
||||
|
||||
Implementation Points
|
||||
"
|
||||
Class {
|
||||
#name : #BreaTheme,
|
||||
#superclass : #Object,
|
||||
#instVars : [
|
||||
'name',
|
||||
'folder',
|
||||
'provider',
|
||||
'url',
|
||||
'preview',
|
||||
'license',
|
||||
'queries',
|
||||
'customizations'
|
||||
],
|
||||
#category : #Brea
|
||||
}
|
||||
|
||||
{ #category : #accessing }
|
||||
BreaTheme class >> availablePacks [
|
||||
^ self downloadLinks keys
|
||||
]
|
||||
|
||||
{ #category : #utilities }
|
||||
BreaTheme class >> downloadLinks [
|
||||
"Keys are the theme names and values are the url where it can be downloaded
|
||||
as a zip file.
|
||||
For the moment we work only with HTML5Up themes, but more could be added
|
||||
and the code should be refactored accordingly."
|
||||
| result providerUrl |
|
||||
result := Dictionary new.
|
||||
providerUrl := 'https://html5up.net'.
|
||||
result
|
||||
at: 'Paradigm Shift' put: providerUrl, '/paradigm-shift/download';
|
||||
at: 'Massively' put: providerUrl, '/massively/download';
|
||||
at: 'Ethereal' put: providerUrl, '/ethereal/download';
|
||||
at: 'Story' put: providerUrl, '/story/download';
|
||||
at: 'Dimension' put: providerUrl, '/dimension/download';
|
||||
at: 'Editorial' put: providerUrl, '/editorial/download';
|
||||
at: 'Forty' put: providerUrl, '/forty/download';
|
||||
at: 'Stellar' put: providerUrl, '/stellar/download';
|
||||
at: 'Multiverse' put: providerUrl, '/multiverse/download';
|
||||
at: 'Phantom' put: providerUrl, '/phantom/download';
|
||||
at: 'Hyperspace' put: providerUrl, '/hyperspace/download';
|
||||
at: 'Future Imperfect' put: providerUrl, '/future-imperfect/download';
|
||||
at: 'Solid State' put: providerUrl, '/solid-state/download';
|
||||
at: 'Identity' put: providerUrl, '/identity/download';
|
||||
at: 'Lens' put: providerUrl, '/lens/download';
|
||||
at: 'Fractal' put: providerUrl, '/fractal/download';
|
||||
at: 'Eventually' put: providerUrl, '/eventually/download';
|
||||
at: 'Spectral' put: providerUrl, '/spectral/download';
|
||||
at: 'Phonon' put: providerUrl, '/photon/download';
|
||||
at: 'Highlights' put: providerUrl, '/highlights/download';
|
||||
at: 'Landed' put: providerUrl, '/landed/download';
|
||||
at: 'Strata' put: providerUrl, '/strata/download';
|
||||
at: 'Read Only' put: providerUrl, '/read-only/download';
|
||||
at: 'Alpha' put: providerUrl, '/alpha/download';
|
||||
at: 'Directive' put: providerUrl, '/directive/download';
|
||||
at: 'Aerial' put: providerUrl, '/aerial/download';
|
||||
at: 'Twenty' put: providerUrl, '/twenty/download';
|
||||
at: 'Big Picture' put: providerUrl, '/big-picture/download';
|
||||
at: 'Tessellate' put: providerUrl, '/tessellate/download';
|
||||
at: 'Overflow' put: providerUrl, 'overflow/download';
|
||||
at: 'Prologue' put: providerUrl, '/prologue/download';
|
||||
at: 'Helios' put: providerUrl, '/helios/download';
|
||||
at: 'Telephasic' put: providerUrl, '/telephasic/download';
|
||||
at: 'Strongly Typed' put: providerUrl, '/strongly-typed/download';
|
||||
at: 'Parallelism' put: providerUrl, '/parallelism/download';
|
||||
at: 'Escape Velocity' put: providerUrl, '/escape-velocity/download';
|
||||
at: 'Astral' put: providerUrl, '/astral/download';
|
||||
at: 'Striped' put: providerUrl, '/striped/download';
|
||||
at: 'Dopetrope' put: providerUrl, '/dopetrope/download';
|
||||
at: 'Miniport' put: providerUrl, '/miniport/download';
|
||||
at: 'TXT' put: providerUrl, '/txt/download';
|
||||
at: 'Verti' put: providerUrl, '/verti/download';
|
||||
at: 'Zerofour' put: providerUrl, '/zerofour/download';
|
||||
at: 'Arcana' put: providerUrl, '/arcana/download';
|
||||
at: 'Halcyonic' put: providerUrl, '/halcyonic/download';
|
||||
at: 'Minimaxing' put: providerUrl, '/minimaxing/download'.
|
||||
^ result
|
||||
]
|
||||
|
||||
{ #category : #operation }
|
||||
BreaTheme >> addQuery: aBreaQuery [
|
||||
self queries add: aBreaQuery cleanInputs
|
||||
]
|
||||
|
||||
{ #category : #operation }
|
||||
BreaTheme >> asSton [
|
||||
^ STON toStringPretty: self
|
||||
]
|
||||
|
||||
{ #category : #utilities }
|
||||
BreaTheme >> dashedName [
|
||||
^ self name asDashedLowercase
|
||||
]
|
||||
|
||||
{ #category : #operation }
|
||||
BreaTheme >> downloadInto: aFolder [
|
||||
| tempName zippedFile |
|
||||
self url ifNil: [ ^ self ].
|
||||
tempName := self name.
|
||||
zippedFile := aFolder / self dashedName , 'zip'.
|
||||
aFolder ensureCreateDirectory.
|
||||
GrafoscopioUtils
|
||||
downloadingFrom: self url withMessage: 'Downloading ', tempName, '...' into: zippedFile.
|
||||
self folder: aFolder.
|
||||
^ zippedFile
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
BreaTheme >> folder [
|
||||
^ folder
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
BreaTheme >> folder: anObject [
|
||||
folder := anObject
|
||||
]
|
||||
|
||||
{ #category : #installation }
|
||||
BreaTheme >> installInto: aFolder [
|
||||
| zippedFile |
|
||||
self url ifNil: [ ^ self ].
|
||||
zippedFile := self downloadInto: FileLocator temp.
|
||||
(ZipArchive new readFrom: zippedFile) extractAllTo: aFolder.
|
||||
^ aFolder
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
BreaTheme >> license [
|
||||
^ license
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
BreaTheme >> license: anObject [
|
||||
license := anObject
|
||||
]
|
||||
|
||||
{ #category : #operation }
|
||||
BreaTheme >> loadConfiguration [
|
||||
| config |
|
||||
config := self folder / 'brea.yaml'.
|
||||
config exists
|
||||
ifTrue: [ ^ PPYAMLGrammar new parse: config contents ]
|
||||
ifFalse: [ self inform:
|
||||
'No configuration file found. A "brea.yaml" file should be located in the theme root folder.
|
||||
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
|
||||
file by running "#createBaseConfiguration" and filing out the "brea.yaml" fields.
|
||||
For more information or help ask at https://t.me/grafoscopio .' ]
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
BreaTheme >> name [
|
||||
^ name ifNil: [ name = 'unamed' ]
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
BreaTheme >> name: anObject [
|
||||
name := anObject
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
BreaTheme >> preview [
|
||||
^ preview
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
BreaTheme >> preview: anObject [
|
||||
preview := anObject
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
BreaTheme >> provider [
|
||||
^ provider
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
BreaTheme >> provider: anObject [
|
||||
provider := anObject
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
BreaTheme >> queries [
|
||||
^ queries ifNil: [ queries := OrderedCollection new ]
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
BreaTheme >> queries: cleanedBreaQueriesCollection [
|
||||
queries := cleanedBreaQueriesCollection
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
BreaTheme >> url [
|
||||
^ url ifNil: [ url := self class downloadLinks at: self name. ]
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
BreaTheme >> url: anObject [
|
||||
url := anObject
|
||||
]
|
||||
|
@ -1,22 +1,22 @@
|
||||
"
|
||||
I provide common utilities for the use with the Brea CMS.
|
||||
"
|
||||
Class {
|
||||
#name : #BreaUtils,
|
||||
#superclass : #Object,
|
||||
#category : #Brea
|
||||
}
|
||||
|
||||
{ #category : #'as yet unclassified' }
|
||||
BreaUtils class >> installSkeleton [
|
||||
"I populate the folder and files structures for Brea documentation and customizations."
|
||||
| skeleton destination |
|
||||
GrafoscopioUtils
|
||||
downloadingFrom: 'https://mutabit.com/repos.fossil/brea/zip'
|
||||
withMessage: 'Dowloading files skeleton'
|
||||
into: FileLocator temp.
|
||||
skeleton := ZipArchive new readFrom: FileLocator temp / 'zip'.
|
||||
destination := FileLocator home / '.local/share/Brea'.
|
||||
destination ensureCreateDirectory.
|
||||
skeleton extractAllTo: destination.
|
||||
]
|
||||
"
|
||||
I provide common utilities for the use with the Brea CMS.
|
||||
"
|
||||
Class {
|
||||
#name : #BreaUtils,
|
||||
#superclass : #Object,
|
||||
#category : #Brea
|
||||
}
|
||||
|
||||
{ #category : #'as yet unclassified' }
|
||||
BreaUtils class >> installSkeleton [
|
||||
"I populate the folder and files structures for Brea documentation and customizations."
|
||||
| skeleton destination |
|
||||
GrafoscopioUtils
|
||||
downloadingFrom: 'https://mutabit.com/repos.fossil/brea/zip'
|
||||
withMessage: 'Dowloading files skeleton'
|
||||
into: FileLocator temp.
|
||||
skeleton := ZipArchive new readFrom: FileLocator temp / 'zip'.
|
||||
destination := FileLocator home / '.local/share/Brea'.
|
||||
destination ensureCreateDirectory.
|
||||
skeleton extractAllTo: destination.
|
||||
]
|
||||
|
@ -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
|
||||
"
|
||||
Class {
|
||||
#name : #ManifestBrea,
|
||||
#superclass : #PackageManifest,
|
||||
#category : #'Brea-Manifest'
|
||||
}
|
||||
|
||||
{ #category : #'code-critics' }
|
||||
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') )
|
||||
]
|
||||
"
|
||||
I store metadata for this package. These meta data are used by other tools such as the SmalllintManifestChecker and the critics Browser
|
||||
"
|
||||
Class {
|
||||
#name : #ManifestBrea,
|
||||
#superclass : #PackageManifest,
|
||||
#category : #'Brea-Manifest'
|
||||
}
|
||||
|
||||
{ #category : #'code-critics' }
|
||||
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') )
|
||||
]
|
||||
|
@ -1 +1 @@
|
||||
Package { #name : #Brea }
|
||||
Package { #name : #Brea }
|
||||
|
Loading…
Reference in New Issue
Block a user