Improved multiplatform support and adding more replacements for Latin characters.

This commit is contained in:
Offray Vladimir Luna Cárdenas 2020-12-18 09:54:09 -08:00
parent d875029940
commit 5d68e79c2b
14 changed files with 1495 additions and 1492 deletions

View File

@ -1,201 +1,201 @@
" "
I provide support for external helper apps for Grafoscopio, publishing, collaboration I provide support for external helper apps for Grafoscopio, publishing, collaboration
and data management. and data management.
" "
Class { Class {
#name : #ExternalApp, #name : #ExternalApp,
#superclass : #Object, #superclass : #Object,
#instVars : [ #instVars : [
'name', 'name',
'url', 'url',
'downloadUrl', 'downloadUrl',
'description', 'description',
'sha1', 'sha1',
'md5', 'md5',
'binaryLocation' 'binaryLocation'
], ],
#category : #'Grafoscopio-Utils' #category : #'Grafoscopio-Utils'
} }
{ #category : #installation } { #category : #installation }
ExternalApp class >> compareHashFor: aFileName with: aSHAString [ ExternalApp class >> compareHashFor: aFileName with: aSHAString [
aSHAString = (SHA1 new hashMessage: aFileName asFileReference binaryReadStream contents) hex aSHAString = (SHA1 new hashMessage: aFileName asFileReference binaryReadStream contents) hex
ifFalse: [ ^ false ] ifFalse: [ ^ false ]
ifTrue: [ ^ true ]. ifTrue: [ ^ true ].
] ]
{ #category : #configuration } { #category : #configuration }
ExternalApp class >> configureFossil [ ExternalApp class >> configureFossil [
"Stablish where is located fossil according to the operative system and/or the input of the user" "Stablish where is located fossil according to the operative system and/or the input of the user"
| fileStream fossil | | fileStream fossil |
fileStream := UIManager default fileOpen: 'Path to the fossil program binary'. fileStream := UIManager default fileOpen: 'Path to the fossil program binary'.
fileStream isNil ifTrue: [ ^nil ]. fileStream isNil ifTrue: [ ^nil ].
fossil := fileStream name asFileReference fullName. fossil := fileStream name asFileReference fullName.
] ]
{ #category : #configuration } { #category : #configuration }
ExternalApp class >> configurePandoc [ ExternalApp class >> configurePandoc [
"Stablish where is located pandoc according to the operative system and/or the input of the user" "Stablish where is located pandoc according to the operative system and/or the input of the user"
| fileStream pandoc | | fileStream pandoc |
fileStream := UIManager default fileOpen: 'Path to pandoc program binary'. fileStream := UIManager default fileOpen: 'Path to pandoc program binary'.
fileStream isNil ifTrue: [ ^nil ]. fileStream isNil ifTrue: [ ^nil ].
pandoc := fileStream name asFileReference fullName. pandoc := fileStream name asFileReference fullName.
] ]
{ #category : #installation } { #category : #installation }
ExternalApp class >> installSQLite32Bits [ ExternalApp class >> installSQLite32Bits [
"I dowload the SQLite binary for the hosting platform, uncompress it and made it available as with the name "I dowload the SQLite binary for the hosting platform, uncompress it and made it available as with the name
NBSQLite is wating for" NBSQLite is wating for"
| packageUrl sha1 localPath packageZipName unzippedFolder | | packageUrl sha1 localPath packageZipName unzippedFolder |
localPath := FileSystem disk workingDirectory parent / 'bin'. localPath := FileSystem disk workingDirectory parent / 'bin'.
Smalltalk platform name = 'unix' Smalltalk platform name = 'unix'
ifTrue: [ ifTrue: [
packageUrl := 'http://sqlite.org/2016/sqlite-tools-linux-x86-3110100.zip'. packageUrl := 'http://sqlite.org/2016/sqlite-tools-linux-x86-3110100.zip'.
sha1 := '21a80cefa91d5de50256996fc55990a027c350fd']. sha1 := '21a80cefa91d5de50256996fc55990a027c350fd'].
Smalltalk platform name = 'Win32' Smalltalk platform name = 'Win32'
ifTrue: [ ifTrue: [
packageUrl := 'http://sqlite.org/2016/sqlite-dll-win32-x86-3110100.zip'. packageUrl := 'http://sqlite.org/2016/sqlite-dll-win32-x86-3110100.zip'.
sha1 := 'cfd6f64ba1fb5de1ccf8321e29764c690c25e0a0']. sha1 := 'cfd6f64ba1fb5de1ccf8321e29764c690c25e0a0'].
Smalltalk platform name = 'Mac OS' Smalltalk platform name = 'Mac OS'
ifTrue: [ ifTrue: [
packageUrl := 'http://sqlite.org/2016/sqlite-tools-osx-x86-3110100.zip'. packageUrl := 'http://sqlite.org/2016/sqlite-tools-osx-x86-3110100.zip'.
sha1 := 'c78b3b92bd37554694d2f73dbecfef1902c15ba7']. sha1 := 'c78b3b92bd37554694d2f73dbecfef1902c15ba7'].
self isSQLite32BitsInstalled self isSQLite32BitsInstalled
ifTrue: [ self inform: 'SQLite ya está instalado en el sistema' ] ifTrue: [ self inform: 'SQLite ya está instalado en el sistema' ]
ifFalse: [ ifFalse: [
GrafoscopioBrowser GrafoscopioBrowser
downloadingFrom: packageUrl downloadingFrom: packageUrl
withMessage: 'Descargando SQLite...' withMessage: 'Descargando SQLite...'
into: localPath asFileReference. into: localPath asFileReference.
packageZipName := (packageUrl splitOn: '/') last. packageZipName := (packageUrl splitOn: '/') last.
sha1 = (SHA1 new hashMessage: (localPath / packageZipName) asFileReference binaryReadStream contents) hex sha1 = (SHA1 new hashMessage: (localPath / packageZipName) asFileReference binaryReadStream contents) hex
ifFalse: [ self inform: 'SQLite: Descarga no exitosa. ifFalse: [ self inform: 'SQLite: Descarga no exitosa.
Por favor intente el procedimiento de nuevo o manualmente'] Por favor intente el procedimiento de nuevo o manualmente']
ifTrue: [ ifTrue: [
ZipArchive new ZipArchive new
readFrom: (localPath / packageZipName); readFrom: (localPath / packageZipName);
extractAllTo: localPath asFileReference. extractAllTo: localPath asFileReference.
unzippedFolder := packageZipName copyReplaceAll: '.zip' with: ''. unzippedFolder := packageZipName copyReplaceAll: '.zip' with: ''.
(localPath / unzippedFolder ) children do: (localPath / unzippedFolder ) children do:
[:file | file moveTo: (localPath / file basenameWithIndicator)]. [:file | file moveTo: (localPath / file basenameWithIndicator)].
(localPath / 'sqlite3') copyTo: (localPath / 'libsqlite3.so'). (localPath / 'sqlite3') copyTo: (localPath / 'libsqlite3.so').
(localPath / unzippedFolder ) deleteAll. (localPath / unzippedFolder ) deleteAll.
self inform: 'SQLite instalado existosammente!' self inform: 'SQLite instalado existosammente!'
]. ].
"Cleaning leftovers" "Cleaning leftovers"
(localPath / packageZipName) delete (localPath / packageZipName) delete
] ]
] ]
{ #category : #configuration } { #category : #configuration }
ExternalApp class >> installSQLite32BitsUI [ ExternalApp class >> installSQLite32BitsUI [
"I verify if SQLite for 32 bits is installed in the proper location. If yes, I inform that. If not, "I verify if SQLite for 32 bits is installed in the proper location. If yes, I inform that. If not,
I made the installation" I made the installation"
| install | | install |
install := (UIManager default install := (UIManager default
confirm: '¿Desea instalar el motor de base de datos (SQLite)?' confirm: '¿Desea instalar el motor de base de datos (SQLite)?'
label: 'Instalar base de datos?'). label: 'Instalar base de datos?').
install ifTrue: [self installSQLite32Bits] install ifTrue: [self installSQLite32Bits]
] ]
{ #category : #installation } { #category : #installation }
ExternalApp class >> isSQLite32BitsInstalled [ ExternalApp class >> isSQLite32BitsInstalled [
"I verify if the SQLite binary for the hosting platform is installed" "I verify if the SQLite binary for the hosting platform is installed"
^ (FileSystem disk workingDirectory parent / 'bin' / 'libsqlite3.so') asFileReference exists ^ (FileSystem disk workingDirectory parent / 'bin' / 'libsqlite3.so') asFileReference exists
] ]
{ #category : #configuration } { #category : #configuration }
ExternalApp class >> pandoc [ ExternalApp class >> pandoc [
"I define where the pandoc external app is located" "I define where the pandoc external app is located"
| app | | app |
app := ExternalApp new app := ExternalApp new
name: 'pandoc'; name: 'pandoc';
url: 'http://pandoc.org'; url: 'http://pandoc.org';
description: 'Pandoc is a free and open-source software document converter, widely used as a writing tool (especially by scholars) and as a basis for publishing workflows. It was originally created by John MacFarlane, a philosophy professor at the University of California, Berkeley. (from https://en.wikipedia.org/wiki/Pandoc)'. description: 'Pandoc is a free and open-source software document converter, widely used as a writing tool (especially by scholars) and as a basis for publishing workflows. It was originally created by John MacFarlane, a philosophy professor at the University of California, Berkeley. (from https://en.wikipedia.org/wiki/Pandoc)'.
app binaryLocation: '/usr/bin/pandoc' asFileReference. app binaryLocation: '/usr/bin/pandoc' asFileReference.
^ app ^ app
] ]
{ #category : #accessing } { #category : #accessing }
ExternalApp >> binaryLocation [ ExternalApp >> binaryLocation [
^ binaryLocation ^ binaryLocation
] ]
{ #category : #accessing } { #category : #accessing }
ExternalApp >> binaryLocation: anObject [ ExternalApp >> binaryLocation: anObject [
binaryLocation := anObject binaryLocation := anObject
] ]
{ #category : #accessing } { #category : #accessing }
ExternalApp >> description [ ExternalApp >> description [
^ description ^ description
] ]
{ #category : #accessing } { #category : #accessing }
ExternalApp >> description: anObject [ ExternalApp >> description: anObject [
description := anObject description := anObject
] ]
{ #category : #accessing } { #category : #accessing }
ExternalApp >> downloadUrl [ ExternalApp >> downloadUrl [
^ downloadUrl ^ downloadUrl
] ]
{ #category : #accessing } { #category : #accessing }
ExternalApp >> downloadUrl: anObject [ ExternalApp >> downloadUrl: anObject [
downloadUrl := anObject downloadUrl := anObject
] ]
{ #category : #accessing } { #category : #accessing }
ExternalApp >> md5 [ ExternalApp >> md5 [
^ md5 ^ md5
] ]
{ #category : #accessing } { #category : #accessing }
ExternalApp >> md5: anObject [ ExternalApp >> md5: anObject [
md5 := anObject md5 := anObject
] ]
{ #category : #accessing } { #category : #accessing }
ExternalApp >> name [ ExternalApp >> name [
^ name ^ name
] ]
{ #category : #accessing } { #category : #accessing }
ExternalApp >> name: anObject [ ExternalApp >> name: anObject [
name := anObject name := anObject
] ]
{ #category : #accessing } { #category : #accessing }
ExternalApp >> sha1 [ ExternalApp >> sha1 [
^ sha1 ^ sha1
] ]
{ #category : #accessing } { #category : #accessing }
ExternalApp >> sha1: anObject [ ExternalApp >> sha1: anObject [
sha1 := anObject sha1 := anObject
] ]
{ #category : #accessing } { #category : #accessing }
ExternalApp >> url [ ExternalApp >> url [
^ url ^ url
] ]
{ #category : #accessing } { #category : #accessing }
ExternalApp >> url: anObject [ ExternalApp >> url: anObject [
url := anObject url := anObject
] ]

View File

@ -1,199 +1,199 @@
" "
I model a documentation object for Grafoscopio. I model a documentation object for Grafoscopio.
Documents are stored in a fossil repository and have Documents are stored in a fossil repository and have
relative paths to it. relative paths to it.
" "
Class { Class {
#name : #GrafoscopioDocumentation, #name : #GrafoscopioDocumentation,
#superclass : #Object, #superclass : #Object,
#instVars : [ #instVars : [
'repository', 'repository',
'documents', 'documents',
'localPlace', 'localPlace',
'name' 'name'
], ],
#category : #'Grafoscopio-Utils' #category : #'Grafoscopio-Utils'
} }
{ #category : #updating } { #category : #updating }
GrafoscopioDocumentation class >> documents [ GrafoscopioDocumentation class >> documents [
^ self newDefault documents ^ self newDefault documents
] ]
{ #category : #api } { #category : #api }
GrafoscopioDocumentation class >> download: aFileName [ GrafoscopioDocumentation class >> download: aFileName [
self newDefault download: aFileName self newDefault download: aFileName
] ]
{ #category : #updating } { #category : #updating }
GrafoscopioDocumentation class >> listOutdatedDocs [ GrafoscopioDocumentation class >> listOutdatedDocs [
^ self newDefault listOutdatedDocs ^ self newDefault listOutdatedDocs
] ]
{ #category : #updating } { #category : #updating }
GrafoscopioDocumentation class >> localPlace [ GrafoscopioDocumentation class >> localPlace [
^ self newDefault localPlace ^ self newDefault localPlace
] ]
{ #category : #'instance creation' } { #category : #'instance creation' }
GrafoscopioDocumentation class >> newDefault [ GrafoscopioDocumentation class >> newDefault [
^ self new ^ self new
] ]
{ #category : #updating } { #category : #updating }
GrafoscopioDocumentation class >> update [ GrafoscopioDocumentation class >> update [
^ self newDefault update ^ self newDefault update
] ]
{ #category : #updating } { #category : #updating }
GrafoscopioDocumentation class >> updateAll [ GrafoscopioDocumentation class >> updateAll [
GfUIHelpers docsCollection do: [ :docs | docs update ] GfUIHelpers docsCollection do: [ :docs | docs update ]
] ]
{ #category : #updating } { #category : #updating }
GrafoscopioDocumentation class >> updateAllUI [ GrafoscopioDocumentation class >> updateAllUI [
"Updates documentation (manual, tutorials) from the official repository for a given documentation." "Updates documentation (manual, tutorials) from the official repository for a given documentation."
| update | | update |
update := (UIManager default update := (UIManager default
confirm: 'Do you wish to update the documentation?' confirm: 'Do you wish to update the documentation?'
label: 'Update documentation'). label: 'Update documentation').
update update
ifTrue: [ self updateAll ] ifTrue: [ self updateAll ]
] ]
{ #category : #accessing } { #category : #accessing }
GrafoscopioDocumentation >> addDocument: aFilePath [ GrafoscopioDocumentation >> addDocument: aFilePath [
"I add the document contained in aFilePath (a String) to the list of documents that belong "I add the document contained in aFilePath (a String) to the list of documents that belong
to this collection, taking care of avoiding repetitions" to this collection, taking care of avoiding repetitions"
(self documents includes: aFilePath) ifFalse: [ self documents add: aFilePath ] (self documents includes: aFilePath) ifFalse: [ self documents add: aFilePath ]
] ]
{ #category : #accessing } { #category : #accessing }
GrafoscopioDocumentation >> documents [ GrafoscopioDocumentation >> documents [
^ documents ifNil: [ documents := OrderedCollection new ] ^ documents ifNil: [ documents := OrderedCollection new ]
] ]
{ #category : #accessing } { #category : #accessing }
GrafoscopioDocumentation >> documents: anObject [ GrafoscopioDocumentation >> documents: anObject [
documents := anObject documents := anObject
] ]
{ #category : #updating } { #category : #updating }
GrafoscopioDocumentation >> download: fileNameWithRelativePath [ GrafoscopioDocumentation >> download: fileNameWithRelativePath [
| fileName parentFolder sanitized lastVersion | | fileName parentFolder sanitized lastVersion |
fileName := (fileNameWithRelativePath splitOn: $/) last. fileName := (fileNameWithRelativePath splitOn: $/) last.
sanitized := self repository sanitize: fileNameWithRelativePath. sanitized := self repository sanitize: fileNameWithRelativePath.
lastVersion := self repository lastVersionPath: fileNameWithRelativePath. lastVersion := self repository lastVersionPath: fileNameWithRelativePath.
parentFolder := GrafoscopioUtils parentFolder := GrafoscopioUtils
ensureCreateDirectory: sanitized into: self localPlace. ensureCreateDirectory: sanitized into: self localPlace.
GrafoscopioUtils GrafoscopioUtils
downloadingFrom: self repository remote asString, lastVersion downloadingFrom: self repository remote asString, lastVersion
withMessage: 'Downloading ', fileName withMessage: 'Downloading ', fileName
into: parentFolder into: parentFolder
] ]
{ #category : #updating } { #category : #updating }
GrafoscopioDocumentation >> isFileUpdatedFor: relativeFilePath [ GrafoscopioDocumentation >> isFileUpdatedFor: relativeFilePath [
"I compare if the local and remote copies of a relativeFilePath are updated for the current "I compare if the local and remote copies of a relativeFilePath are updated for the current
documentation and return true if they are and false in any other case" documentation and return true if they are and false in any other case"
| localFile | | localFile |
localFile := self localPlace / relativeFilePath. localFile := self localPlace / relativeFilePath.
localFile exists localFile exists
ifFalse: [ ^ false ] ifFalse: [ ^ false ]
ifTrue: [ ifTrue: [
^ ExternalApp ^ ExternalApp
compareHashFor: localFile compareHashFor: localFile
with: (self repository lastHashNumberFor: relativeFilePath) ] with: (self repository lastHashNumberFor: relativeFilePath) ]
] ]
{ #category : #updating } { #category : #updating }
GrafoscopioDocumentation >> listOutdatedDocs [ GrafoscopioDocumentation >> listOutdatedDocs [
"I return the list of all documentent where the local copy and the remote copy doesn't match" "I return the list of all documentent where the local copy and the remote copy doesn't match"
^ self documents reject: [ :doc | (self isFileUpdatedFor: doc) ] ^ self documents reject: [ :doc | (self isFileUpdatedFor: doc) ]
] ]
{ #category : #accessing } { #category : #accessing }
GrafoscopioDocumentation >> localPlace [ GrafoscopioDocumentation >> localPlace [
^ localPlace. ^ localPlace.
] ]
{ #category : #accessing } { #category : #accessing }
GrafoscopioDocumentation >> localPlace: aFileDirectory [ GrafoscopioDocumentation >> localPlace: aFileDirectory [
localPlace := aFileDirectory. localPlace := aFileDirectory.
self localPlace exists ifFalse: [ self localPlace ensureCreateDirectory ]. self localPlace exists ifFalse: [ self localPlace ensureCreateDirectory ].
] ]
{ #category : #accessing } { #category : #accessing }
GrafoscopioDocumentation >> name [ GrafoscopioDocumentation >> name [
^ name ^ name
] ]
{ #category : #accessing } { #category : #accessing }
GrafoscopioDocumentation >> name: anObject [ GrafoscopioDocumentation >> name: anObject [
name := anObject name := anObject
] ]
{ #category : #accessing } { #category : #accessing }
GrafoscopioDocumentation >> openNotebookAt: index [ GrafoscopioDocumentation >> openNotebookAt: index [
"I open a notebook included with the documentation, located at a given index (anInteger)" "I open a notebook included with the documentation, located at a given index (anInteger)"
| notebookTemp | | notebookTemp |
(index between: 1 and: self documents size) (index between: 1 and: self documents size)
ifFalse: [ ^ self ] ifFalse: [ ^ self ]
ifTrue: [ ifTrue: [
notebookTemp := (self localPlace fullName, '/', (self documents at: index)) asFileReference. notebookTemp := (self localPlace fullName, '/', (self documents at: index)) asFileReference.
notebookTemp exists notebookTemp exists
ifTrue: [GrafoscopioNotebook new openFromFile: notebookTemp] ifTrue: [GrafoscopioNotebook new openFromFile: notebookTemp]
ifFalse: [ self updateUI ]] ifFalse: [ self updateUI ]]
] ]
{ #category : #updating } { #category : #updating }
GrafoscopioDocumentation >> registerIntoDockingBar [ GrafoscopioDocumentation >> registerIntoDockingBar [
"I detect if any of the documents that are part of my collection contains any metadata "I detect if any of the documents that are part of my collection contains any metadata
indicating if they should be registered in the main docking bar, and in such case, I add them." indicating if they should be registered in the main docking bar, and in such case, I add them."
self documents self documents
do: [ :doc | | metadata currentNotebook | do: [ :doc | | metadata currentNotebook |
currentNotebook := GrafoscopioNotebook new loadFromFile: self localPlace / doc. currentNotebook := GrafoscopioNotebook new loadFromFile: self localPlace / doc.
metadata := currentNotebook metadata. metadata := currentNotebook metadata.
metadata ifNotNil: [ metadata ifNotNil: [
metadata metadata
at: 'showOnHelp' at: 'showOnHelp'
ifPresent: [ self error:' missing class grafoscopio docking bar' "GrafoscopioDockingBar addToHelpMenu: currentNotebook" ] ] ] ifPresent: [ self error:' missing class grafoscopio docking bar' "GrafoscopioDockingBar addToHelpMenu: currentNotebook" ] ] ]
] ]
{ #category : #accessing } { #category : #accessing }
GrafoscopioDocumentation >> repository [ GrafoscopioDocumentation >> repository [
^ repository ^ repository
] ]
{ #category : #accessing } { #category : #accessing }
GrafoscopioDocumentation >> repository: aFossilRepo [ GrafoscopioDocumentation >> repository: aFossilRepo [
repository := aFossilRepo repository := aFossilRepo
] ]
{ #category : #updating } { #category : #updating }
GrafoscopioDocumentation >> update [ GrafoscopioDocumentation >> update [
(self listOutdatedDocs) (self listOutdatedDocs)
ifEmpty: [ ifEmpty: [
self inform: 'All documents in the ', self name,' collection are already updated'. self inform: 'All documents in the ', self name,' collection are already updated'.
^ self ] ^ self ]
ifNotEmpty: [:outdatedDocs | ifNotEmpty: [:outdatedDocs |
outdatedDocs do: [ :eachDoc | self download: eachDoc ]. outdatedDocs do: [ :eachDoc | self download: eachDoc ].
self inform: 'Updating of ', self name,' documentation finished.' ] self inform: 'Updating of ', self name,' documentation finished.' ]
] ]
{ #category : #updating } { #category : #updating }
GrafoscopioDocumentation >> updateDocsPlaceUI [ GrafoscopioDocumentation >> updateDocsPlaceUI [
self current localPlace: (UIManager default chooseDirectory: 'Path to the documentation folder') self current localPlace: (UIManager default chooseDirectory: 'Path to the documentation folder')
] ]
{ #category : #updating } { #category : #updating }
GrafoscopioDocumentation >> updateUI [ GrafoscopioDocumentation >> updateUI [
"Updates documentation (manual, tutorials) from the official repository for a given documentation." "Updates documentation (manual, tutorials) from the official repository for a given documentation."
| update | | update |
update := (UIManager default update := (UIManager default
confirm: 'Do you wish to update the ', self name,' documentation?' confirm: 'Do you wish to update the ', self name,' documentation?'
label: 'Update ', self name, ' documentation'). label: 'Update ', self name, ' documentation').
update ifTrue: [ self update ] update ifTrue: [ self update ]
] ]

View File

@ -1,24 +1,24 @@
" "
A GrafoscopioDocumentationTest is a test class for testing the behavior of GrafoscopioDocumentation A GrafoscopioDocumentationTest is a test class for testing the behavior of GrafoscopioDocumentation
" "
Class { Class {
#name : #GrafoscopioDocumentationTest, #name : #GrafoscopioDocumentationTest,
#superclass : #TestCase, #superclass : #TestCase,
#category : #'Grafoscopio-Utils-Tests' #category : #'Grafoscopio-Utils-Tests'
} }
{ #category : #'tests-utility' } { #category : #'tests-utility' }
GrafoscopioDocumentationTest >> defaultTestRepo [ GrafoscopioDocumentationTest >> defaultTestRepo [
"I create a default documentation repository, that is used for several test." "I create a default documentation repository, that is used for several test."
| testRepo | | testRepo |
testRepo := GrafoscopioDocumentation new. testRepo := GrafoscopioDocumentation new.
testRepo repository: (FossilRepo new remote: 'http://mutabit.com/repos.fossil/grafoscopio'); testRepo repository: (FossilRepo new remote: 'http://mutabit.com/repos.fossil/grafoscopio');
localPlace: FileLocator temp asFileReference /'Grafoscopio'; localPlace: FileLocator temp asFileReference /'Grafoscopio';
name: 'test Repo'. name: 'test Repo'.
testRepo testRepo
addDocument: 'Docs/Es/Tutoriales/tutorial.ston'; addDocument: 'Docs/Es/Tutoriales/tutorial.ston';
addDocument: 'Docs/En/Books/Manual/manual.ston'; addDocument: 'Docs/En/Books/Manual/manual.ston';
addDocument: 'Docs/En/Books/DataActivism/techniques-for-datactivism.ston'. addDocument: 'Docs/En/Books/DataActivism/techniques-for-datactivism.ston'.
^ testRepo ^ testRepo
] ]

View File

@ -1,164 +1,164 @@
" "
I contain simple general functionality used by Grafoscopio, Dataviz I contain simple general functionality used by Grafoscopio, Dataviz
or other related projects. or other related projects.
" "
Class { Class {
#name : #GrafoscopioUtils, #name : #GrafoscopioUtils,
#superclass : #Object, #superclass : #Object,
#category : #'Grafoscopio-Utils' #category : #'Grafoscopio-Utils'
} }
{ #category : #utilities } { #category : #utilities }
GrafoscopioUtils class >> checksumFor: aFileReference [ GrafoscopioUtils class >> checksumFor: aFileReference [
^ (SHA1 new hashMessage: aFileReference binaryReadStream contents) hex. ^ (SHA1 new hashMessage: aFileReference binaryReadStream contents) hex.
] ]
{ #category : #updating } { #category : #updating }
GrafoscopioUtils class >> download: fileNameWithRelativePath from: urlString into: aFolder [ GrafoscopioUtils class >> download: fileNameWithRelativePath from: urlString into: aFolder [
| fileName parentFolder | | fileName parentFolder |
fileName := (fileNameWithRelativePath splitOn: $/) last. fileName := (fileNameWithRelativePath splitOn: $/) last.
parentFolder := self ensureCreateDirectory: fileNameWithRelativePath into: aFolder. parentFolder := self ensureCreateDirectory: fileNameWithRelativePath into: aFolder.
self self
downloadingFrom: urlString, fileNameWithRelativePath downloadingFrom: urlString, fileNameWithRelativePath
withMessage: 'Downloading ', fileName withMessage: 'Downloading ', fileName
into: parentFolder into: parentFolder
] ]
{ #category : #'graphical interface' } { #category : #'graphical interface' }
GrafoscopioUtils class >> downloadingFrom: downloadUrl withMessage: aString into: location [ GrafoscopioUtils class >> downloadingFrom: downloadUrl withMessage: aString into: location [
| fileName | | fileName |
fileName := (self sanitize: downloadUrl) segments last. fileName := (self sanitize: downloadUrl) segments last.
(location / fileName) ensureDelete. (location / fileName) ensureDelete.
[: bar | [: bar |
bar title: aString. bar title: aString.
[ZnClient new [ZnClient new
enforceHttpSuccess: true; enforceHttpSuccess: true;
url: downloadUrl; url: downloadUrl;
downloadTo: location; downloadTo: location;
signalProgress: true signalProgress: true
] ]
on: HTTPProgress on: HTTPProgress
do: [ :progress | do: [ :progress |
progress isEmpty ifFalse: [ bar current: progress percentage ]. progress isEmpty ifFalse: [ bar current: progress percentage ].
progress resume ]. progress resume ].
] asJob run. ] asJob run.
^ (location / fileName) asFileReference ^ (location / fileName) asFileReference
] ]
{ #category : #utilities } { #category : #utilities }
GrafoscopioUtils class >> ensureCreateDirectory: fileNameWithRelativePath into: aFolder [ GrafoscopioUtils class >> ensureCreateDirectory: fileNameWithRelativePath into: aFolder [
| relativePathFolders parentFolder newPath | | relativePathFolders parentFolder newPath |
relativePathFolders := (fileNameWithRelativePath splitOn: $/) allButLast. relativePathFolders := (fileNameWithRelativePath splitOn: $/) allButLast.
newPath := aFolder path. newPath := aFolder path.
relativePathFolders do: [ :folder | newPath := newPath / folder ]. relativePathFolders do: [ :folder | newPath := newPath / folder ].
parentFolder := newPath asFileReference. parentFolder := newPath asFileReference.
parentFolder ensureCreateDirectory. parentFolder ensureCreateDirectory.
^ parentFolder ^ parentFolder
] ]
{ #category : #persistence } { #category : #persistence }
GrafoscopioUtils class >> exportAsSton: anObject on: aFileReference [ GrafoscopioUtils class >> exportAsSton: anObject on: aFileReference [
aFileReference exists ifTrue: [ aFileReference ensureDelete ]. aFileReference exists ifTrue: [ aFileReference ensureDelete ].
aFileReference ensureCreateFile. aFileReference ensureCreateFile.
aFileReference writeStreamDo: [ :stream | aFileReference writeStreamDo: [ :stream |
(STON writer on: stream) (STON writer on: stream)
newLine: String crlf; newLine: String crlf;
prettyPrint: true; prettyPrint: true;
keepNewLines: true; keepNewLines: true;
nextPut: anObject ]. nextPut: anObject ].
] ]
{ #category : #'graphical interface' } { #category : #'graphical interface' }
GrafoscopioUtils class >> getContentsFrom: url withMessage: aString [ GrafoscopioUtils class >> getContentsFrom: url withMessage: aString [
| client | | client |
[: bar | [: bar |
bar title: aString. bar title: aString.
[client := ZnClient new [client := ZnClient new
enforceHttpSuccess: true; enforceHttpSuccess: true;
get: (url); get: (url);
signalProgress: true signalProgress: true
] ]
on: HTTPProgress on: HTTPProgress
do: [ :progress | do: [ :progress |
progress isEmpty ifFalse: [ bar current: progress percentage ]. progress isEmpty ifFalse: [ bar current: progress percentage ].
progress resume ]. progress resume ].
] asJob run. ] asJob run.
^ client contents. ^ client contents.
] ]
{ #category : #persistence } { #category : #persistence }
GrafoscopioUtils class >> joinLinesFor: aCollection [ GrafoscopioUtils class >> joinLinesFor: aCollection [
| joinedLines | | joinedLines |
joinedLines := WriteStream on: ''. joinedLines := WriteStream on: ''.
aCollection do: [ :line | joinedLines nextPutAll: line; crlf ]. aCollection do: [ :line | joinedLines nextPutAll: line; crlf ].
^ joinedLines contents ^ joinedLines contents
] ]
{ #category : #utilities } { #category : #utilities }
GrafoscopioUtils class >> perform: aString on: anObject [ GrafoscopioUtils class >> perform: aString on: anObject [
| msg | | msg |
msg := self selectorAndArgumentsFrom: aString. msg := self selectorAndArgumentsFrom: aString.
msg msg
at: 'args' at: 'args'
ifPresent: [ ^ anObject perform: (msg at: 'selector') withArguments: (msg at: 'args') ] ifPresent: [ ^ anObject perform: (msg at: 'selector') withArguments: (msg at: 'args') ]
ifAbsent: [ ^ anObject perform: (msg at: 'selector') ] ifAbsent: [ ^ anObject perform: (msg at: 'selector') ]
] ]
{ #category : #private } { #category : #private }
GrafoscopioUtils class >> sanitize: url [ GrafoscopioUtils class >> sanitize: url [
"I remove white spaces in url's and prepend 'http://' to urls when it is ommited, so "I remove white spaces in url's and prepend 'http://' to urls when it is ommited, so
operations that rely on sane and well formed urls don't throw error messages." operations that rely on sane and well formed urls don't throw error messages."
| sanitized modUrl | | sanitized modUrl |
modUrl := url. modUrl := url.
[modUrl asString endsWith: ' '] [modUrl asString endsWith: ' ']
whileTrue: [ modUrl := modUrl copyFrom: 1 to: (modUrl size - 1) ]. whileTrue: [ modUrl := modUrl copyFrom: 1 to: (modUrl size - 1) ].
(url asString beginsWith: 'http') "http or https" (url asString beginsWith: 'http') "http or https"
ifFalse: [ sanitized := ('http://', modUrl) asUrl ] ifFalse: [ sanitized := ('http://', modUrl) asUrl ]
ifTrue: [ sanitized := modUrl asUrl ]. ifTrue: [ sanitized := modUrl asUrl ].
^ sanitized ^ sanitized
] ]
{ #category : #utilities } { #category : #utilities }
GrafoscopioUtils class >> selectorAndArgumentsFrom: aString [ GrafoscopioUtils class >> selectorAndArgumentsFrom: aString [
"I return from aString a dictionary that contains a message and an array of arguments used "I return from aString a dictionary that contains a message and an array of arguments used
in such string. Notice that the keyword message must contain spaces between the ':' and its in such string. Notice that the keyword message must contain spaces between the ':' and its
respective argument. respective argument.
See GrafoscopioUtilsTest for examples" See GrafoscopioUtilsTest for examples"
| msgArray answer keywords selector args | | msgArray answer keywords selector args |
answer := OrderedDictionary new. answer := OrderedDictionary new.
msgArray := aString splitOn: ':'. msgArray := aString splitOn: ':'.
msgArray size = 1 msgArray size = 1
ifTrue: [ ifTrue: [
^ answer ^ answer
at: 'selector' put: (msgArray at: 1) asSymbol; at: 'selector' put: (msgArray at: 1) asSymbol;
yourself ]. yourself ].
selector := ''. selector := ''.
args := OrderedCollection new. args := OrderedCollection new.
aString aString
splitOn: Character space splitOn: Character space
do: [ :part | do: [ :part |
part endsWithAColon part endsWithAColon
ifTrue: [ selector := selector, part ] ifTrue: [ selector := selector, part ]
ifFalse: [ args add: part ] ]. ifFalse: [ args add: part ] ].
answer answer
at: 'selector' put: selector asSymbol; at: 'selector' put: selector asSymbol;
at: 'args' put: args asArray. at: 'args' put: args asArray.
^ answer ^ answer
] ]
{ #category : #updating } { #category : #updating }
GrafoscopioUtils class >> update [ GrafoscopioUtils class >> update [
"Updates GrafoscopioUtils with new versions of itself take from the source code repository." "Updates GrafoscopioUtils with new versions of itself take from the source code repository."
Gofer new Gofer new
smalltalkhubUser: 'Offray' project: 'Grafoscopio'; smalltalkhubUser: 'Offray' project: 'Grafoscopio';
package: 'Grafoscopio-Utils'; package: 'Grafoscopio-Utils';
load. load.
] ]

View File

@ -1,8 +1,8 @@
" "
A GrafoscopioUtilsTest is a test class for testing the behavior of GrafoscopioUtils A GrafoscopioUtilsTest is a test class for testing the behavior of GrafoscopioUtils
" "
Class { Class {
#name : #GrafoscopioUtilsTest, #name : #GrafoscopioUtilsTest,
#superclass : #TestCase, #superclass : #TestCase,
#category : #'Grafoscopio-Utils-Tests' #category : #'Grafoscopio-Utils-Tests'
} }

View File

@ -1,113 +1,113 @@
" "
I model the interface between a CodiMD (https://demo.codimd.org) documentation I model the interface between a CodiMD (https://demo.codimd.org) documentation
server and Grafoscopio. server and Grafoscopio.
I enable the interaction between Grafoscopio notebooks and CodiMD documents, I enable the interaction between Grafoscopio notebooks and CodiMD documents,
so one document can start online (as a CodiMD pad) and continue as a Grafoscopio so one document can start online (as a CodiMD pad) and continue as a Grafoscopio
notebook or viceversa. notebook or viceversa.
" "
Class { Class {
#name : #HedgeDoc, #name : #HedgeDoc,
#superclass : #Object, #superclass : #Object,
#instVars : [ #instVars : [
'server', 'server',
'pad', 'pad',
'contents', 'contents',
'url' 'url'
], ],
#category : #'Grafoscopio-Utils' #category : #'Grafoscopio-Utils'
} }
{ #category : #'as yet unclassified' } { #category : #'as yet unclassified' }
HedgeDoc class >> newDefault [ HedgeDoc class >> newDefault [
^ self new ^ self new
defaultServer. defaultServer.
] ]
{ #category : #accessing } { #category : #accessing }
HedgeDoc >> contents [ HedgeDoc >> contents [
^ contents ^ contents
] ]
{ #category : #accessing } { #category : #accessing }
HedgeDoc >> contents: anObject [ HedgeDoc >> contents: anObject [
contents := anObject contents := anObject
] ]
{ #category : #'as yet unclassified' } { #category : #'as yet unclassified' }
HedgeDoc >> defaultServer [ HedgeDoc >> defaultServer [
self server: 'https://docutopia.tupale.co'. self server: 'https://docutopia.tupale.co'.
] ]
{ #category : #'as yet unclassified' } { #category : #'as yet unclassified' }
HedgeDoc >> htmlUrl [ HedgeDoc >> htmlUrl [
| link | | link |
link := self url copy. link := self url copy.
link segments insert: 's' before: 1. link segments insert: 's' before: 1.
^ link ^ link
] ]
{ #category : #'as yet unclassified' } { #category : #'as yet unclassified' }
HedgeDoc >> importContents [ HedgeDoc >> importContents [
self contents: self retrieveContents self contents: self retrieveContents
] ]
{ #category : #accessing } { #category : #accessing }
HedgeDoc >> pad [ HedgeDoc >> pad [
^ pad ^ pad
] ]
{ #category : #accessing } { #category : #accessing }
HedgeDoc >> pad: anObject [ HedgeDoc >> pad: anObject [
pad := anObject pad := anObject
] ]
{ #category : #'as yet unclassified' } { #category : #'as yet unclassified' }
HedgeDoc >> retrieveContents [ HedgeDoc >> retrieveContents [
self url ifNil: [ ^ self ]. self url ifNil: [ ^ self ].
^ (self url addPathSegment: 'download') retrieveContents ^ (self url addPathSegment: 'download') retrieveContents
] ]
{ #category : #'as yet unclassified' } { #category : #'as yet unclassified' }
HedgeDoc >> retrieveHtmlContents [ HedgeDoc >> retrieveHtmlContents [
| htmlContents | | htmlContents |
self url ifNil: [ ^ self ]. self url ifNil: [ ^ self ].
htmlContents := self htmlUrl. htmlContents := self htmlUrl.
^ htmlContents retrieveContents ^ htmlContents retrieveContents
] ]
{ #category : #'as yet unclassified' } { #category : #'as yet unclassified' }
HedgeDoc >> saveContentsToFile: aFileLocator [ HedgeDoc >> saveContentsToFile: aFileLocator [
self url ifNil: [ ^ self ]. self url ifNil: [ ^ self ].
^ (self url addPathSegment: 'download') saveContentsToFile: aFileLocator ^ (self url addPathSegment: 'download') saveContentsToFile: aFileLocator
] ]
{ #category : #'as yet unclassified' } { #category : #'as yet unclassified' }
HedgeDoc >> saveHtmlContentsToFile: aFileLocator [ HedgeDoc >> saveHtmlContentsToFile: aFileLocator [
self url ifNil: [ ^ self ]. self url ifNil: [ ^ self ].
^ self htmlUrl saveContentsToFile: aFileLocator ^ self htmlUrl saveContentsToFile: aFileLocator
] ]
{ #category : #accessing } { #category : #accessing }
HedgeDoc >> server [ HedgeDoc >> server [
^ server ^ server
] ]
{ #category : #accessing } { #category : #accessing }
HedgeDoc >> server: aUrlString [ HedgeDoc >> server: aUrlString [
server := aUrlString server := aUrlString
] ]
{ #category : #accessing } { #category : #accessing }
HedgeDoc >> url [ HedgeDoc >> url [
^ url asUrl ^ url asUrl
] ]
{ #category : #accessing } { #category : #accessing }
HedgeDoc >> url: anObject [ HedgeDoc >> url: anObject [
url := anObject url := anObject
] ]
{ #category : #visiting } { #category : #visiting }
HedgeDoc >> visit [ HedgeDoc >> visit [
WebBrowser openOn: self server, '/', self pad. WebBrowser openOn: self server, '/', self pad.
] ]

View File

@ -1,185 +1,185 @@
" "
I model a Mardeep file as described in https://casual-effects.com/markdeep/ I model a Mardeep file as described in https://casual-effects.com/markdeep/
" "
Class { Class {
#name : #Markdeep, #name : #Markdeep,
#superclass : #Object, #superclass : #Object,
#instVars : [ #instVars : [
'tocStyle', 'tocStyle',
'comments', 'comments',
'header', 'header',
'tail', 'tail',
'body', 'body',
'language', 'language',
'markdownFile' 'markdownFile'
], ],
#category : #'Grafoscopio-Utils' #category : #'Grafoscopio-Utils'
} }
{ #category : #'as yet unclassified' } { #category : #'as yet unclassified' }
Markdeep class >> fromMarkdownFile: aFileReference [ Markdeep class >> fromMarkdownFile: aFileReference [
^ self new fromMarkdownFile: aFileReference. ^ self new fromMarkdownFile: aFileReference.
] ]
{ #category : #accessing } { #category : #accessing }
Markdeep >> body [ Markdeep >> body [
^ body ^ body
] ]
{ #category : #accessing } { #category : #accessing }
Markdeep >> body: anObject [ Markdeep >> body: anObject [
body := anObject body := anObject
] ]
{ #category : #accessing } { #category : #accessing }
Markdeep >> comments [ Markdeep >> comments [
^ comments ifNil: [ ^ comments := true ] ^ comments ifNil: [ ^ comments := true ]
] ]
{ #category : #accessing } { #category : #accessing }
Markdeep >> comments: aBoolean [ Markdeep >> comments: aBoolean [
"I tell if comments are enabled by default or not." "I tell if comments are enabled by default or not."
comments := aBoolean comments := aBoolean
] ]
{ #category : #utilities } { #category : #utilities }
Markdeep >> commentsProvider [ Markdeep >> commentsProvider [
"I return the url of the default service that provides annotation support. "I return the url of the default service that provides annotation support.
I am used to add such support in the contents of the Markdeep page." I am used to add such support in the contents of the Markdeep page."
^ 'https://hypothes.is' ^ 'https://hypothes.is'
] ]
{ #category : #utilities } { #category : #utilities }
Markdeep >> commentsProviderStrings [ Markdeep >> commentsProviderStrings [
"I associate a comments service provider with the string that is required to be added "I associate a comments service provider with the string that is required to be added
to the document to enable such provider." to the document to enable such provider."
| providers | | providers |
providers := Dictionary new. providers := Dictionary new.
providers at: 'https://hypothes.is' put: '<!-- Hypothesis --> providers at: 'https://hypothes.is' put: '<!-- Hypothesis -->
<script src="https://hypothes.is/embed.js" async></script>'. <script src="https://hypothes.is/embed.js" async></script>'.
^ providers ^ providers
] ]
{ #category : #utilities } { #category : #utilities }
Markdeep >> commentsSupport [ Markdeep >> commentsSupport [
"I enable comments of the page." "I enable comments of the page."
self comments ifFalse: [ ^ self ]. self comments ifFalse: [ ^ self ].
^ self commentsProviderStrings at: self commentsProvider ^ self commentsProviderStrings at: self commentsProvider
] ]
{ #category : #'instance creation' } { #category : #'instance creation' }
Markdeep >> contents [ Markdeep >> contents [
| output | | output |
output := '' writeStream. output := '' writeStream.
output output
nextPutAll: self header; crlf; nextPutAll: self header; crlf;
nextPutAll: self body; crlf; nextPutAll: self body; crlf;
nextPutAll: self tail; crlf; crlf; nextPutAll: self tail; crlf; crlf;
nextPutAll: self commentsSupport. nextPutAll: self commentsSupport.
^ output contents. ^ output contents.
] ]
{ #category : #persistence } { #category : #persistence }
Markdeep >> exportAsFile [ Markdeep >> exportAsFile [
| newFile | | newFile |
self markdownFile ifNil: [ self inform: 'Define an input Markdown file or use #exportAsFileOn: instead.' ]. self markdownFile ifNil: [ self inform: 'Define an input Markdown file or use #exportAsFileOn: instead.' ].
newFile := (self markdownFile fullName, '.html') asFileReference. newFile := (self markdownFile fullName, '.html') asFileReference.
self exportAsFileOn: newFile. self exportAsFileOn: newFile.
] ]
{ #category : #persistence } { #category : #persistence }
Markdeep >> exportAsFileOn: aFileReference [ Markdeep >> exportAsFileOn: aFileReference [
aFileReference exists ifFalse: [ aFileReference ensureCreateFile ]. aFileReference exists ifFalse: [ aFileReference ensureCreateFile ].
aFileReference writeStreamDo: [ :stream | aFileReference writeStreamDo: [ :stream |
stream nextPutAll: self contents ]. stream nextPutAll: self contents ].
self inform: 'Exported as: ', String cr, aFileReference fullName self inform: 'Exported as: ', String cr, aFileReference fullName
] ]
{ #category : #utilities } { #category : #utilities }
Markdeep >> fontAwesomeHeader [ Markdeep >> fontAwesomeHeader [
"I enable the font awesome support in the document header" "I enable the font awesome support in the document header"
^ ' <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css"> ^ ' <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
' '
] ]
{ #category : #'instance creation' } { #category : #'instance creation' }
Markdeep >> fromMarkdownFile: aFileReference [ Markdeep >> fromMarkdownFile: aFileReference [
"I create a Markdeep document from a given Markdown file." "I create a Markdeep document from a given Markdown file."
self processMarkdownFor: aFileReference. self processMarkdownFor: aFileReference.
^ self. ^ self.
] ]
{ #category : #accessing } { #category : #accessing }
Markdeep >> header [ Markdeep >> header [
^ self fontAwesomeHeader ^ self fontAwesomeHeader
] ]
{ #category : #accessing } { #category : #accessing }
Markdeep >> header: anObject [ Markdeep >> header: anObject [
header := anObject header := anObject
] ]
{ #category : #accessing } { #category : #accessing }
Markdeep >> language [ Markdeep >> language [
^ language ^ language
] ]
{ #category : #accessing } { #category : #accessing }
Markdeep >> language: anObject [ Markdeep >> language: anObject [
language := anObject language := anObject
] ]
{ #category : #accessing } { #category : #accessing }
Markdeep >> markdownFile [ Markdeep >> markdownFile [
^ markdownFile ^ markdownFile
] ]
{ #category : #accessing } { #category : #accessing }
Markdeep >> markdownFile: aFileReference [ Markdeep >> markdownFile: aFileReference [
"I provide information about which Markdown file was used to generate the Markdeep body" "I provide information about which Markdown file was used to generate the Markdeep body"
markdownFile := aFileReference markdownFile := aFileReference
] ]
{ #category : #'instance creation' } { #category : #'instance creation' }
Markdeep >> processMarkdownFor: aFileReference [ Markdeep >> processMarkdownFor: aFileReference [
"comment stating purpose of message" "comment stating purpose of message"
| markdownContent | | markdownContent |
self markdownFile: aFileReference. self markdownFile: aFileReference.
markdownContent := Markdown fromFile: aFileReference. markdownContent := Markdown fromFile: aFileReference.
self body: (markdownContent commentYAMLMetadata contents). self body: (markdownContent commentYAMLMetadata contents).
] ]
{ #category : #accessing } { #category : #accessing }
Markdeep >> tail [ Markdeep >> tail [
"I enable the document tail, which, in turn, enables a Markdeep document" "I enable the document tail, which, in turn, enables a Markdeep document"
^ ' ^ '
<!-- Markdeep: --> <!-- Markdeep: -->
<style class="fallback">body{visibility:hidden;white-space:pre;font-family:monospace}</style> <style class="fallback">body{visibility:hidden;white-space:pre;font-family:monospace}</style>
<script>window.markdeepOptions = {tocStyle: "medium"}</script> <script>window.markdeepOptions = {tocStyle: "medium"}</script>
<script src="markdeep.min.js" charset="utf-8"></script> <script src="markdeep.min.js" charset="utf-8"></script>
<script <script
src="https://casual-effects.com/markdeep/latest/markdeep.min.js?" src="https://casual-effects.com/markdeep/latest/markdeep.min.js?"
charset="utf-8"> charset="utf-8">
</script> </script>
<!--<script>window.alreadyProcessedMarkdeep||(document.body.style.visibility="visible")</script>--> ' <!--<script>window.alreadyProcessedMarkdeep||(document.body.style.visibility="visible")</script>--> '
] ]
{ #category : #accessing } { #category : #accessing }
Markdeep >> tail: anObject [ Markdeep >> tail: anObject [
tail := anObject tail := anObject
] ]
{ #category : #accessing } { #category : #accessing }
Markdeep >> tocStyle [ Markdeep >> tocStyle [
^ tocStyle ^ tocStyle
] ]
{ #category : #accessing } { #category : #accessing }
Markdeep >> tocStyle: anObject [ Markdeep >> tocStyle: anObject [
tocStyle := anObject tocStyle := anObject
] ]

View File

@ -1,169 +1,169 @@
" "
I model a Markdown document. I model a Markdown document.
At some point the idea is to have a full native parser implemented to deal At some point the idea is to have a full native parser implemented to deal
with my syntax, but meanwhile I will be collaborating with external parsers, with my syntax, but meanwhile I will be collaborating with external parsers,
particularly the ones provided by Pandoc and/or Lunamark. particularly the ones provided by Pandoc and/or Lunamark.
" "
Class { Class {
#name : #Markdown, #name : #Markdown,
#superclass : #Object, #superclass : #Object,
#instVars : [ #instVars : [
'contents', 'contents',
'file' 'file'
], ],
#category : #'Grafoscopio-Utils' #category : #'Grafoscopio-Utils'
} }
{ #category : #'instance creation' } { #category : #'instance creation' }
Markdown class >> fromFile: aFileReference [ Markdown class >> fromFile: aFileReference [
^ self new fromFile: aFileReference ^ self new fromFile: aFileReference
] ]
{ #category : #utilities } { #category : #utilities }
Markdown class >> yamlMetadataDelimiter [ Markdown class >> yamlMetadataDelimiter [
^ '---' ^ '---'
] ]
{ #category : #operation } { #category : #operation }
Markdown >> commentYAMLMetadata [ Markdown >> commentYAMLMetadata [
| newContents | | newContents |
self detectYAMLMetadata ifFalse: [ ^ self ]. self detectYAMLMetadata ifFalse: [ ^ self ].
newContents := '' writeStream. newContents := '' writeStream.
newContents nextPutAll: '<!--@yaml:'; crlf. newContents nextPutAll: '<!--@yaml:'; crlf.
newContents nextPutAll: self extractYAMLMetadata. newContents nextPutAll: self extractYAMLMetadata.
newContents nextPutAll: String cr. newContents nextPutAll: String cr.
newContents nextPutAll: '-->'; crlf. newContents nextPutAll: '-->'; crlf.
(self lines copyFrom: self locateYAMLMetadataClosing + 2 to: self lines size) do: [ :line | (self lines copyFrom: self locateYAMLMetadataClosing + 2 to: self lines size) do: [ :line |
newContents nextPutAll: line; crlf ]. newContents nextPutAll: line; crlf ].
self contents: newContents contents. self contents: newContents contents.
^ self contents ^ self contents
] ]
{ #category : #utilities } { #category : #utilities }
Markdown >> containsYAMLMetadataClosing [ Markdown >> containsYAMLMetadataClosing [
^ self locateYAMLMetadataClosing > 0 ^ self locateYAMLMetadataClosing > 0
] ]
{ #category : #accessing } { #category : #accessing }
Markdown >> contents [ Markdown >> contents [
^ contents ^ contents
] ]
{ #category : #accessing } { #category : #accessing }
Markdown >> contents: anObject [ Markdown >> contents: anObject [
contents := anObject contents := anObject
] ]
{ #category : #utilities } { #category : #utilities }
Markdown >> detectYAMLMetadata [ Markdown >> detectYAMLMetadata [
| lines | | lines |
lines := self lines. lines := self lines.
^ self startsWithYAMLMetadataDelimiter ^ self startsWithYAMLMetadataDelimiter
and: [ lines allButFirst and: [ lines allButFirst
detect: [ :currentLine | currentLine beginsWith: self class yamlMetadataDelimiter ] detect: [ :currentLine | currentLine beginsWith: self class yamlMetadataDelimiter ]
ifFound: [ ^ true ] ifNone: [ ^ false ] ] ifFound: [ ^ true ] ifNone: [ ^ false ] ]
] ]
{ #category : #operation } { #category : #operation }
Markdown >> exportMetadataAsJson [ Markdown >> exportMetadataAsJson [
"TBD: Lua scripts should be checked and installed when missing. Maybe a shared location "TBD: Lua scripts should be checked and installed when missing. Maybe a shared location
in '.local/share/Grafoscopio/Scripts' should be developed in the near future." in '.local/share/Grafoscopio/Scripts' should be developed in the near future."
| output luaScript | | output luaScript |
luaScript := FileLocator home / '.local/share/Brea/scripts/meta-to-json.lua'. luaScript := FileLocator home / '.local/share/Brea/scripts/meta-to-json.lua'.
Smalltalk platformName = 'unix' ifTrue: [ Smalltalk platformName = 'unix' ifTrue: [
OSSUnixSubprocess new OSSUnixSubprocess new
workingDirectory: self file parent fullName; workingDirectory: self file parent fullName;
command: 'pandoc'; command: 'pandoc';
arguments: { '--lua-filter=', luaScript fullName . self file basename }; arguments: { '--lua-filter=', luaScript fullName . self file basename };
redirectStdout; redirectStdout;
redirectStdin; redirectStdin;
runAndWaitOnExitDo: [ :process :outString :errString | runAndWaitOnExitDo: [ :process :outString :errString |
output := process isSuccess output := process isSuccess
ifTrue: [ outString ] ifTrue: [ outString ]
ifFalse: [ errString ] ifFalse: [ errString ]
]]. ]].
^ output correctAccentedCharacters ^ output correctAccentedCharacters
] ]
{ #category : #operation } { #category : #operation }
Markdown >> exportMetadataAsYaml [ Markdown >> exportMetadataAsYaml [
| exportedFile | | exportedFile |
exportedFile := FileLocator temp / 'metadata.yaml'. exportedFile := FileLocator temp / 'metadata.yaml'.
MarkupFile exportAsFileOn: exportedFile containing: self yamlMetadataAsString. MarkupFile exportAsFileOn: exportedFile containing: self yamlMetadataAsString.
^ exportedFile ^ exportedFile
] ]
{ #category : #operation } { #category : #operation }
Markdown >> extractYAMLMetadata [ Markdown >> extractYAMLMetadata [
| output yamlLines | | output yamlLines |
self detectYAMLMetadata ifFalse: [ ^ nil ]. self detectYAMLMetadata ifFalse: [ ^ nil ].
yamlLines := self lines copyFrom: 2 to: (self locateYAMLMetadataClosing). yamlLines := self lines copyFrom: 2 to: (self locateYAMLMetadataClosing).
output := '' writeStream. output := '' writeStream.
yamlLines do: [ :line | yamlLines do: [ :line |
output output
nextPutAll: line; nextPutAll: line;
nextPut: Character cr. ]. nextPut: Character cr. ].
^ output contents ^ output contents
] ]
{ #category : #accessing } { #category : #accessing }
Markdown >> file [ Markdown >> file [
^ file ^ file
] ]
{ #category : #accessing } { #category : #accessing }
Markdown >> file: aFileReference [ Markdown >> file: aFileReference [
"I store the origen/destination of the Markdown contents." "I store the origen/destination of the Markdown contents."
file := aFileReference file := aFileReference
] ]
{ #category : #'instance creation' } { #category : #'instance creation' }
Markdown >> fromFile: aFileReference [ Markdown >> fromFile: aFileReference [
self contents: aFileReference contents. self contents: aFileReference contents.
self file: aFileReference self file: aFileReference
] ]
{ #category : #utilities } { #category : #utilities }
Markdown >> lines [ Markdown >> lines [
^ self contents lines. ^ self contents lines.
] ]
{ #category : #utilities } { #category : #utilities }
Markdown >> locateYAMLMetadataClosing [ Markdown >> locateYAMLMetadataClosing [
"I return the line where the closing of the YAML metadata occurs or 0 if no closing is found." "I return the line where the closing of the YAML metadata occurs or 0 if no closing is found."
| result | | result |
self startsWithYAMLMetadataDelimiter ifFalse: [ ^ self ]. self startsWithYAMLMetadataDelimiter ifFalse: [ ^ self ].
result := 0. result := 0.
self lines allButFirst doWithIndex: [ :currentLine :i | self lines allButFirst doWithIndex: [ :currentLine :i |
(currentLine beginsWith: self class yamlMetadataDelimiter) ifTrue: [ result := i ]]. (currentLine beginsWith: self class yamlMetadataDelimiter) ifTrue: [ result := i ]].
^ result ^ result
] ]
{ #category : #accessing } { #category : #accessing }
Markdown >> metadata [ Markdown >> metadata [
| rawMeta | | rawMeta |
rawMeta := PPYAMLGrammar new parse: self extractYAMLMetadata. rawMeta := PPYAMLGrammar new parse: self extractYAMLMetadata.
rawMeta associationsDo: [ :assoc | rawMeta associationsDo: [ :assoc |
assoc value = 'false' ifTrue: [ assoc value: false ]. assoc value = 'false' ifTrue: [ assoc value: false ].
assoc value = 'true' ifTrue: [ assoc value: true ] ]. assoc value = 'true' ifTrue: [ assoc value: true ] ].
^ rawMeta ^ rawMeta
] ]
{ #category : #utilities } { #category : #utilities }
Markdown >> startsWithYAMLMetadataDelimiter [ Markdown >> startsWithYAMLMetadataDelimiter [
^ self lines first beginsWith: self class yamlMetadataDelimiter ^ self lines first beginsWith: self class yamlMetadataDelimiter
] ]
{ #category : #utilities } { #category : #utilities }
Markdown >> yamlMetadataAsString [ Markdown >> yamlMetadataAsString [
| output | | output |
self extractYAMLMetadata ifNil: [ ^ nil ]. self extractYAMLMetadata ifNil: [ ^ nil ].
output := String new writeStream. output := String new writeStream.
output nextPutAll: self class yamlMetadataDelimiter; cr. output nextPutAll: self class yamlMetadataDelimiter; cr.
output nextPutAll: self extractYAMLMetadata. output nextPutAll: self extractYAMLMetadata.
output nextPutAll: self class yamlMetadataDelimiter; cr. output nextPutAll: self class yamlMetadataDelimiter; cr.
^ output contents. ^ output contents.
] ]

View File

@ -1,23 +1,23 @@
" "
I model common operations made with several markup files. I model common operations made with several markup files.
" "
Class { Class {
#name : #MarkupFile, #name : #MarkupFile,
#superclass : #Object, #superclass : #Object,
#instVars : [ #instVars : [
'file' 'file'
], ],
#category : #'Grafoscopio-Utils' #category : #'Grafoscopio-Utils'
} }
{ #category : #persistence } { #category : #persistence }
MarkupFile class >> exportAsFileOn: aFileReferenceOrFileName containing: text [ MarkupFile class >> exportAsFileOn: aFileReferenceOrFileName containing: text [
| file | | file |
file := aFileReferenceOrFileName asFileReference. file := aFileReferenceOrFileName asFileReference.
file ensureDelete. file ensureDelete.
file exists ifFalse: [ file ensureCreateFile ]. file exists ifFalse: [ file ensureCreateFile ].
file writeStreamDo: [ :stream | file writeStreamDo: [ :stream |
stream nextPutAll: text withInternetLineEndings]. stream nextPutAll: text withInternetLineEndings].
self inform: 'Exported as: ', String cr, file fullName. self inform: 'Exported as: ', String cr, file fullName.
^ file ^ file
] ]

View File

@ -1,46 +1,46 @@
" "
I provide some utilites to work with OrgMode files. I provide some utilites to work with OrgMode files.
https://orgmode.org/ https://orgmode.org/
" "
Class { Class {
#name : #OrgMode, #name : #OrgMode,
#superclass : #Object, #superclass : #Object,
#instVars : [ #instVars : [
'contents', 'contents',
'file' 'file'
], ],
#category : #'Grafoscopio-Utils' #category : #'Grafoscopio-Utils'
} }
{ #category : #'instance creation' } { #category : #'instance creation' }
OrgMode class >> fromFile: aFileReference [ OrgMode class >> fromFile: aFileReference [
^ self new contents: aFileReference contents. ^ self new contents: aFileReference contents.
] ]
{ #category : #accessing } { #category : #accessing }
OrgMode >> contents [ OrgMode >> contents [
^ contents ^ contents
] ]
{ #category : #accessing } { #category : #accessing }
OrgMode >> contents: anObject [ OrgMode >> contents: anObject [
contents := anObject contents := anObject
] ]
{ #category : #accessing } { #category : #accessing }
OrgMode >> file [ OrgMode >> file [
^ file ^ file
] ]
{ #category : #accessing } { #category : #accessing }
OrgMode >> file: anObject [ OrgMode >> file: anObject [
file := anObject file := anObject
] ]
{ #category : #utilities } { #category : #utilities }
OrgMode >> selectHeadlines [ OrgMode >> selectHeadlines [
^ self contents lines select: [ :line | ^ self contents lines select: [ :line |
line isOrgModeHeader ] line isOrgModeHeader ]
] ]

View File

@ -1,146 +1,146 @@
" "
I model the interaction between Pandoc and Grafoscopio. I model the interaction between Pandoc and Grafoscopio.
" "
Class { Class {
#name : #Pandoc, #name : #Pandoc,
#superclass : #Object, #superclass : #Object,
#classInstVars : [ #classInstVars : [
'executable' 'executable'
], ],
#category : #'Grafoscopio-Utils' #category : #'Grafoscopio-Utils'
} }
{ #category : #'as yet unclassified' } { #category : #'as yet unclassified' }
Pandoc class >> downloadLuaFilters [ Pandoc class >> downloadLuaFilters [
self luaFilters do: [ :filter | | filterUrl | self luaFilters do: [ :filter | | filterUrl |
filterUrl := filter asUrl. filterUrl := filter asUrl.
(FileLocator temp asFileReference / (filterUrl segments last)) exists (FileLocator temp asFileReference / (filterUrl segments last)) exists
ifFalse: [ ifFalse: [
ZnClient new ZnClient new
url: filterUrl; url: filterUrl;
downloadTo: FileLocator temp ] ] downloadTo: FileLocator temp ] ]
] ]
{ #category : #accessing } { #category : #accessing }
Pandoc class >> executable [ Pandoc class >> executable [
^ executable ifNil: [ self executableLocation ] ^ executable ifNil: [ self executableLocation ]
] ]
{ #category : #accessing } { #category : #accessing }
Pandoc class >> executable: aFileReference [ Pandoc class >> executable: aFileReference [
executable := aFileReference executable := aFileReference
] ]
{ #category : #accessing } { #category : #accessing }
Pandoc class >> executableLocation [ Pandoc class >> executableLocation [
| location | | location |
location := '/usr/bin/pandoc'. location := '/usr/bin/pandoc'.
location asFileReference exists location asFileReference exists
ifTrue: [ ^ location ] ifTrue: [ ^ location ]
ifFalse: [ self definePandocExecutable ] ifFalse: [ self definePandocExecutable ]
] ]
{ #category : #utility } { #category : #utility }
Pandoc class >> extractImagesInUnixFor: aFileReference withFilter: aLuaFilter [ Pandoc class >> extractImagesInUnixFor: aFileReference withFilter: aLuaFilter [
"I use Pandoc Lua scripting capabilities to extract al images links in aFileReference" "I use Pandoc Lua scripting capabilities to extract al images links in aFileReference"
OSSUnixSubprocess new OSSUnixSubprocess new
command: 'pandoc'; command: 'pandoc';
arguments: {aFileReference fullName . '--lua-filter=',aLuaFilter fullName }; arguments: {aFileReference fullName . '--lua-filter=',aLuaFilter fullName };
redirectStdout; redirectStdout;
redirectStderr; redirectStderr;
runAndWaitOnExitDo: [ :process :outString :errString | runAndWaitOnExitDo: [ :process :outString :errString |
process isSuccess process isSuccess
ifTrue: [ ifTrue: [
^ ((Soup fromString: outString) findAllTags: 'td') collect: [ :each | each next ] ] ^ ((Soup fromString: outString) findAllTags: 'td') collect: [ :each | each next ] ]
ifFalse: [ ifFalse: [
"OSSUnixProcessExitStatus has a nice #printOn: " "OSSUnixProcessExitStatus has a nice #printOn: "
Transcript show: 'Command exit with error status: ', process exitStatusInterpreter printString; cr. Transcript show: 'Command exit with error status: ', process exitStatusInterpreter printString; cr.
Transcript show: 'Stderr contents: ', errString. Transcript show: 'Stderr contents: ', errString.
] ]
] ]
] ]
{ #category : #converters } { #category : #converters }
Pandoc class >> htmlToMarkdown: inputFile [ Pandoc class >> htmlToMarkdown: inputFile [
| outputFile | | outputFile |
outputFile := FileLocator temp / 'body.md'. outputFile := FileLocator temp / 'body.md'.
outputFile ensureDelete. outputFile ensureDelete.
outputFile ensureCreateFile. outputFile ensureCreateFile.
OSSUnixSubprocess new OSSUnixSubprocess new
command: 'pandoc'; command: 'pandoc';
arguments: {'-f'. 'html'. '-t'. 'markdown'. '--atx-headers'. inputFile fullName. arguments: {'-f'. 'html'. '-t'. 'markdown'. '--atx-headers'. inputFile fullName.
'--output'. outputFile fullName }; '--output'. outputFile fullName };
redirectStdout; redirectStdout;
redirectStderr; redirectStderr;
runAndWaitOnExitDo: [ :process :outString :errString | runAndWaitOnExitDo: [ :process :outString :errString |
process isSuccess process isSuccess
ifTrue: [ ^ outputFile contents ] ifTrue: [ ^ outputFile contents ]
ifFalse: [ ^inputFile contents ] ifFalse: [ ^inputFile contents ]
] ]
] ]
{ #category : #'as yet unclassified' } { #category : #'as yet unclassified' }
Pandoc class >> listImagesFrom: aFileReference [ Pandoc class >> listImagesFrom: aFileReference [
"I provide a list of all images contained in aFile." "I provide a list of all images contained in aFile."
| filter commandString outputString | | filter commandString outputString |
filter := FileLocator temp asFileReference / 'image-links.lua'. filter := FileLocator temp asFileReference / 'image-links.lua'.
filter exists filter exists
ifFalse: [ self downloadLuaFilters ]. ifFalse: [ self downloadLuaFilters ].
commandString := 'pandoc ' , aFileReference fullName commandString := 'pandoc ' , aFileReference fullName
, ' --lua-filter=' , filter fullName. , ' --lua-filter=' , filter fullName.
^ self extractImagesInUnixFor: aFileReference withFilter: filter ^ self extractImagesInUnixFor: aFileReference withFilter: filter
] ]
{ #category : #utility } { #category : #utility }
Pandoc class >> luaFilters [ Pandoc class >> luaFilters [
"I define the location of set of scripts, that allows to change the default behaviour of Pandoc "I define the location of set of scripts, that allows to change the default behaviour of Pandoc
and/or the processing of supported markup languages. and/or the processing of supported markup languages.
For more information about Lua filters see: For more information about Lua filters see:
https://pandoc.org/lua-filters.html https://pandoc.org/lua-filters.html
" "
| filters | | filters |
filters := OrderedCollection new. filters := OrderedCollection new.
filters filters
add: 'http://mutabit.com/repos.fossil/dataweek/doc/tip/Artefactos/Scripts/image-links.lua'. add: 'http://mutabit.com/repos.fossil/dataweek/doc/tip/Artefactos/Scripts/image-links.lua'.
^ filters ^ filters
] ]
{ #category : #converters } { #category : #converters }
Pandoc class >> markdownToHtml: inputFile [ Pandoc class >> markdownToHtml: inputFile [
(Smalltalk os isUnix or: [ Smalltalk os isMacOS ]) ifTrue: [ ^ self markdownToHtmlOnUnix: inputFile ]. (Smalltalk os isUnix or: [ Smalltalk os isMacOS ]) ifTrue: [ ^ self markdownToHtmlOnUnix: inputFile ].
Smalltalk os isWindows ifTrue: [ ^ self markdownToHtmlOnWindows: inputFile ]. Smalltalk os isWindows ifTrue: [ ^ self markdownToHtmlOnWindows: inputFile ].
] ]
{ #category : #converters } { #category : #converters }
Pandoc class >> markdownToHtmlOnUnix: inputFile [ Pandoc class >> markdownToHtmlOnUnix: inputFile [
| outputFile | | outputFile |
outputFile := FileLocator temp / (inputFile basenameWithoutExtension , '.html'). outputFile := FileLocator temp / (inputFile basenameWithoutExtension , '.html').
outputFile ensureDelete. outputFile ensureDelete.
outputFile ensureCreateFile. outputFile ensureCreateFile.
OSSUnixSubprocess new OSSUnixSubprocess new
command: 'pandoc'; command: 'pandoc';
arguments: {'-f'. 'markdown+startnum+task_lists'. '-t'. 'html'. inputFile fullName. arguments: {'-f'. 'markdown+startnum+task_lists'. '-t'. 'html'. inputFile fullName.
'--output'. outputFile fullName }; '--output'. outputFile fullName };
redirectStdout; redirectStdout;
redirectStderr; redirectStderr;
runAndWaitOnExitDo: [ :process :outString :errString | runAndWaitOnExitDo: [ :process :outString :errString |
process isSuccess process isSuccess
ifTrue: [ ^ outputFile ] ifTrue: [ ^ outputFile ]
ifFalse: [ ^ inputFile ] ifFalse: [ ^ inputFile ]
] ]
] ]
{ #category : #converters } { #category : #converters }
Pandoc class >> markdownToHtmlOnWindows: inputFile [ Pandoc class >> markdownToHtmlOnWindows: inputFile [
"ToDo: This command still doesn't receive any arguments."
^ LibC resultOfCommand: 'pandoc -f markdown+startnum+task_lists -t html', inputFile fullName. ^ (LibC resultOfCommand: 'pandoc ', inputFile fullName) correctAccentedCharacters.
] ]

View File

@ -1,178 +1,178 @@
" "
I model a work (book, booklet, web page, etc) in Pandoc, its table of contents, its metadata file to I model a work (book, booklet, web page, etc) in Pandoc, its table of contents, its metadata file to
control exportation and other elements. control exportation and other elements.
I can be used to improve reproductibility of published works that use Pandoc. I can be used to improve reproductibility of published works that use Pandoc.
By default it is supposed that a root folder contains the set of folders, organized by By default it is supposed that a root folder contains the set of folders, organized by
language (following the ISO 639-1 two letters convetion) where the contents of the work language (following the ISO 639-1 two letters convetion) where the contents of the work
and their translations are located. and their translations are located.
Chapters, subchapters, sections and subsections are contained there as Markdown files Chapters, subchapters, sections and subsections are contained there as Markdown files
and its order is stated as a ordered dictionary for each language. and its order is stated as a ordered dictionary for each language.
A YAML metadata block is used in each file to map translations between files and languages A YAML metadata block is used in each file to map translations between files and languages
and other sources, synchronizations and meta data. and other sources, synchronizations and meta data.
" "
Class { Class {
#name : #PandocWork, #name : #PandocWork,
#superclass : #Object, #superclass : #Object,
#instVars : [ #instVars : [
'language', 'language',
'contents', 'contents',
'metadataFiles', 'metadataFiles',
'rootFolder', 'rootFolder',
'manifests' 'manifests'
], ],
#category : #'Grafoscopio-Utils' #category : #'Grafoscopio-Utils'
} }
{ #category : #utilities } { #category : #utilities }
PandocWork >> buildManifestFileForLanguage: anISOCode on: aFileName [ PandocWork >> buildManifestFileForLanguage: anISOCode on: aFileName [
"anISOCode is the ISO 639-1 two letters language code" "anISOCode is the ISO 639-1 two letters language code"
| manifestFile | | manifestFile |
manifestFile := (self rootFolder / anISOCode / 'manifests' / aFileName ) asFileReference ensureCreateFile. manifestFile := (self rootFolder / anISOCode / 'manifests' / aFileName ) asFileReference ensureCreateFile.
self buildManifestForLanguage: 'es'. self buildManifestForLanguage: 'es'.
GrafoscopioUtils exportAsSton: (self manifests at: anISOCode) on: manifestFile. GrafoscopioUtils exportAsSton: (self manifests at: anISOCode) on: manifestFile.
^ manifestFile ^ manifestFile
] ]
{ #category : #utlity } { #category : #utlity }
PandocWork >> buildManifestForLanguage: anISOCode [ PandocWork >> buildManifestForLanguage: anISOCode [
self self
metadataManifestForLanguage: anISOCode; metadataManifestForLanguage: anISOCode;
contentsManifestForLanguage: anISOCode. contentsManifestForLanguage: anISOCode.
^ self manifests ^ self manifests
] ]
{ #category : #accessing } { #category : #accessing }
PandocWork >> contents [ PandocWork >> contents [
^ contents ^ contents
] ]
{ #category : #accessing } { #category : #accessing }
PandocWork >> contents: anOrderedDictionary [ PandocWork >> contents: anOrderedDictionary [
"I model the table of contents of the work. "I model the table of contents of the work.
The key of the dictionary is the folder, inside the language folder (see the language variable) The key of the dictionary is the folder, inside the language folder (see the language variable)
where the files are stored, and the value is and ordered collection of the files on such folder where the files are stored, and the value is and ordered collection of the files on such folder
which are part ot the exported result, without the file extension (by default is supposed to be '.md')" which are part ot the exported result, without the file extension (by default is supposed to be '.md')"
contents := anOrderedDictionary contents := anOrderedDictionary
] ]
{ #category : #utilities } { #category : #utilities }
PandocWork >> contentsManifest [ PandocWork >> contentsManifest [
| checksums | | checksums |
checksums := OrderedDictionary new. checksums := OrderedDictionary new.
self contents keysDo: [ :folder | self contents keysDo: [ :folder |
(self contents at: folder) do: [ :fileName | | keyName contentFile | (self contents at: folder) do: [ :fileName | | keyName contentFile |
keyName := fileName, self defaultFileExtension. keyName := fileName, self defaultFileExtension.
contentFile := self rootFolder / self language / folder / keyName. contentFile := self rootFolder / self language / folder / keyName.
checksums at: keyName put: (GrafoscopioUtils checksumFor: contentFile)]. checksums at: keyName put: (GrafoscopioUtils checksumFor: contentFile)].
self manifest at: folder put: checksums ]. self manifest at: folder put: checksums ].
^ self manifest ^ self manifest
] ]
{ #category : #utilities } { #category : #utilities }
PandocWork >> contentsManifestForLanguage: anISOCode [ PandocWork >> contentsManifestForLanguage: anISOCode [
| checksums | | checksums |
checksums := OrderedDictionary new. checksums := OrderedDictionary new.
self contents keysDo: [ :folder | self contents keysDo: [ :folder |
(self contents at: folder) do: [ :fileName | | keyName contentFile | (self contents at: folder) do: [ :fileName | | keyName contentFile |
keyName := fileName, self defaultFileExtension. keyName := fileName, self defaultFileExtension.
contentFile := self rootFolder / anISOCode / folder / keyName. contentFile := self rootFolder / anISOCode / folder / keyName.
checksums at: keyName put: (GrafoscopioUtils checksumFor: contentFile)]. checksums at: keyName put: (GrafoscopioUtils checksumFor: contentFile)].
(self manifestForLanguage: anISOCode) (self manifestForLanguage: anISOCode)
add: {folder -> checksums} asOrderedDictionary ]. add: {folder -> checksums} asOrderedDictionary ].
^ self manifests at: anISOCode ^ self manifests at: anISOCode
] ]
{ #category : #utilities } { #category : #utilities }
PandocWork >> defaultFileExtension [ PandocWork >> defaultFileExtension [
^ '.md' ^ '.md'
] ]
{ #category : #accessing } { #category : #accessing }
PandocWork >> language [ PandocWork >> language [
^ language ^ language
] ]
{ #category : #accessing } { #category : #accessing }
PandocWork >> language: aISOLangString [ PandocWork >> language: aISOLangString [
"I model the lanaguage of a work as a ISO 639-1 two letters string. "I model the lanaguage of a work as a ISO 639-1 two letters string.
I used to stablish the folder where the content is stored, following the convention a folder I used to stablish the folder where the content is stored, following the convention a folder
by language." by language."
language := aISOLangString language := aISOLangString
] ]
{ #category : #utlity } { #category : #utlity }
PandocWork >> manifestForLanguage: anISOCode [ PandocWork >> manifestForLanguage: anISOCode [
self manifests at: anISOCode ifAbsent: [ self manifests at: anISOCode ifAbsent: [
self manifests self manifests
at: anISOCode put: OrderedCollection new; at: anISOCode put: OrderedCollection new;
yourself]. yourself].
^ self manifests at: anISOCode ^ self manifests at: anISOCode
] ]
{ #category : #accessing } { #category : #accessing }
PandocWork >> manifests [ PandocWork >> manifests [
^ manifests ifNil: [ ^ manifests := OrderedDictionary new ] ^ manifests ifNil: [ ^ manifests := OrderedDictionary new ]
] ]
{ #category : #accessing } { #category : #accessing }
PandocWork >> manifests: anOrderedDictionary [ PandocWork >> manifests: anOrderedDictionary [
manifests := anOrderedDictionary manifests := anOrderedDictionary
] ]
{ #category : #accessing } { #category : #accessing }
PandocWork >> metadataFiles [ PandocWork >> metadataFiles [
^ metadataFiles ^ metadataFiles
] ]
{ #category : #accessing } { #category : #accessing }
PandocWork >> metadataFiles: aCollection [ PandocWork >> metadataFiles: aCollection [
"I model the YAML metadata files that are used to control the output of the exportation. "I model the YAML metadata files that are used to control the output of the exportation.
I can have several files, controlling several outputs, one for PDF, one for HTML, one for EPUB I can have several files, controlling several outputs, one for PDF, one for HTML, one for EPUB
and so on. and so on.
This should be stated in the name of the metadatafile and by default will be controlling PDF This should be stated in the name of the metadatafile and by default will be controlling PDF
output." output."
metadataFiles := aCollection metadataFiles := aCollection
] ]
{ #category : #utilities } { #category : #utilities }
PandocWork >> metadataManifest [ PandocWork >> metadataManifest [
| languageFolder | | languageFolder |
languageFolder := self language. languageFolder := self language.
"Could the similar parts of this and contentsManifest be refactored?" "Could the similar parts of this and contentsManifest be refactored?"
self metadataFiles do: [ :fileName | | contentFile | self metadataFiles do: [ :fileName | | contentFile |
contentFile := self rootFolder / languageFolder / fileName. contentFile := self rootFolder / languageFolder / fileName.
self manifest at: languageFolder put: {fileName -> (GrafoscopioUtils checksumFor: contentFile)} asOrderedDictionary ]. self manifest at: languageFolder put: {fileName -> (GrafoscopioUtils checksumFor: contentFile)} asOrderedDictionary ].
^ self manifest ^ self manifest
] ]
{ #category : #utilities } { #category : #utilities }
PandocWork >> metadataManifestForLanguage: anISOCode [ PandocWork >> metadataManifestForLanguage: anISOCode [
"anISOCode is the ISO 639-1 two letters language code" "anISOCode is the ISO 639-1 two letters language code"
"Could the similar parts of this and contentsManifest be refactored?" "Could the similar parts of this and contentsManifest be refactored?"
self metadataFiles do: [ :fileName | | contentFile | self metadataFiles do: [ :fileName | | contentFile |
contentFile := self rootFolder / anISOCode / fileName. contentFile := self rootFolder / anISOCode / fileName.
(self manifestForLanguage: anISOCode) (self manifestForLanguage: anISOCode)
add: {fileName -> (GrafoscopioUtils checksumFor: contentFile)} asOrderedDictionary]. add: {fileName -> (GrafoscopioUtils checksumFor: contentFile)} asOrderedDictionary].
^ self manifests at: anISOCode ^ self manifests at: anISOCode
] ]
{ #category : #accessing } { #category : #accessing }
PandocWork >> rootFolder [ PandocWork >> rootFolder [
^ rootFolder ^ rootFolder
] ]
{ #category : #accessing } { #category : #accessing }
PandocWork >> rootFolder: aFileReference [ PandocWork >> rootFolder: aFileReference [
"I model the folder where the Markdown files are located." "I model the folder where the Markdown files are located."
rootFolder := aFileReference rootFolder := aFileReference
] ]

View File

@ -1,35 +1,38 @@
Extension { #name : #String } Extension { #name : #String }
{ #category : #'*Grafoscopio-Utils' } { #category : #'*Grafoscopio-Utils' }
String >> asCapitalizedPhrase [ String >> asCapitalizedPhrase [
"I convert phrases like 'THIS IS A PHRASE' into 'This is a Phrase'." "I convert phrases like 'THIS IS A PHRASE' into 'This is a Phrase'."
^ Character space join: (self substrings collect: [:each | each asLowercase capitalized ]) ^ Character space join: (self substrings collect: [:each | each asLowercase capitalized ])
] ]
{ #category : #'*Grafoscopio-Utils' } { #category : #'*Grafoscopio-Utils' }
String >> asDashedLowercase [ String >> asDashedLowercase [
"I convert phrases like 'This is a phrase' into 'this-is-a-phrase'." "I convert phrases like 'This is a phrase' into 'this-is-a-phrase'."
^ '-' join: (self substrings collect: [:each | each asLowercase ]) ^ '-' join: (self substrings collect: [:each | each asLowercase ])
] ]
{ #category : #'*Grafoscopio-Utils' } { #category : #'*Grafoscopio-Utils' }
String >> correctAccentedCharacters [ String >> correctAccentedCharacters [
| output | | output |
output := self output := self
copyReplaceAll: 'ó' with: 'ó'. copyReplaceAll: 'ó' with: 'ó'.
output := output copyReplaceAll: 'á' with: 'á'. output := output copyReplaceAll: 'á' with: 'á'.
output := output copyReplaceAll: 'é' with: 'é'. output := output copyReplaceAll: 'é' with: 'é'.
output := output copyReplaceAll: 'í' with: 'í'. output := output copyReplaceAll: 'í' with: 'í'.
output := output copyReplaceAll: 'ú' with: 'ú'. output := output copyReplaceAll: 'ú' with: 'ú'.
^ output output := output copyReplaceAll: 'ñ' with: 'ñ'.
] output := output copyReplaceAll: '“' with: '“'.
output := output copyReplaceAll: '”' with: '”'.
{ #category : #'*Grafoscopio-Utils' } ^ output
String >> isOrgModeHeader [ ]
^ self beginsWithAnyOf: #('* ' '** ' '*** ' '**** ' '***** ' '***** ')
{ #category : #'*Grafoscopio-Utils' }
String >> isOrgModeHeader [
] ^ self beginsWithAnyOf: #('* ' '** ' '*** ' '**** ' '***** ' '***** ')
]

View File

@ -1 +1 @@
Package { #name : #'Grafoscopio-Utils' } Package { #name : #'Grafoscopio-Utils' }