Improving Windows support. #2

Merged
Offray merged 2 commits from Windows into master 2020-12-18 18:54:40 +00:00
14 changed files with 698 additions and 1674 deletions
Showing only changes of commit 1044fb4997 - Show all commits

View File

@ -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
]

View File

@ -1,31 +0,0 @@
Class {
#name : #BreaDataSource,
#superclass : #Object,
#instVars : [
'source',
'queries'
],
#category : #Brea
}
{ #category : #accessing }
BreaDataSource >> queries [
^ queries
]
{ #category : #accessing }
BreaDataSource >> queries: anObject [
queries := anObject
]
{ #category : #accessing }
BreaDataSource >> source [
^ source
]
{ #category : #accessing }
BreaDataSource >> source: aDictionary [
"Key, value pair in aDictionary contain a short name and a url pointing to a local or a remote
resource. If is local a FileLocator should be provided."
source := aDictionary
]

View File

@ -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 ].
]
{ #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
]

View File

@ -1,489 +0,0 @@
"
I model a member of a Brea site, usually a human.
"
Class {
#name : #BreaMember,
#superclass : #Object,
#instVars : [
'givenName',
'familyName',
'picture',
'country',
'tags',
'email',
'password',
'webPresence',
'organizations'
],
#category : #Brea
}
{ #category : #converting }
BreaMember >> asStonModified [
"asSton is generated a core dumped now. This renaming is trying to solve that. Maybe
in the offical release it will be solved"
^ STON toStringPretty: self
]
{ #category : #accessing }
BreaMember >> country [
^ country
]
{ #category : #accessing }
BreaMember >> country: anObject [
country := anObject
]
{ #category : #public }
BreaMember >> countryTemplate [
^ '{{#country}}
<tr>
<td class="mdl-data-table__cell--non-numeric"><b>Country</b></td>
<td class="mdl-data-table__cell--non-numeric">{{.}}</td>
</tr>
{{/country}}' asMustacheTemplate value: self
]
{ #category : #helpers }
BreaMember >> createTestUser [
^ self class new
givenName: 'Test';
familyName: 'User';
country: 'Neverland';
memberOf: 'HackBo' withWebsite: 'http://hackbo.co/';
memberOf: 'mutabiT' withWebsite: 'http://mutabit.com/';
website: 'http://test.user';
twitter: '@offrayLC';
email: 'iam@test.user';
tags: 'just, a lot, of words, separated, by commas'.
]
{ #category : #accessing }
BreaMember >> email [
^ email
]
{ #category : #accessing }
BreaMember >> email: anEmailAddress [
email := (SHA1 new hashMessage: anEmailAddress) hex
]
{ #category : #accessing }
BreaMember >> facebook [
^ self webPresence facebook.
]
{ #category : #accessing }
BreaMember >> facebook: aProfileName [
aProfileName = ''
ifTrue: [ self webPresence facebook: nil ]
ifFalse: [ self webPresence facebook: aProfileName ]
]
{ #category : #public }
BreaMember >> facebookTemplate [
^ '{{#facebook}}
<tr>
<td class="mdl-data-table__cell--non-numeric">
<b>Facebook</b></td>
<td class="mdl-data-table__cell--non-numeric">
<a href="https://facebook.com/{{.}}">
{{.}}</a></td>
</tr>
{{/facebook}}' asMustacheTemplate value: self
]
{ #category : #accessing }
BreaMember >> familyName [
^ familyName
]
{ #category : #accessing }
BreaMember >> familyName: anObject [
familyName := anObject
]
{ #category : #helpers }
BreaMember >> fullName [
^ self givenName asLowercase, '-', self familyName asLowercase
]
{ #category : #accessing }
BreaMember >> getGenericProfilePicture [
"Other considered avatars where:
'https://upload.wikimedia.org/wikipedia/commons/1/1e/Default-avatar.jpg'"
self picture: 'https://www.jamf.com/jamf-nation/img/default-avatars/generic-user.png'.
^ picture
]
{ #category : #accessing }
BreaMember >> givenName [
^ givenName
]
{ #category : #accessing }
BreaMember >> givenName: anObject [
givenName := anObject
]
{ #category : #public }
BreaMember >> head [
^ '<head>', self headMeta, self headTitle, self headStyles,'</head>'
]
{ #category : #utility }
BreaMember >> headMeta [
^ '<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="description" content="A portfolio template that uses Material Design Lite.">
<meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0">'
]
{ #category : #utility }
BreaMember >> headStyles [
^ '
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:regular,bold,italic,thin,light,bolditalic,black,medium&amp;lang=en">
<link rel="stylesheet" href="https://code.getmdl.io/1.3.0/material.grey-pink.min.css" />
<link rel="stylesheet" href="http://mutabit.com/repos.fossil/gig/doc/tip/styles.css" />
<link rel="stylesheet" href="styles.css" />
<link rel="stylesheet" href="https://fonts.googleapis.com/icon?family=Material+Icons">
'
]
{ #category : #utility }
BreaMember >> headTitle [
^ self headTitled: 'GIG: Network'
]
{ #category : #utility }
BreaMember >> headTitled: aString [
^ '<title>', aString ,'</title>'
]
{ #category : #public }
BreaMember >> html [
"I show the member profile as HTML"
^ self head, self htmlOutput
]
{ #category : #public }
BreaMember >> htmlInput [
"I capture data in a HTML Form and use it to create a new BreaMember"
^ '
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="description" content="A portfolio template that uses Material Design Lite.">
<meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0">
<title>Add Member | GIG Network</title>
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:regular,bold,italic,thin,light,bolditalic,black,medium&amp;lang=en">
<link rel="stylesheet" href="https://code.getmdl.io/1.3.0/material.grey-pink.min.css" />
<link rel="stylesheet" href="styles.css" />
<link rel="stylesheet" href="https://fonts.googleapis.com/icon?family=Material+Icons">
</head>
<body>
<div class="mdl-layout mdl-js-layout mdl-layout--fixed-header">
<div class="mdl-layout__drawer mdl-layout--small-screen-only">
<nav class="mdl-navigation mdl-typography--body-1-force-preferred-font">
<a class="mdl-navigation__link is-active" href="index.html">Portfolio</a>
<a class="mdl-navigation__link" href="blog.html">Blog</a>
<a class="mdl-navigation__link" href="about.html">About</a>
<a class="mdl-navigation__link" href="contact.html">Contact</a>
</nav>
</div>
<main class="mdl-layout__content">
<div class="mdl-grid portfolio-max-width portfolio-contact">
<div class="mdl-cell mdl-cell--12-col mdl-card mdl-shadow--4dp">
<div class="mdl-card__title">
<h2 class="mdl-card__title-text">Add new member</h2>
</div>
<div class="mdl-card__supporting-text">
<p>
Fill out the form.
The fields preceded by [*] are obligatory.
</p>
<form enctype="application/x-www-form-urlencoded" action="summit" method="POST" class="">
<div class="mdl-textfield mdl-js-textfield mdl-textfield--floating-label">
<input class="mdl-textfield__input" pattern="[A-Z,a-z, ]*" type="text" name="givenName">
<label class="mdl-textfield__label" for="givenName">[*]Given Name...</label>
<span class="mdl-textfield__error">Letters and spaces only</span>
</div>
<div class="mdl-textfield mdl-js-textfield mdl-textfield--floating-label">
<input class="mdl-textfield__input" pattern="[A-Z,a-z, ]*" type="text" name="familyName">
<label class="mdl-textfield__label" for="familyName">[*]Family Name...</label>
<span class="mdl-textfield__error">Letters and spaces only</span>
</div><br>
<div class="mdl-textfield mdl-js-textfield mdl-textfield--floating-label">
<input class="mdl-textfield__input" type="text" name="email">
<label class="mdl-textfield__label" for="email">[*]Email...</label>
</div>
<div class="mdl-textfield mdl-js-textfield mdl-textfield--floating-label">
<input class="mdl-textfield__input" pattern="[A-Z,a-z, ]*" type="text" name="country">
<label class="mdl-textfield__label" for="country">[*]Country...</label>
<span class="mdl-textfield__error">Letters and spaces only</span>
</div><br>
<div class="mdl-textfield mdl-js-textfield mdl-textfield--floating-label">
<input class="mdl-textfield__input" pattern="[A-Z,a-z, ]*" type="text" name="organizations">
<label class="mdl-textfield__label" for="organizations">
[*]Organization(s) (separated with commas)</label>
<span class="mdl-textfield__error">Letters and spaces only</span>
</div><br>
<div class="mdl-textfield mdl-js-textfield mdl-textfield--floating-label">
<input class="mdl-textfield__input" type="text" name="picture">
<label class="mdl-textfield__label" for="website">Profile picture url...</label>
</div>
<div class="mdl-textfield mdl-js-textfield mdl-textfield--floating-label">
<input class="mdl-textfield__input" type="text" name="website">
<label class="mdl-textfield__label" for="website">Personal website...</label>
</div><br>
<div class="mdl-textfield mdl-js-textfield mdl-textfield--floating-label">
<input class="mdl-textfield__input" type="text" name="twitter">
<label class="mdl-textfield__label" for="twitter">Twitter...</label>
</div>
<div class="mdl-textfield mdl-js-textfield mdl-textfield--floating-label">
<input class="mdl-textfield__input" type="text" name="facebook">
<label class="mdl-textfield__label" for="facebook">Facebook...</label>
</div><br>
<div class="mdl-textfield mdl-js-textfield mdl-textfield--floating-label">
<textarea class="mdl-textfield__input" type="text" rows="5" name="tags"></textarea>
<label class="mdl-textfield__label" for="tags">Tags (separated with commas)...</label>
</div>
<p>
<button class="mdl-button mdl-js-button mdl-button--raised mdl-js-ripple-effect
mdl-button--accent" type="submit" value="Submit">
Submit
</button>
</p>
</form>
</div>
</div>
</div>
<footer class="mdl-mini-footer">
<div class="mdl-mini-footer__left-section">
<div class="mdl-logo">Simple portfolio website</div>
</div>
<div class="mdl-mini-footer__right-section">
<ul class="mdl-mini-footer__link-list">
<li><a href="#">Help</a></li>
<li><a href="#">Privacy & Terms</a></li>
</ul>
</div>
</footer>
</main>
</div>
<script src="https://code.getmdl.io/1.3.0/material.min.js"></script>
</body>
</html>
'
]
{ #category : #public }
BreaMember >> htmlOutput [
^ self htmlOutputTemplate asMustacheTemplate value: self
]
{ #category : #public }
BreaMember >> htmlOutputTemplate [
"I show the member profile as HTML"
^ '<div class="mdl-grid portfolio-max-width">
<div class="mdl-cell mdl-card mdl-shadow--4dp portfolio-card">
<div class="mdl-card__title">
<h2 class="mdl-card__title-text">{{givenName}} {{familyName}}</h2>
</div>
<div class="mdl-card__media">
<img class="article-image"
src="{{picture}}"
border="0" alt="">
</div>
<div class="mdl-card__supporting-text">
<table class="mdl-data-table mdl-js-data-table">
<tbody>
<tr>
<td class="mdl-data-table__cell--non-numeric"><b>Name</b></td>
<td class="mdl-data-table__cell--non-numeric">{{givenName}} {{familyName}}</td>
</tr>',
self countryTemplate,
self organizationsTemplate,
self websiteTemplate,
self twitterTemplate,
self facebookTemplate,
self tagsTemplate,
'
</tbody>
</table>
</div>
<div class="mdl-card__actions mdl-card--border">
<a class="mdl-button mdl-button--colored mdl-js-button
mdl-js-ripple-effect mdl-button--accent"
href="portfolio-example01.html">Read more</a>
</div>
</div>
</div>
'
]
{ #category : #accessing }
BreaMember >> instagram [
^ self webPresence instagram.
]
{ #category : #accessing }
BreaMember >> instagram: aProfileName [
self webPresence instagram: aProfileName
]
{ #category : #accessing }
BreaMember >> memberOf: anOrgName [
self organizations add:
(BreaOrganization new name: anOrgName)
]
{ #category : #accessing }
BreaMember >> memberOf: anOrgName withWebsite: aUrl [
self organizations add:
(BreaOrganization new
name: anOrgName;
website: aUrl)
]
{ #category : #accessing }
BreaMember >> organizations [
^ organizations ifNil: [ organizations := OrderedCollection new ]
]
{ #category : #accessing }
BreaMember >> organizations: anOrgListOrName [
anOrgListOrName splitOn: ',' do: [ :each | self memberOf: each ]
]
{ #category : #public }
BreaMember >> organizationsTemplate [
^ '
<tr>
<td class="mdl-data-table__cell--non-numeric"><b>Organization(s)</b></td>
<td class="mdl-data-table__cell--non-numeric">
{{#organizations}}
<a href="{{website}}">{{name}}</a>
{{/organizations}}
</td>
</tr>' asMustacheTemplate value: self
]
{ #category : #accessing }
BreaMember >> password [
^ password
]
{ #category : #accessing }
BreaMember >> password: anObject [
password := anObject
]
{ #category : #accessing }
BreaMember >> picture [
^ picture ifNil: [ ^ self getGenericProfilePicture ]
]
{ #category : #accessing }
BreaMember >> picture: anImageFilePath [
picture := anImageFilePath
]
{ #category : #helpers }
BreaMember >> renderTestUserAsHtml [
^ self class new createTestUser html
]
{ #category : #'server handling' }
BreaMember >> storeInto: aFileDirectory [
| folder file |
folder := (aFileDirectory asFileReference / self fullName) ensureCreateDirectory.
file := (folder / 'info.ston') ensureCreateFile.
file writeStreamDo: [:stream |
(STON writer on: stream)
newLine: String crlf;
prettyPrint: true;
nextPut: self]
]
{ #category : #accessing }
BreaMember >> tags [
^ tags
]
{ #category : #accessing }
BreaMember >> tags: anObject [
tags := anObject
]
{ #category : #public }
BreaMember >> tagsTemplate [
^ '{{#tags}}
<tr>
<td colspan="2"; style="text-align:left">
<b>Tags</b><br>
{{.}}
</td>
</tr>
{{/tags}}' asMustacheTemplate value: self
]
{ #category : #accessing }
BreaMember >> twitter [
^ self webPresence twitter.
]
{ #category : #accessing }
BreaMember >> twitter: aProfileName [
aProfileName = ''
ifTrue: [ self webPresence twitter: nil ]
ifFalse: [ self webPresence twitter: aProfileName ]
]
{ #category : #public }
BreaMember >> twitterTemplate [
^ '{{#twitter}}
<tr>
<td class="mdl-data-table__cell--non-numeric">
<b>Twitter</b></td>
<td class="mdl-data-table__cell--non-numeric">
<a href="https://twitter.com/{{.}}">
{{.}}</a></td>
</tr>
{{/twitter}}' asMustacheTemplate value: self
]
{ #category : #accessing }
BreaMember >> webPresence [
^ webPresence ifNil: [ webPresence := BreaWebPresence new ]
]
{ #category : #accessing }
BreaMember >> webPresence: anObject [
webPresence := anObject
]
{ #category : #accessing }
BreaMember >> website [
^ self webPresence website.
]
{ #category : #accessing }
BreaMember >> website: anUrl [
self webPresence website: anUrl
]
{ #category : #public }
BreaMember >> websiteTemplate [
^ '{{#website}}
<tr>
<td class="mdl-data-table__cell--non-numeric"><b>Website</b></td>
<td class="mdl-data-table__cell--non-numeric">
<a href="{{.}}">{{.}}</a>
</td>
{{/website}}' asMustacheTemplate value: self
]

View File

@ -1,8 +0,0 @@
"
A BreaMemberTest is a test class for testing the behavior of BreaMember
"
Class {
#name : #BreaMemberTest,
#superclass : #TestCase,
#category : #'Brea-Tests'
}

View File

@ -1,32 +0,0 @@
"
I store the places a BreaMember is affiliated to.
"
Class {
#name : #BreaOrganization,
#superclass : #Object,
#instVars : [
'name',
'website'
],
#category : #Brea
}
{ #category : #accessing }
BreaOrganization >> name [
^ name
]
{ #category : #accessing }
BreaOrganization >> name: anObject [
name := anObject
]
{ #category : #accessing }
BreaOrganization >> website [
^ website
]
{ #category : #accessing }
BreaOrganization >> website: anObject [
website := anObject
]

View File

@ -1,250 +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 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
]
{ #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 |
"(self file isMarkdown and: [ self bodyTag isNil ]) ifTrue: [ ^ self ]".
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 : #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 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
]

View File

@ -1,89 +0,0 @@
"
I define a [Mustache][1] template and how it is used to create
derivate output files combining it with particular data sources.
[1]: https://mustache.github.io/
"
Class {
#name : #BreaTemplate,
#superclass : #Object,
#instVars : [
'template',
'data',
'location',
'queries',
'outputs'
],
#category : #Brea
}
{ #category : #adding }
BreaTemplate >> addDataSourceNamed: name with: source [
self
data at: name put: source.
self data.
]
{ #category : #accessing }
BreaTemplate >> data [
^ data ifNil: [ data := Dictionary new ]
]
{ #category : #accessing }
BreaTemplate >> data: aDictionary [
"Each item in the dictionary is a unique alias (as key) and a data location (as value),
usually on the web.
Alias and locations are used later to define data queries to feed into templates."
data := aDictionary
]
{ #category : #accessing }
BreaTemplate >> location [
^ location
]
{ #category : #accessing }
BreaTemplate >> location: aFolderPath [
"This is the place where a template and its derivate files are located.
A shared location is an easy approach to start with and creates more explicit
relation between derived files and templates.
Eventually some re-mapping or re-routing could be used so templates and their outputs
could be further apart."
location := aFolderPath
]
{ #category : #accessing }
BreaTemplate >> outputs [
^ outputs
]
{ #category : #accessing }
BreaTemplate >> outputs: fileNamesList [
"fileNamesList contain the files which are derived from the template."
outputs := fileNamesList
]
{ #category : #accessing }
BreaTemplate >> queries [
^ queries ifNil: [ queries := Dictionary new ]
]
{ #category : #accessing }
BreaTemplate >> queries: aDictionary [
"aDictionary contains the alias for the query as key and a block that will be executed
on a particular data source, as value."
queries := aDictionary
]
{ #category : #accessing }
BreaTemplate >> template [
^ template
]
{ #category : #accessing }
BreaTemplate >> template: aFileName [
"I provide the name of the mustache base template.
The file can have any name, but by convention they end in '.mus.html' 'mus.md' and
so on."
template := aFileName
]

View File

@ -1,204 +1,204 @@
"
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',
'provider',
'url',
'preview',
'license',
'folder',
'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 : #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 : #'as yet unclassified' }
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 >> 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',
'provider',
'url',
'preview',
'license',
'folder',
'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 : #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 : #'as yet unclassified' }
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 >> url [
^ url ifNil: [ url := self class downloadLinks at: self name. ]
]
{ #category : #accessing }
BreaTheme >> url: anObject [
url := anObject
]

View File

@ -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.
]

View File

@ -1,54 +0,0 @@
"
I store the common forms of web presence a BreaMember can have online.
"
Class {
#name : #BreaWebPresence,
#superclass : #Object,
#instVars : [
'website',
'twitter',
'facebook',
'instagram'
],
#category : #Brea
}
{ #category : #accessing }
BreaWebPresence >> facebook [
^ facebook
]
{ #category : #accessing }
BreaWebPresence >> facebook: anObject [
facebook := anObject
]
{ #category : #accessing }
BreaWebPresence >> instagram [
^ instagram
]
{ #category : #accessing }
BreaWebPresence >> instagram: anObject [
instagram := anObject
]
{ #category : #accessing }
BreaWebPresence >> twitter [
^ twitter
]
{ #category : #accessing }
BreaWebPresence >> twitter: anObject [
twitter := anObject
]
{ #category : #accessing }
BreaWebPresence >> website [
^ website
]
{ #category : #accessing }
BreaWebPresence >> website: anObject [
website := anObject
]

View File

@ -1,292 +0,0 @@
"
I model the fossil repository where public data is stored for the
building of this web site.
"
Class {
#name : #BreaWebsite,
#superclass : #Object,
#instVars : [
'fossilRepo',
'server',
'template',
'title'
],
#category : #Brea
}
{ #category : #utility }
BreaWebsite class >> availableTemplates [
self templates keys.
]
{ #category : #utility }
BreaWebsite class >> demoFolder [
^ FileLocator temp asFileReference / 'BreaDemo'.
]
{ #category : #example }
BreaWebsite class >> example [
"I run an example mockup of a website using Brea.
After runing me, go to:
- http://localhost:8080/demo
- http://localhost:8080/members/test
- http://localhost:8080/members/add "
self new
local: FileLocator temp asFileReference / 'BreaDemo';
template: 'portafolio';
downloadTemplate;
modifyTemplate;
start
]
{ #category : #example }
BreaWebsite class >> exampleDashboard [
"I run an example mockup of a website using Brea.
After runing me, go to: http://localhost:8080/demo "
self new
local: FileLocator temp asFileReference / 'BreaDemo';
template: 'dashboard';
downloadTemplate;
modifyTemplate;
start
]
{ #category : #'server handling' }
BreaWebsite class >> stopAll [
"I stop the server"
Teapot stopAll
]
{ #category : #utility }
BreaWebsite class >> templates [
"I provide the supported MDL templates taken from: https://getmdl.io/templates/"
^ Dictionary new
at: 'portafolio' put: 'https://code.getmdl.io/1.3.0/mdl-template-portfolio.zip';
at: 'dashboard' put: 'https://code.getmdl.io/1.3.0/mdl-template-dashboard.zip';
yourself.
]
{ #category : #utility }
BreaWebsite >> defaultTemplate [
self template
ifNil: [
self template: 'portafolio' ].
^ self template.
]
{ #category : #utility }
BreaWebsite >> downloadDefaultTemplate [
self downloadTemplateNamed: self defaultTemplate Into: self local.
]
{ #category : #utility }
BreaWebsite >> downloadDefaultTemplateInto: aDirectory [
| remoteUrl templatesFile |
aDirectory ensureDeleteAll.
aDirectory ensureCreateDirectory.
remoteUrl := self class templates at: self template.
GrafoscopioUtils
downloadingFrom: remoteUrl
withMessage: 'Downloading templates'
into: FileLocator temp asFileReference.
templatesFile := FileLocator temp asFileReference / (remoteUrl splitOn: '/') last.
ZipArchive new
readFrom: templatesFile;
extractAllTo: aDirectory
]
{ #category : #utility }
BreaWebsite >> downloadTemplate [
self downloadTemplateNamed: self template Into: self local.
]
{ #category : #utility }
BreaWebsite >> downloadTemplateNamed: aName Into: aDirectory [
"aName: String aDirectory: aFileLocation"
| remoteUrl templatesFile localDirectory |
localDirectory := aDirectory asFileReference.
localDirectory ensureDeleteAll.
localDirectory ensureCreateDirectory.
remoteUrl := self class templates at: aName.
GrafoscopioUtils
downloadingFrom: remoteUrl
withMessage: 'Downloading templates'
into: FileLocator temp asFileReference.
templatesFile := FileLocator temp asFileReference / (remoteUrl splitOn: '/') last.
ZipArchive new
readFrom: templatesFile;
extractAllTo: localDirectory
]
{ #category : #accessing }
BreaWebsite >> fossilRepo [
^ fossilRepo ifNil: [ fossilRepo := FossilRepo new ]
]
{ #category : #accessing }
BreaWebsite >> fossilRepo: aFossilRepo [
fossilRepo := aFossilRepo
]
{ #category : #utility }
BreaWebsite >> local [
^ self fossilRepo local
]
{ #category : #'server handling' }
BreaWebsite >> local: aFilePath [
"I define the local storage of the Fossil repository.
For the moment aFilePath must be an absolute "
| localSite |
aFilePath asFileReference exists
ifFalse: [
localSite := (FileLocator temp / 'breaSite') ensureCreateDirectory.
self fossilRepo local: localSite fullName ]
ifTrue: [ self fossilRepo local: aFilePath ].
]
{ #category : #'server handling' }
BreaWebsite >> local: aFilePath remote: anUrl [
"I define the local and remote storages of the Fossil repository"
self remote: anUrl.
self local: aFilePath
]
{ #category : #utility }
BreaWebsite >> modifyDashboardTemplate [
"I replace default templates with versioned files, that contains Mustache tags used
for examples."
"This part should be factorized and integrated into a single method tha modifies any
template, instead of repeated the code of modifyPortafolioTemplate."
| remoteRepoUrl files |
remoteRepoUrl := 'http://mutabit.com/repos.fossil/brea/templates/portaforlio'.
files := #('index.html' 'styles.css').
"files do: [ :file |
GrafoscopioUtils
downloadingFrom: remoteRepoUrl, 'doc/tip/', file
withMessage: 'Replacing ', file
into: self local ]"
]
{ #category : #utility }
BreaWebsite >> modifyPortafolioTemplate [
"I replace default templates with versioned files, that contains Mustache tags used
for examples."
| remoteRepoUrl files |
remoteRepoUrl := 'http://mutabit.com/repos.fossil/gig/'.
files := #('index.html' 'styles.css').
files do: [ :file |
GrafoscopioUtils
downloadingFrom: remoteRepoUrl, 'doc/tip/', file
withMessage: 'Replacing ', file
into: self local ]
]
{ #category : #utility }
BreaWebsite >> modifyTemplate [
"I replace default templates with versioned files, that contains Mustache tags used
for examples."
self template = 'portafolio' ifTrue: [ self modifyPortafolioTemplate ].
self template = 'dashboard' ifTrue: [ self modifyDashboardTemplate ]
]
{ #category : #'input processing' }
BreaWebsite >> processNewMember: request [
| member badRequest |
badRequest := [ ^ ZnResponse badRequest: request ].
(request hasEntity
and: [ request contentType matches: ZnMimeType applicationFormUrlEncoded ])
ifFalse: [ badRequest ].
member := BreaMember new
givenName: (request at: #givenName);
familyName: (request at: #familyName);
email: (request at: #email);
country: (request at: #country);
organizations: (request at: #organizations);
picture: (request at: #picture);
website: (request at: #website);
twitter: (request at: #twitter);
facebook: (request at: #facebook);
tags: (request at: #tags).
self store: member.
^ 'New member stored!'
]
{ #category : #'server handling' }
BreaWebsite >> remote: anUrl [
"I define the remote storage of the Fossil repository"
self remote: anUrl.
]
{ #category : #'server handling' }
BreaWebsite >> routes [
"I define how the website behaves accordingly to particular routes."
self server
serveStatic: 'demo' from: (self local);
GET: 'members/test' -> [ :req | BreaMember new renderTestUserAsHtml ];
GET: 'members/add' -> [ :req | BreaMember new htmlInput ];
POST: 'members/summit' -> [ :req | self processNewMember: req ]
]
{ #category : #accessing }
BreaWebsite >> server [
^ server ifNil: [ self setup ]
]
{ #category : #accessing }
BreaWebsite >> server: anObject [
server := anObject
]
{ #category : #accessing }
BreaWebsite >> setup [
^ server := Teapot
configure:
{(#port -> 8080).
(#debugMode -> true)}
]
{ #category : #'server handling' }
BreaWebsite >> start [
"I define the config and start the server"
self routes.
self server start
]
{ #category : #'server handling' }
BreaWebsite >> storageFor: anObject [
"I define the places where local storage is done for several types of objects"
anObject class = BreaMember
ifTrue: [ ^ self local asFileReference / 'members' ].
^ self
]
{ #category : #'server handling' }
BreaWebsite >> store: anObject [
"I store different kind of objects in the website repository.
For the moment I will only store BreaMembers, but as long as new
objects will emerge, I will specialize other ways of storage."
anObject storeInto: (self storageFor: anObject)
]
{ #category : #accessing }
BreaWebsite >> template [
^ template
]
{ #category : #accessing }
BreaWebsite >> template: aTemplateName [
"I define the default template to be used for the Brea website.
Available options are at self class templates."
template := aTemplateName
]
{ #category : #accessing }
BreaWebsite >> title [
^ title
]
{ #category : #accessing }
BreaWebsite >> title: anObject [
title := anObject
]

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
"
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') )
]

View File

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