Compare commits
No commits in common. "master" and "gt-crashes/2" have entirely different histories.
master
...
gt-crashes
@ -11,29 +11,20 @@ BaselineOfMiniDocs >> baseline: spec [
|
|||||||
for: #common
|
for: #common
|
||||||
do: [
|
do: [
|
||||||
"Dependencies"
|
"Dependencies"
|
||||||
self setUpTeapot: spec.
|
|
||||||
self setUpPetitParser: spec.
|
|
||||||
self setUpLepiterBuildingBlocs: spec. "working in v1.0.993"
|
|
||||||
spec
|
spec
|
||||||
baseline: 'Mustache' with: [ spec repository: 'github://noha/mustache' ];
|
baseline: 'Mustache' with: [ spec repository: 'github://noha/mustache' ];
|
||||||
baseline: 'Temple' with: [ spec repository: 'github://astares/Pharo-Temple/src' ];
|
|
||||||
baseline: 'Tealight' with: [ spec repository: 'github://astares/Tealight:main/src' ];
|
baseline: 'Tealight' with: [ spec repository: 'github://astares/Tealight:main/src' ];
|
||||||
baseline: 'DataFrame' with: [ spec repository: 'github://PolyMathOrg/DataFrame/src' ].
|
baseline: 'PetitParser' with: [
|
||||||
|
spec
|
||||||
|
loads: #('Minimal' 'Core' 'Tests' 'Islands');
|
||||||
|
repository: 'github://moosetechnology/PetitParser:v3.x.x/src'
|
||||||
|
].
|
||||||
"self fossil: spec."
|
"self fossil: spec."
|
||||||
self xmlParserHTML: spec.
|
|
||||||
|
|
||||||
"Packages"
|
"Packages"
|
||||||
spec
|
spec
|
||||||
package: 'PetitMarkdown' with: [ spec requires: #('PetitParser')];
|
package: 'PetitMarkdown' with: [ spec requires: #('PetitParser')];
|
||||||
package: 'MiniDocs'
|
package: 'MiniDocs' with: [ spec requires: #('Mustache' 'Tealight' 'PetitMarkdown')].
|
||||||
with: [ spec requires: #(
|
|
||||||
'Mustache' 'Temple' "Templating"
|
|
||||||
'Teapot' 'Tealight' "Web server"
|
|
||||||
'PetitMarkdown' 'PetitParser' "Parsers"
|
|
||||||
'DataFrame' "Tabular data"
|
|
||||||
'LepiterBuildingBlocs' "Lepiter utilities")].
|
|
||||||
.
|
|
||||||
|
|
||||||
"Groups"
|
"Groups"
|
||||||
|
|
||||||
@ -46,7 +37,7 @@ BaselineOfMiniDocs >> baseline: spec [
|
|||||||
BaselineOfMiniDocs >> fossil: spec [
|
BaselineOfMiniDocs >> fossil: spec [
|
||||||
| repo |
|
| repo |
|
||||||
repo := ExoRepo new
|
repo := ExoRepo new
|
||||||
repository: 'https://code.sustrato.red/Offray/Fossil'.
|
repository: 'https://code.tupale.co/Offray/Fossil'.
|
||||||
repo load.
|
repo load.
|
||||||
spec baseline: 'Fossil' with: [ spec repository: 'gitlocal://', repo local fullName ]
|
spec baseline: 'Fossil' with: [ spec repository: 'gitlocal://', repo local fullName ]
|
||||||
]
|
]
|
||||||
@ -56,41 +47,15 @@ BaselineOfMiniDocs >> semanticVersion [
|
|||||||
^ '0.2.0'
|
^ '0.2.0'
|
||||||
]
|
]
|
||||||
|
|
||||||
{ #category : #accessing }
|
|
||||||
BaselineOfMiniDocs >> setUpLepiterBuildingBlocs: spec [
|
|
||||||
spec
|
|
||||||
baseline: 'LepiterBuildingBlocs'
|
|
||||||
with: [spec repository: 'github://botwhytho/LepiterBuildingBlocs:main/src']
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #accessing }
|
|
||||||
BaselineOfMiniDocs >> setUpPetitParser: spec [
|
|
||||||
spec
|
|
||||||
baseline: 'PetitParser'
|
|
||||||
with: [ spec
|
|
||||||
repository: 'github://moosetechnology/PetitParser:v3.x.x/src';
|
|
||||||
loads: #('Minimal' 'Core' 'Tests' 'Islands')];
|
|
||||||
import: 'PetitParser'
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #accessing }
|
|
||||||
BaselineOfMiniDocs >> setUpTeapot: spec [
|
|
||||||
|
|
||||||
spec
|
|
||||||
baseline: 'Teapot'
|
|
||||||
with: [ spec
|
|
||||||
repository: 'github://zeroflag/Teapot/source';
|
|
||||||
loads: #('ALL') ];
|
|
||||||
import: 'Teapot'
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #accessing }
|
{ #category : #accessing }
|
||||||
BaselineOfMiniDocs >> xmlParserHTML: spec [
|
BaselineOfMiniDocs >> xmlParserHTML: spec [
|
||||||
|
Metacello new
|
||||||
spec
|
baseline: 'XMLParserHTML';
|
||||||
baseline: 'XMLParserHTML'
|
repository: 'github://pharo-contributions/XML-XMLParserHTML/src';
|
||||||
with: [ spec
|
onConflict: [ :ex | ex useLoaded ];
|
||||||
repository: 'github://ruidajo/XML-XMLParserHTML/src';
|
onUpgrade: [ :ex | ex useLoaded ];
|
||||||
loads: #('ALL')];
|
onDowngrade: [ :ex | ex useLoaded ];
|
||||||
import: 'XMLParserHTML'
|
onWarningLog;
|
||||||
|
load.
|
||||||
|
spec baseline: 'XMLParserHTML' with: [spec repository: 'github://pharo-contributions/XML-XMLParserHTML/src']
|
||||||
]
|
]
|
||||||
|
@ -1,18 +0,0 @@
|
|||||||
"
|
|
||||||
I model a possible bridge between TaskWarrior and MiniDocs. (starting DRAFT).
|
|
||||||
"
|
|
||||||
Class {
|
|
||||||
#name : #AcroReport,
|
|
||||||
#superclass : #Object,
|
|
||||||
#category : #MiniDocs
|
|
||||||
}
|
|
||||||
|
|
||||||
{ #category : #accessing }
|
|
||||||
AcroReport class >> project: projectName [
|
|
||||||
| jsonReport |
|
|
||||||
jsonReport := (GtSubprocessWithInMemoryOutput new
|
|
||||||
shellCommand: 'task project:', projectName , ' export';
|
|
||||||
runAndWait;
|
|
||||||
stdout).
|
|
||||||
^ STONJSON fromString: jsonReport
|
|
||||||
]
|
|
@ -1,57 +0,0 @@
|
|||||||
Class {
|
|
||||||
#name : #AlphanumCounter,
|
|
||||||
#superclass : #Object,
|
|
||||||
#instVars : [
|
|
||||||
'letters',
|
|
||||||
'digits',
|
|
||||||
'currentLetter',
|
|
||||||
'currentDigit'
|
|
||||||
],
|
|
||||||
#category : #MiniDocs
|
|
||||||
}
|
|
||||||
|
|
||||||
{ #category : #accessing }
|
|
||||||
AlphanumCounter >> current [
|
|
||||||
^ self currentLetter asString, self currentDigit asString
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #accessing }
|
|
||||||
AlphanumCounter >> currentDigit [
|
|
||||||
|
|
||||||
^ currentDigit ifNil: [ currentDigit := self digits first ]
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #accessing }
|
|
||||||
AlphanumCounter >> currentLetter [
|
|
||||||
^ currentLetter ifNil: [ currentLetter := self letters first ]
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #accessing }
|
|
||||||
AlphanumCounter >> currentLetterIndex [
|
|
||||||
^ self letters detectIndex: [:n | n = self currentLetter]
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #accessing }
|
|
||||||
AlphanumCounter >> digits [
|
|
||||||
^ digits ifNil: [ digits := 1 to: 9 ]
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #accessing }
|
|
||||||
AlphanumCounter >> digits: aNumbersArray [
|
|
||||||
digits := aNumbersArray
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #accessing }
|
|
||||||
AlphanumCounter >> increase [
|
|
||||||
(self currentDigit < self digits last)
|
|
||||||
ifTrue: [ currentDigit := currentDigit + 1 ]
|
|
||||||
ifFalse: [
|
|
||||||
currentLetter := self letters at: (self currentLetterIndex + 1).
|
|
||||||
currentDigit := self digits first
|
|
||||||
]
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #accessing }
|
|
||||||
AlphanumCounter >> letters [
|
|
||||||
^ letters ifNil: [ letters := $A to: $Z ]
|
|
||||||
]
|
|
@ -1,45 +0,0 @@
|
|||||||
Extension { #name : #Array }
|
|
||||||
|
|
||||||
{ #category : #'*MiniDocs' }
|
|
||||||
Array >> bagOfWordsFor: sentenceArray [
|
|
||||||
"An utility machine training little algorithm.
|
|
||||||
Inspired by https://youtu.be/8qwowmiXANQ?t=1144.
|
|
||||||
This should be moved probably to [Polyglot](https://github.com/pharo-ai/Polyglot),
|
|
||||||
but the repository is pretty innactive (with commits 2 or more years old and no reponse to issues).
|
|
||||||
Meanwhile, it will be in MiniDocs.
|
|
||||||
|
|
||||||
Given the sentence := #('hello' 'how' 'are' 'you')
|
|
||||||
and the testVocabulary := #('hi' 'hello' 'I' 'you' 'bye' 'thank' 'you')
|
|
||||||
then
|
|
||||||
|
|
||||||
testVocabulary bagOfWordsFor: sentence.
|
|
||||||
|
|
||||||
Should give: #(0 1 0 1 0 0 0)
|
|
||||||
"
|
|
||||||
| bagOfWords |
|
|
||||||
bagOfWords := Array new: self size.
|
|
||||||
bagOfWords doWithIndex: [:each :i | bagOfWords at: i put: 0 ].
|
|
||||||
sentenceArray do: [:token | |index|
|
|
||||||
index := self indexOf: token.
|
|
||||||
index > 0
|
|
||||||
ifTrue: [bagOfWords at: index put: 1]
|
|
||||||
].
|
|
||||||
^ bagOfWords
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #'*MiniDocs' }
|
|
||||||
Array >> replaceWithUniqueNilsAndBooleans [
|
|
||||||
| response |
|
|
||||||
(self includesAny: #(true false nil))
|
|
||||||
ifFalse: [ response := self ]
|
|
||||||
ifTrue: [ | newItem |
|
|
||||||
response := OrderedCollection new.
|
|
||||||
self do: [:item |
|
|
||||||
(item isBoolean or: [ item isNil ])
|
|
||||||
ifTrue: [ newItem := item asString, '-', (NanoID generate copyFrom: 1 to: 3) ]
|
|
||||||
ifFalse: [ newItem := item ].
|
|
||||||
response add: newItem.
|
|
||||||
].
|
|
||||||
].
|
|
||||||
^ response
|
|
||||||
]
|
|
@ -1,12 +0,0 @@
|
|||||||
Extension { #name : #ByteString }
|
|
||||||
|
|
||||||
{ #category : #'*MiniDocs' }
|
|
||||||
ByteString >> asHTMLComment [
|
|
||||||
^ '<!-- ', self , ' -->'
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #'*MiniDocs' }
|
|
||||||
ByteString >> email [
|
|
||||||
"Quick fix for importing Lepiter pages that have a plain ByteString field as email."
|
|
||||||
^ self
|
|
||||||
]
|
|
@ -1,46 +0,0 @@
|
|||||||
Extension { #name : #DataFrame }
|
|
||||||
|
|
||||||
{ #category : #'*MiniDocs' }
|
|
||||||
DataFrame >> asMarkdown [
|
|
||||||
| response |
|
|
||||||
response := '' writeStream.
|
|
||||||
self columnNames do: [ :name | response nextPutAll: '| ' , name , ' ' ].
|
|
||||||
response
|
|
||||||
nextPutAll: '|';
|
|
||||||
cr.
|
|
||||||
self columns size timesRepeat: [ response nextPutAll: '|---' ].
|
|
||||||
response
|
|
||||||
nextPutAll: '|';
|
|
||||||
cr.
|
|
||||||
self asArrayOfRows
|
|
||||||
do: [ :row |
|
|
||||||
row do: [ :cell | response nextPutAll: '| ' , cell asString , ' ' ].
|
|
||||||
response
|
|
||||||
nextPutAll: '|';
|
|
||||||
cr ].
|
|
||||||
^ response contents accentedCharactersCorrection withInternetLineEndings.
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #'*MiniDocs' }
|
|
||||||
DataFrame >> viewDataFor: aView [
|
|
||||||
<gtView>
|
|
||||||
| columnedList |
|
|
||||||
self numberOfRows >= 1 ifFalse: [ ^ aView empty ].
|
|
||||||
columnedList := aView columnedList
|
|
||||||
title: 'Data';
|
|
||||||
items: [ self transposed columns ];
|
|
||||||
priority: 40.
|
|
||||||
self columnNames
|
|
||||||
withIndexDo: [:aName :anIndex |
|
|
||||||
columnedList
|
|
||||||
column: aName
|
|
||||||
text: [:anItem | anItem at: anIndex ]
|
|
||||||
].
|
|
||||||
^ columnedList
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #'*MiniDocs' }
|
|
||||||
DataFrame >> webView [
|
|
||||||
|
|
||||||
^ Pandoc convertString: self asMarkdown from: 'markdown' to: 'html'
|
|
||||||
]
|
|
@ -1,6 +0,0 @@
|
|||||||
Extension { #name : #Dictionary }
|
|
||||||
|
|
||||||
{ #category : #'*MiniDocs' }
|
|
||||||
Dictionary >> treeView [
|
|
||||||
^ self asOrderedDictionary treeView
|
|
||||||
]
|
|
@ -1,53 +0,0 @@
|
|||||||
Extension { #name : #FileLocator }
|
|
||||||
|
|
||||||
{ #category : #'*MiniDocs' }
|
|
||||||
FileLocator class >> aliases [
|
|
||||||
| fileAliases |
|
|
||||||
fileAliases := self fileAliases.
|
|
||||||
fileAliases exists
|
|
||||||
ifFalse: [ | initialConfig |
|
|
||||||
initialConfig := Dictionary new.
|
|
||||||
fileAliases ensureCreateFile.
|
|
||||||
MarkupFile exportAsFileOn: fileAliases containing: initialConfig
|
|
||||||
].
|
|
||||||
^ STON fromString: fileAliases contents
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #'*MiniDocs' }
|
|
||||||
FileLocator class >> atAlias: aString put: aFolderOrFile [
|
|
||||||
| updatedAliases |
|
|
||||||
updatedAliases:= self aliases
|
|
||||||
at: aString put: aFolderOrFile;
|
|
||||||
yourself.
|
|
||||||
MarkupFile exportAsFileOn: self fileAliases containing: updatedAliases.
|
|
||||||
^ updatedAliases
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #'*MiniDocs' }
|
|
||||||
FileLocator >> extractMetadata [
|
|
||||||
"I package the functionality from [[How to extract meta information using ExifTool]],
|
|
||||||
from the GToolkit Book.
|
|
||||||
I depend on the external tool ExifTool."
|
|
||||||
|
|
||||||
| process variablesList |
|
|
||||||
process := GtSubprocessWithInMemoryOutput new
|
|
||||||
command: 'exiftool';
|
|
||||||
arguments: { self fullName}.
|
|
||||||
process errorBlock: [ :proc | ^ self error: 'Failed to run exiftool' ].
|
|
||||||
process runAndWait.
|
|
||||||
variablesList := process stdout lines collect: [ :currentLine |
|
|
||||||
| separatorIndex name value |
|
|
||||||
separatorIndex := currentLine indexOf: $:.
|
|
||||||
name := (currentLine copyFrom: 1 to: separatorIndex - 1) trimBoth.
|
|
||||||
value := (currentLine
|
|
||||||
copyFrom: separatorIndex + 1
|
|
||||||
to: currentLine size) trimBoth.
|
|
||||||
name -> value
|
|
||||||
].
|
|
||||||
^ variablesList asOrderedDictionary
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #'*MiniDocs' }
|
|
||||||
FileLocator class >> fileAliases [
|
|
||||||
^ MiniDocs appFolder / 'fileAliases.ston'
|
|
||||||
]
|
|
@ -27,14 +27,6 @@ GrafoscopioNode class >> fromFile: aFileReference [
|
|||||||
^ (STON fromString: aFileReference contents) first parent
|
^ (STON fromString: aFileReference contents) first parent
|
||||||
]
|
]
|
||||||
|
|
||||||
{ #category : #accessing }
|
|
||||||
GrafoscopioNode class >> fromLink: aStonLink [
|
|
||||||
| notebook |
|
|
||||||
notebook := (STON fromString: aStonLink asUrl retrieveContents utf8Decoded) first parent.
|
|
||||||
notebook addRemoteLocation: aStonLink.
|
|
||||||
^ notebook
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #accessing }
|
{ #category : #accessing }
|
||||||
GrafoscopioNode >> addRemoteLocation: anURL [
|
GrafoscopioNode >> addRemoteLocation: anURL [
|
||||||
self remoteLocations add: anURL
|
self remoteLocations add: anURL
|
||||||
@ -61,11 +53,10 @@ GrafoscopioNode >> asLePage [
|
|||||||
self root populateTimestamps.
|
self root populateTimestamps.
|
||||||
page := LePage new
|
page := LePage new
|
||||||
initializeTitle: 'Grafoscopio Notebook (imported)'.
|
initializeTitle: 'Grafoscopio Notebook (imported)'.
|
||||||
self nodesInPreorder allButFirst
|
self nodesInPreorder allButFirst do: [:node |
|
||||||
do: [:node | page addSnippet: node asSnippet ].
|
page addSnippet: node asSnippet ].
|
||||||
page latestEditTime: self root latestEditionDate.
|
page latestEditTime: self root latestEditionDate.
|
||||||
page createTime: self root earliestCreationDate.
|
page createTime: self root earliestCreationDate.
|
||||||
page optionAt: 'remoteLocations' put: self remoteLocations.
|
|
||||||
^ page.
|
^ page.
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -1,72 +0,0 @@
|
|||||||
Extension { #name : #GtGQLSnippet }
|
|
||||||
|
|
||||||
{ #category : #'*MiniDocs' }
|
|
||||||
GtGQLSnippet >> asMarkdeep [
|
|
||||||
| output |
|
|
||||||
output := WriteStream on: ''.
|
|
||||||
(self metadata)
|
|
||||||
at: 'operation' put: self operation;
|
|
||||||
at: 'input' put: self input;
|
|
||||||
at: 'context' put: self context;
|
|
||||||
yourself.
|
|
||||||
output
|
|
||||||
nextPutAll: self metadataDiv;
|
|
||||||
nextPutAll: self markdeepCustomOpener;
|
|
||||||
nextPutAll: self asMarkdownString;
|
|
||||||
nextPut: Character lf;
|
|
||||||
nextPutAll: self markdeepCustomCloser;
|
|
||||||
nextPut: Character lf;
|
|
||||||
nextPutAll: '</div>';
|
|
||||||
nextPut: Character lf;
|
|
||||||
nextPut: Character lf.
|
|
||||||
^ output contents withInternetLineEndings
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #'*MiniDocs' }
|
|
||||||
GtGQLSnippet >> markdeepCustomCloser [
|
|
||||||
^ self markdeepCustomOpener
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #'*MiniDocs' }
|
|
||||||
GtGQLSnippet >> markdeepCustomOpener [
|
|
||||||
^ '* * *'
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #'*MiniDocs' }
|
|
||||||
GtGQLSnippet >> metadataDiv [
|
|
||||||
"PENDING: Shared among several snippets. Should be abstracted further?"
|
|
||||||
| output |
|
|
||||||
output := WriteStream on: ''.
|
|
||||||
output
|
|
||||||
nextPutAll: '<div st-class="' , self class greaseString , '"';
|
|
||||||
nextPut: Character lf;
|
|
||||||
nextPutAll: ' st-data="' , (STON toStringPretty: self metadata) , '">';
|
|
||||||
nextPut: Character lf.
|
|
||||||
^ output contents withInternetLineEndings.
|
|
||||||
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #'*MiniDocs' }
|
|
||||||
GtGQLSnippet >> metadataUpdate [
|
|
||||||
| createEmailSanitized editEmailSanitized |
|
|
||||||
createEmailSanitized := self createEmail asString withoutXMLTagDelimiters.
|
|
||||||
editEmailSanitized := self editEmail asString withoutXMLTagDelimiters.
|
|
||||||
^ OrderedDictionary new
|
|
||||||
at: 'id' put: self uidString;
|
|
||||||
at: 'parent' put: self parent uid asString36;
|
|
||||||
at: 'created' put: self createTime asString;
|
|
||||||
at: 'modified' put: self latestEditTime asString;
|
|
||||||
at: 'creator' put: createEmailSanitized;
|
|
||||||
at: 'modifier' put: editEmailSanitized;
|
|
||||||
yourself
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #'*MiniDocs' }
|
|
||||||
GtGQLSnippet >> sanitizeMetadata [
|
|
||||||
self metadata keysAndValuesDo: [:k :v |
|
|
||||||
(v includesAny: #($< $>))
|
|
||||||
ifTrue: [
|
|
||||||
self metadata at: k put: (v copyWithoutAll: #($< $>))
|
|
||||||
]
|
|
||||||
]
|
|
||||||
]
|
|
@ -16,52 +16,12 @@ Class {
|
|||||||
#category : #'MiniDocs-Core'
|
#category : #'MiniDocs-Core'
|
||||||
}
|
}
|
||||||
|
|
||||||
{ #category : #accessing }
|
|
||||||
HedgeDoc class >> fromLink: aUrl [
|
|
||||||
^ self new fromLink: aUrl
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #'as yet unclassified' }
|
{ #category : #'as yet unclassified' }
|
||||||
HedgeDoc class >> newDefault [
|
HedgeDoc class >> newDefault [
|
||||||
^ self new
|
^ self new
|
||||||
defaultServer.
|
defaultServer.
|
||||||
]
|
]
|
||||||
|
|
||||||
{ #category : #accessing }
|
|
||||||
HedgeDoc >> asLePage [
|
|
||||||
| newPage sanitizedMarkdown |
|
|
||||||
sanitizedMarkdown := self bodyWithoutTitleHeader promoteMarkdownHeaders.
|
|
||||||
newPage := LePage new
|
|
||||||
initializeTitle: self title.
|
|
||||||
sanitizedMarkdown := sanitizedMarkdown markdownSplitted.
|
|
||||||
sanitizedMarkdown class = OrderedCollection ifTrue: [
|
|
||||||
sanitizedMarkdown do: [:lines | | snippet |
|
|
||||||
snippet := LeTextSnippet new
|
|
||||||
string: lines asStringWithCr;
|
|
||||||
uid: LeUID new.
|
|
||||||
newPage
|
|
||||||
addSnippet: snippet;
|
|
||||||
yourself
|
|
||||||
]
|
|
||||||
].
|
|
||||||
sanitizedMarkdown class = ByteString ifTrue: [ | snippet |
|
|
||||||
snippet := LeTextSnippet new
|
|
||||||
string: sanitizedMarkdown;
|
|
||||||
uid: LeUID new.
|
|
||||||
newPage
|
|
||||||
addSnippet: snippet;
|
|
||||||
yourself
|
|
||||||
].
|
|
||||||
newPage
|
|
||||||
incomingLinks;
|
|
||||||
splitAdmonitionSnippets.
|
|
||||||
newPage editTime: DateAndTime now.
|
|
||||||
newPage options
|
|
||||||
at: 'HedgeDoc' at: 'yamlFrontmatter' put: self metadata;
|
|
||||||
at: 'HedgeDoc' at: 'url' put: self url asString asHTMLComment.
|
|
||||||
^ newPage
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #accessing }
|
{ #category : #accessing }
|
||||||
HedgeDoc >> asMarkdeep [
|
HedgeDoc >> asMarkdeep [
|
||||||
^ Markdeep new
|
^ Markdeep new
|
||||||
@ -80,18 +40,9 @@ HedgeDoc >> asMarkdownTiddler [
|
|||||||
created: Tiddler nowLocal.
|
created: Tiddler nowLocal.
|
||||||
]
|
]
|
||||||
|
|
||||||
{ #category : #accessing }
|
|
||||||
HedgeDoc >> bodyWithoutTitleHeader [
|
|
||||||
| headerIndex |
|
|
||||||
headerIndex := self body lines
|
|
||||||
detectIndex: [ :line | line includesSubstring: self headerAsTitle ]
|
|
||||||
ifNone: [ ^ self body].
|
|
||||||
^ (self body lines copyWithoutIndex: headerIndex) asStringWithCr
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #accessing }
|
{ #category : #accessing }
|
||||||
HedgeDoc >> contents [
|
HedgeDoc >> contents [
|
||||||
^ super contents
|
^ body
|
||||||
]
|
]
|
||||||
|
|
||||||
{ #category : #accessing }
|
{ #category : #accessing }
|
||||||
@ -104,12 +55,6 @@ HedgeDoc >> defaultServer [
|
|||||||
self server: 'https://docutopia.tupale.co'.
|
self server: 'https://docutopia.tupale.co'.
|
||||||
]
|
]
|
||||||
|
|
||||||
{ #category : #accessing }
|
|
||||||
HedgeDoc >> fromLink: aString [
|
|
||||||
self url: aString.
|
|
||||||
self retrieveContents
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #'as yet unclassified' }
|
{ #category : #'as yet unclassified' }
|
||||||
HedgeDoc >> htmlUrl [
|
HedgeDoc >> htmlUrl [
|
||||||
| link |
|
| link |
|
||||||
@ -136,7 +81,7 @@ HedgeDoc >> pad: anObject [
|
|||||||
{ #category : #accessing }
|
{ #category : #accessing }
|
||||||
HedgeDoc >> retrieveContents [
|
HedgeDoc >> retrieveContents [
|
||||||
self url ifNil: [ ^ self ].
|
self url ifNil: [ ^ self ].
|
||||||
self fromString: (self url addPathSegment: 'download') retrieveContents.
|
self contents: (self url addPathSegment: 'download') retrieveContents.
|
||||||
^ self.
|
^ self.
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -172,18 +117,11 @@ HedgeDoc >> server: aUrlString [
|
|||||||
|
|
||||||
{ #category : #accessing }
|
{ #category : #accessing }
|
||||||
HedgeDoc >> url [
|
HedgeDoc >> url [
|
||||||
url ifNotNil: [ ^ url asUrl ]
|
^ url asUrl
|
||||||
]
|
]
|
||||||
|
|
||||||
{ #category : #accessing }
|
{ #category : #accessing }
|
||||||
HedgeDoc >> url: anObject [
|
HedgeDoc >> url: anObject [
|
||||||
| tempUrl html |
|
|
||||||
tempUrl := anObject asZnUrl.
|
|
||||||
html := XMLHTMLParser parse: tempUrl retrieveContents.
|
|
||||||
(html xpath: '//head/meta[@name="application-name"][@content = "HedgeDoc - Ideas grow better together"]') isEmpty
|
|
||||||
ifTrue: [ self inform: 'Not a hedgedoc url'.
|
|
||||||
url := nil ].
|
|
||||||
server := tempUrl host.
|
|
||||||
url := anObject
|
url := anObject
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -7,17 +7,17 @@ Class {
|
|||||||
#category : #'MiniDocs-Model'
|
#category : #'MiniDocs-Model'
|
||||||
}
|
}
|
||||||
|
|
||||||
{ #category : #accessing }
|
|
||||||
HedgeDocGrammar >> metadataAsYAML [
|
|
||||||
"I parse the header of the hedgedoc document for YAML metadata."
|
|
||||||
^ '---' asPParser token, #any asPParser starLazy token, '---' asPParser token
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #accessing }
|
{ #category : #accessing }
|
||||||
HedgeDocGrammar >> start [
|
HedgeDocGrammar >> start [
|
||||||
| any |
|
| any |
|
||||||
any := #any asPParser.
|
any := #any asPParser.
|
||||||
^ (self metadataAsYAML / any starLazy), youtubeEmbeddedLink
|
^ (self yamlMetadata / any starLazy), youtubeEmbeddedLink
|
||||||
|
]
|
||||||
|
|
||||||
|
{ #category : #accessing }
|
||||||
|
HedgeDocGrammar >> yamlMetadata [
|
||||||
|
"I parse the header of the hedgedoc document for YAML metadata."
|
||||||
|
^ '---' asPParser token, #any asPParser starLazy token, '---' asPParser token
|
||||||
]
|
]
|
||||||
|
|
||||||
{ #category : #accessing }
|
{ #category : #accessing }
|
||||||
|
@ -1,26 +0,0 @@
|
|||||||
Extension { #name : #LeChangesSnippet }
|
|
||||||
|
|
||||||
{ #category : #'*MiniDocs' }
|
|
||||||
LeChangesSnippet >> metadataUpdate [
|
|
||||||
| createEmailSanitized editEmailSanitized |
|
|
||||||
createEmailSanitized := self createEmail asString withoutXMLTagDelimiters.
|
|
||||||
editEmailSanitized := self editEmail asString withoutXMLTagDelimiters.
|
|
||||||
^ OrderedDictionary new
|
|
||||||
at: 'id' put: self uidString;
|
|
||||||
at: 'parent' put: self parent uuid;
|
|
||||||
at: 'created' put: self createTime asString;
|
|
||||||
at: 'modified' put: self latestEditTime asString;
|
|
||||||
at: 'creator' put: createEmailSanitized;
|
|
||||||
at: 'modifier' put: editEmailSanitized;
|
|
||||||
yourself
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #'*MiniDocs' }
|
|
||||||
LeChangesSnippet >> sanitizeMetadata [
|
|
||||||
self metadata keysAndValuesDo: [:k :v |
|
|
||||||
(v includesAny: #($< $>))
|
|
||||||
ifTrue: [
|
|
||||||
self metadata at: k put: (v copyWithoutAll: #($< $>))
|
|
||||||
]
|
|
||||||
]
|
|
||||||
]
|
|
@ -1,21 +0,0 @@
|
|||||||
Extension { #name : #LeCodeSnippet }
|
|
||||||
|
|
||||||
{ #category : #'*MiniDocs' }
|
|
||||||
LeCodeSnippet >> metadataUpdate [
|
|
||||||
| surrogate |
|
|
||||||
self parent
|
|
||||||
ifNil: [ surrogate := nil]
|
|
||||||
ifNotNil: [
|
|
||||||
self parent isString
|
|
||||||
ifTrue: [ surrogate := self parent]
|
|
||||||
ifFalse: [ surrogate := self parent uidString ]
|
|
||||||
].
|
|
||||||
^ OrderedDictionary new
|
|
||||||
at: 'id' put: self uidString;
|
|
||||||
at: 'parent' put: surrogate;
|
|
||||||
at: 'created' put: self createTime asString;
|
|
||||||
at: 'modified' put: self latestEditTime asString;
|
|
||||||
at: 'creator' put: self createEmail asString withoutXMLTagDelimiters;
|
|
||||||
at: 'modifier' put: self editEmail asString withoutXMLTagDelimiters;
|
|
||||||
yourself
|
|
||||||
]
|
|
@ -1,17 +1,28 @@
|
|||||||
Extension { #name : #LeDatabase }
|
Extension { #name : #LeDatabase }
|
||||||
|
|
||||||
{ #category : #'*MiniDocs' }
|
{ #category : #'*MiniDocs' }
|
||||||
LeDatabase >> addPage2FromMarkdeep: markdeepDocTree withRemote: externalDocLocation [
|
LeDatabase >> addPageFromMarkdeep: markdeepDocTree withRemote: externalDocLocation [
|
||||||
| newPage |
|
| remoteMetadata divSnippets snippets page |
|
||||||
"^ { snippets . page }"
|
divSnippets := (markdeepDocTree xpath: '//div[@st-class]') asOrderedCollection
|
||||||
"Rebulding partial subtrees"
|
collect: [ :xmlElement | xmlElement postCopy ].
|
||||||
"Adding unrooted subtrees to the page"
|
snippets := divSnippets
|
||||||
"^ newPage"
|
collect: [ :xmlElement |
|
||||||
newPage := self
|
(xmlElement attributes at: 'st-class') = 'LeTextSnippet'
|
||||||
rebuildPageFromMarkdeep: markdeepDocTree
|
ifTrue: [ LeTextSnippet new contentFrom: xmlElement ]
|
||||||
withRemote: externalDocLocation.
|
ifFalse: [ (xmlElement attributes at: 'st-class') = 'LePharoSnippet'
|
||||||
newPage
|
ifTrue: [ LePharoSnippet new contentFrom: xmlElement ] ] ].
|
||||||
childrenDo: [ :snippet |
|
remoteMetadata := Markdeep new metadataFromXML: markdeepDocTree.
|
||||||
|
page := LePage new
|
||||||
|
title: (remoteMetadata at: 'title');
|
||||||
|
basicUid: (UUID fromString36: (remoteMetadata at: 'id'));
|
||||||
|
createTime: (LeTime new time: (remoteMetadata at: 'created') asDateAndTime);
|
||||||
|
editTime: (LeTime new time: (remoteMetadata at: 'modified') asDateAndTime);
|
||||||
|
latestEditTime: (LeTime new time: (remoteMetadata at: 'modified') asDateAndTime);
|
||||||
|
createEmail: (remoteMetadata at: 'creator');
|
||||||
|
editEmail: (remoteMetadata at: 'modifier').
|
||||||
|
snippets do: [ :snippet | page addSnippet: snippet ].
|
||||||
|
page children
|
||||||
|
do: [ :snippet |
|
||||||
(self hasBlockUID: snippet uid)
|
(self hasBlockUID: snippet uid)
|
||||||
ifTrue: [ | existingPage |
|
ifTrue: [ | existingPage |
|
||||||
existingPage := self pages
|
existingPage := self pages
|
||||||
@ -20,56 +31,6 @@ LeDatabase >> addPage2FromMarkdeep: markdeepDocTree withRemote: externalDocLocat
|
|||||||
^ self ]
|
^ self ]
|
||||||
ifFalse: [ snippet database: self.
|
ifFalse: [ snippet database: self.
|
||||||
self registerSnippet: snippet ] ].
|
self registerSnippet: snippet ] ].
|
||||||
self addPage: newPage.
|
|
||||||
^ newPage
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #'*MiniDocs' }
|
|
||||||
LeDatabase >> addPageCopy: aLePage [
|
|
||||||
| pageTitle timestamp shortID page |
|
|
||||||
timestamp := DateAndTime now asString.
|
|
||||||
pageTitle := 'Copy of ', aLePage title.
|
|
||||||
page := aLePage duplicatePageWithNewName: pageTitle, timestamp.
|
|
||||||
shortID := '(id: ', (page uid asString copyFrom: 1 to: 8), ')'.
|
|
||||||
page title: (page title copyReplaceAll: timestamp with: shortID).
|
|
||||||
^ page
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #'*MiniDocs' }
|
|
||||||
LeDatabase >> addPageFromMarkdeep: markdeepDocTree withRemote: externalDocLocation [
|
|
||||||
| remoteMetadata divSnippets dataSnippets page |
|
|
||||||
divSnippets := (markdeepDocTree xpath: '//div[@st-class]') asOrderedCollection
|
|
||||||
collect: [ :xmlElement | xmlElement postCopy ].
|
|
||||||
remoteMetadata := Markdeep new metadataFromXML: markdeepDocTree.
|
|
||||||
"Ensuring remote metadata has consistent data"
|
|
||||||
remoteMetadata at: 'origin' put: externalDocLocation.
|
|
||||||
remoteMetadata at: 'title' ifAbsentPut: [ markdeepDocTree detectMarkdeepTitle ].
|
|
||||||
remoteMetadata at: 'id' ifAbsentPut: [UUID new asString36].
|
|
||||||
remoteMetadata at: 'created' ifAbsentPut: [ DateAndTime now] .
|
|
||||||
remoteMetadata at: 'creator' ifAbsentPut: [ 'unknown' ].
|
|
||||||
remoteMetadata at: 'modified' ifAbsentPut: [ DateAndTime now].
|
|
||||||
remoteMetadata at: 'modifier' ifAbsentPut: [ 'unknown' ].
|
|
||||||
dataSnippets := self sanitizeMarkdeepSnippets: divSnippets withMetadata: remoteMetadata.
|
|
||||||
page := LePage new.
|
|
||||||
page fromDictionary: remoteMetadata.
|
|
||||||
dataSnippets do: [:each | | snippet|
|
|
||||||
snippet := each asLepiterSnippet.
|
|
||||||
page addSnippet: snippet.
|
|
||||||
].
|
|
||||||
page children
|
|
||||||
do: [ :snippet |
|
|
||||||
(self hasBlockUID: snippet uid)
|
|
||||||
ifTrue: [ | existingPage |
|
|
||||||
existingPage := self pages
|
|
||||||
detect: [ :pageTemp | pageTemp includesSnippetUid: snippet uid ]
|
|
||||||
ifFound: [
|
|
||||||
self importErrorForLocal: existingPage withRemote: externalDocLocation.
|
|
||||||
^ self
|
|
||||||
]
|
|
||||||
ifNone: [ snippet database: self ].
|
|
||||||
]
|
|
||||||
ifFalse: [ snippet database: self ]
|
|
||||||
].
|
|
||||||
self addPage: page.
|
self addPage: page.
|
||||||
^ page
|
^ page
|
||||||
]
|
]
|
||||||
@ -81,7 +42,7 @@ LeDatabase >> addPageFromMarkdeepUrl: aString [
|
|||||||
page
|
page
|
||||||
ifNotNil: [ :arg |
|
ifNotNil: [ :arg |
|
||||||
self importErrorForLocal: page withRemote: aString.
|
self importErrorForLocal: page withRemote: aString.
|
||||||
^ self errorCardFor: page uidString ].
|
^ self ].
|
||||||
^ self addPageFromMarkdeep: (self docTreeForLink: aString) withRemote: aString
|
^ self addPageFromMarkdeep: (self docTreeForLink: aString) withRemote: aString
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -101,10 +62,10 @@ LeDatabase >> docTreeForLink: aString [
|
|||||||
]
|
]
|
||||||
|
|
||||||
{ #category : #'*MiniDocs' }
|
{ #category : #'*MiniDocs' }
|
||||||
LeDatabase >> errorCardFor: errorKey [
|
LeDatabase >> errorCardFor: error [
|
||||||
|
|
||||||
| keepButton overwriteButton loadCopyButton errorMessageUI localPage |
|
|
||||||
|
|
||||||
|
| keepButton overwriteButton backupButton errorMessageUI localPage errorKey |
|
||||||
|
errorKey := error keys first.
|
||||||
localPage := self pageWithID: errorKey.
|
localPage := self pageWithID: errorKey.
|
||||||
keepButton := BrButton new
|
keepButton := BrButton new
|
||||||
aptitude: BrGlamorousButtonWithIconAndLabelAptitude;
|
aptitude: BrGlamorousButtonWithIconAndLabelAptitude;
|
||||||
@ -121,28 +82,22 @@ LeDatabase >> errorCardFor: errorKey [
|
|||||||
icon: BrGlamorousVectorIcons edit;
|
icon: BrGlamorousVectorIcons edit;
|
||||||
action: [ :aButton |
|
action: [ :aButton |
|
||||||
self removePage: localPage.
|
self removePage: localPage.
|
||||||
aButton phlow spawnObject: (self addPageFromMarkdeepUrl: (self errors at: errorKey at: 'remote')).
|
aButton phlow spawnObject: (self addPageFromMarkdeepUrl: (error at: errorKey at: 'remote')).
|
||||||
self errors removeKey: errorKey
|
self errors removeKey: errorKey
|
||||||
];
|
];
|
||||||
margin: (BlInsets left: 10).
|
margin: (BlInsets left: 10).
|
||||||
loadCopyButton := BrButton new
|
backupButton := BrButton new
|
||||||
aptitude: BrGlamorousButtonWithIconAndLabelAptitude;
|
aptitude: BrGlamorousButtonWithIconAndLabelAptitude;
|
||||||
label: 'Load remote page as a copy';
|
label: 'Backup local page';
|
||||||
icon: BrGlamorousVectorIcons changes;
|
icon: BrGlamorousVectorIcons changes;
|
||||||
action: [ :aButton | self ];
|
action: [ :aButton | ];
|
||||||
margin: (BlInsets left: 10).
|
margin: (BlInsets left: 10).
|
||||||
|
|
||||||
errorMessageUI := BrEditor new
|
errorMessageUI := BrEditor new
|
||||||
aptitude: BrGlamorousRegularEditorAptitude new ;
|
aptitude: BrGlamorousRegularEditorAptitude new ;
|
||||||
text: (self errors at: errorKey at: 'message');
|
text: (error at: errorKey at: 'message');
|
||||||
vFitContent.
|
vFitContent.
|
||||||
^ BrHorizontalPane new
|
^ { errorMessageUI. keepButton. overwriteButton. backupButton }
|
||||||
matchParent;
|
|
||||||
alignCenter;
|
|
||||||
addChild:errorMessageUI;
|
|
||||||
addChild: keepButton;
|
|
||||||
addChild: overwriteButton;
|
|
||||||
addChild: loadCopyButton
|
|
||||||
]
|
]
|
||||||
|
|
||||||
{ #category : #'*MiniDocs' }
|
{ #category : #'*MiniDocs' }
|
||||||
@ -169,34 +124,6 @@ LeDatabase >> gtViewErrorDetailsOn: aView [
|
|||||||
].
|
].
|
||||||
]
|
]
|
||||||
|
|
||||||
{ #category : #'*MiniDocs' }
|
|
||||||
LeDatabase >> gtViewErrorDetailsOn: aView withKey: erroKey [
|
|
||||||
<gtView>
|
|
||||||
^ aView explicit
|
|
||||||
title: 'Errors beta' translated;
|
|
||||||
priority: 5;
|
|
||||||
stencil: [ | container |
|
|
||||||
container := BlElement new
|
|
||||||
layout: BlFlowLayout new;
|
|
||||||
constraintsDo: [ :c |
|
|
||||||
c vertical fitContent.
|
|
||||||
c horizontal matchParent ];
|
|
||||||
padding: (BlInsets all: 10).
|
|
||||||
container
|
|
||||||
addChildren: (self errorCardFor: erroKey)
|
|
||||||
].
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #'*MiniDocs' }
|
|
||||||
LeDatabase >> importDocumentFrom: aURL [
|
|
||||||
| doc |
|
|
||||||
"Using file extension in URL as a cheap (non-robuts) way of detecting the kind of document.
|
|
||||||
Better file type detection should be implemented in the future."
|
|
||||||
(aURL endsWith: '.md.html') ifTrue: [ ^ self addPageFromMarkdeepUrl: aURL ].
|
|
||||||
doc := HedgeDoc fromLink: aURL asString.
|
|
||||||
^ self addPage: doc asLePage
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #'*MiniDocs' }
|
{ #category : #'*MiniDocs' }
|
||||||
LeDatabase >> importErrorForLocal: page withRemote: externalDocLocation [
|
LeDatabase >> importErrorForLocal: page withRemote: externalDocLocation [
|
||||||
|
|
||||||
@ -227,8 +154,7 @@ LeDatabase >> importErrorForLocal: page withRemote: externalDocLocation [
|
|||||||
at: 'remote' put: externalDocLocation;
|
at: 'remote' put: externalDocLocation;
|
||||||
at: 'message' put: message ;
|
at: 'message' put: message ;
|
||||||
yourself.
|
yourself.
|
||||||
self errors at: id put: error.
|
self errors at: id put: error
|
||||||
^ self errors at: id.
|
|
||||||
]
|
]
|
||||||
|
|
||||||
{ #category : #'*MiniDocs' }
|
{ #category : #'*MiniDocs' }
|
||||||
@ -236,77 +162,3 @@ LeDatabase >> options [
|
|||||||
|
|
||||||
^ options
|
^ options
|
||||||
]
|
]
|
||||||
|
|
||||||
{ #category : #'*MiniDocs' }
|
|
||||||
LeDatabase >> previewSanitizedPageFromMarkdeep: markdeepDocTree withRemote: externalDocLocation [
|
|
||||||
| remoteMetadata divSnippets divSnippetsSanitized |
|
|
||||||
divSnippets := (markdeepDocTree xpath: '//div[@st-class]') asOrderedCollection
|
|
||||||
collect: [ :xmlElement | xmlElement postCopy ].
|
|
||||||
remoteMetadata := Markdeep new metadataFromXML: markdeepDocTree.
|
|
||||||
remoteMetadata at: 'origin' put: externalDocLocation.
|
|
||||||
divSnippetsSanitized := self sanitizeMarkdeepSnippets: divSnippets withMetadata: remoteMetadata.
|
|
||||||
^ { divSnippets . divSnippetsSanitized . remoteMetadata }
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #'*MiniDocs' }
|
|
||||||
LeDatabase >> rebuildPageFromMarkdeep: markdeepDocTree withRemote: externalDocLocation [
|
|
||||||
| newPage snippets divSnippets remoteMetadata dataSnippets |
|
|
||||||
divSnippets := (markdeepDocTree xpath: '//div[@st-class]') asOrderedCollection
|
|
||||||
collect: [ :xmlElement | xmlElement postCopy ].
|
|
||||||
remoteMetadata := Markdeep new metadataFromXML: markdeepDocTree.
|
|
||||||
remoteMetadata at: 'origin' put: externalDocLocation.
|
|
||||||
dataSnippets := self
|
|
||||||
sanitizeMarkdeepSnippets: divSnippets
|
|
||||||
withMetadata: remoteMetadata.
|
|
||||||
snippets := dataSnippets collect: [ :each | each asLepiterSnippet ].
|
|
||||||
newPage := LePage new
|
|
||||||
title: (remoteMetadata at: 'title');
|
|
||||||
basicUid: (UUID fromString36: (remoteMetadata at: 'id'));
|
|
||||||
createTime: (LeTime new time: (remoteMetadata at: 'created') asDateAndTime);
|
|
||||||
editTime: (LeTime new time: (remoteMetadata at: 'modified') asDateAndTime);
|
|
||||||
latestEditTime: (LeTime new time: (remoteMetadata at: 'modified') asDateAndTime);
|
|
||||||
createEmail: (remoteMetadata at: 'creator');
|
|
||||||
editEmail: (remoteMetadata at: 'modifier'). "^ { snippets . page }" "Rebulding partial subtrees"
|
|
||||||
snippets
|
|
||||||
do: [ :currentSnippet |
|
|
||||||
| parentSnippet |
|
|
||||||
parentSnippet := snippets
|
|
||||||
detect: [ :item | item uid asString = currentSnippet parent ]
|
|
||||||
ifNone: [ parentSnippet := 'unrooted' ].
|
|
||||||
currentSnippet parent: parentSnippet.
|
|
||||||
parentSnippet class = ByteString
|
|
||||||
ifFalse: [ parentSnippet children addChild: currentSnippet ] ]. "Adding unrooted subtrees to the page"
|
|
||||||
"^ { unrooted . newPage }."
|
|
||||||
snippets
|
|
||||||
select: [ :each | each parent = 'unrooted' ]
|
|
||||||
thenDo: [ :unrooted | newPage addSnippet: unrooted ].
|
|
||||||
^ newPage
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #'*MiniDocs' }
|
|
||||||
LeDatabase >> sanitizeMarkdeepSnippets: divSnippets withMetadata: remoteMetadata [
|
|
||||||
^ divSnippets collectWithIndex: [:markdeepDiv :i | | snippetData creationTime modificationTime timestampWarning |
|
|
||||||
snippetData := markdeepDiv asSnippetDictionary.
|
|
||||||
creationTime := snippetData at: 'created'.
|
|
||||||
modificationTime := snippetData at: 'modified'.
|
|
||||||
timestampWarning := [:timestamp |
|
|
||||||
'Modified timestamps: ', timestamp ,' date and time was replaced instead of nil value. See "origin" metadata for more historical traceability information.'
|
|
||||||
].
|
|
||||||
(creationTime = 'nil' and: [ modificationTime ~= 'nil' ])
|
|
||||||
ifTrue: [
|
|
||||||
snippetData redefineTimestampsBefore: modificationTime.
|
|
||||||
snippetData addErrata: (timestampWarning value: 'creation').
|
|
||||||
snippetData at: 'origin' put: (remoteMetadata at: 'origin').
|
|
||||||
].
|
|
||||||
(creationTime = 'nil' and: [ modificationTime = 'nil' ])
|
|
||||||
ifTrue: [ | timeDiff |
|
|
||||||
timeDiff := divSnippets size - i. "Suggesting that last snippets were modified after the first ones."
|
|
||||||
modificationTime := (remoteMetadata at: 'created') asDateAndTime - timeDiff seconds.
|
|
||||||
snippetData redefineTimestampsBefore: modificationTime.
|
|
||||||
snippetData addErrata: (timestampWarning value: 'creation').
|
|
||||||
snippetData addErrata: (timestampWarning value: 'modification').
|
|
||||||
snippetData at: 'origin' put: (remoteMetadata at: 'origin').
|
|
||||||
].
|
|
||||||
snippetData.
|
|
||||||
]
|
|
||||||
]
|
|
||||||
|
@ -1,26 +0,0 @@
|
|||||||
Extension { #name : #LeDockerSnippet }
|
|
||||||
|
|
||||||
{ #category : #'*MiniDocs' }
|
|
||||||
LeDockerSnippet >> metadataUpdate [
|
|
||||||
| createEmailSanitized editEmailSanitized |
|
|
||||||
createEmailSanitized := self createEmail asString withoutXMLTagDelimiters.
|
|
||||||
editEmailSanitized := self editEmail asString withoutXMLTagDelimiters.
|
|
||||||
^ OrderedDictionary new
|
|
||||||
at: 'id' put: self uidString;
|
|
||||||
at: 'parent' put: self parent uuid;
|
|
||||||
at: 'created' put: self createTime asString;
|
|
||||||
at: 'modified' put: self latestEditTime asString;
|
|
||||||
at: 'creator' put: createEmailSanitized;
|
|
||||||
at: 'modifier' put: editEmailSanitized;
|
|
||||||
yourself
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #'*MiniDocs' }
|
|
||||||
LeDockerSnippet >> sanitizeMetadata [
|
|
||||||
self metadata keysAndValuesDo: [:k :v |
|
|
||||||
(v includesAny: #($< $>))
|
|
||||||
ifTrue: [
|
|
||||||
self metadata at: k put: (v copyWithoutAll: #($< $>))
|
|
||||||
]
|
|
||||||
]
|
|
||||||
]
|
|
@ -5,28 +5,3 @@ LeExampleSnippet >> asMarkdeep [
|
|||||||
|
|
||||||
^ (WriteStream on: '') contents
|
^ (WriteStream on: '') contents
|
||||||
]
|
]
|
||||||
|
|
||||||
{ #category : #'*MiniDocs' }
|
|
||||||
LeExampleSnippet >> metadataUpdate [
|
|
||||||
| createEmailSanitized editEmailSanitized |
|
|
||||||
createEmailSanitized := self createEmail asString withoutXMLTagDelimiters.
|
|
||||||
editEmailSanitized := self editEmail asString withoutXMLTagDelimiters.
|
|
||||||
^ OrderedDictionary new
|
|
||||||
at: 'id' put: self uidString;
|
|
||||||
at: 'parent' put: self parent uuid;
|
|
||||||
at: 'created' put: self createTime asString;
|
|
||||||
at: 'modified' put: self latestEditTime asString;
|
|
||||||
at: 'creator' put: createEmailSanitized;
|
|
||||||
at: 'modifier' put: editEmailSanitized;
|
|
||||||
yourself
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #'*MiniDocs' }
|
|
||||||
LeExampleSnippet >> sanitizeMetadata [
|
|
||||||
self metadata keysAndValuesDo: [:k :v |
|
|
||||||
(v includesAny: #($< $>))
|
|
||||||
ifTrue: [
|
|
||||||
self metadata at: k put: (v copyWithoutAll: #($< $>))
|
|
||||||
]
|
|
||||||
]
|
|
||||||
]
|
|
||||||
|
@ -1,26 +0,0 @@
|
|||||||
Extension { #name : #LeGitHubSnippet }
|
|
||||||
|
|
||||||
{ #category : #'*MiniDocs' }
|
|
||||||
LeGitHubSnippet >> metadataUpdate [
|
|
||||||
| createEmailSanitized editEmailSanitized |
|
|
||||||
createEmailSanitized := self createEmail asString withoutXMLTagDelimiters.
|
|
||||||
editEmailSanitized := self editEmail asString withoutXMLTagDelimiters.
|
|
||||||
^ OrderedDictionary new
|
|
||||||
at: 'id' put: self uidString;
|
|
||||||
at: 'parent' put: self parent uuid;
|
|
||||||
at: 'created' put: self createTime asString;
|
|
||||||
at: 'modified' put: self latestEditTime asString;
|
|
||||||
at: 'creator' put: createEmailSanitized;
|
|
||||||
at: 'modifier' put: editEmailSanitized;
|
|
||||||
yourself
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #'*MiniDocs' }
|
|
||||||
LeGitHubSnippet >> sanitizeMetadata [
|
|
||||||
self metadata keysAndValuesDo: [:k :v |
|
|
||||||
(v includesAny: #($< $>))
|
|
||||||
ifTrue: [
|
|
||||||
self metadata at: k put: (v copyWithoutAll: #($< $>))
|
|
||||||
]
|
|
||||||
]
|
|
||||||
]
|
|
@ -1,8 +0,0 @@
|
|||||||
Extension { #name : #LeHeaderNode }
|
|
||||||
|
|
||||||
{ #category : #'*MiniDocs' }
|
|
||||||
LeHeaderNode >> headerFullName [
|
|
||||||
^ self topParent completeSource
|
|
||||||
copyFrom: self startPosition
|
|
||||||
to: self stopPosition
|
|
||||||
]
|
|
@ -1,56 +0,0 @@
|
|||||||
Extension { #name : #LeHomeDatabaseHeaderElement }
|
|
||||||
|
|
||||||
{ #category : #'*MiniDocs' }
|
|
||||||
LeHomeDatabaseHeaderElement >> importMinidocsButtonElement [
|
|
||||||
^ self userData at: 'importMinidocsButtonElement' ifAbsentPut: [ self newImportMiniDocsButton]
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #'*MiniDocs' }
|
|
||||||
LeHomeDatabaseHeaderElement >> initialize [
|
|
||||||
super initialize.
|
|
||||||
self initializeEditableTitleElement.
|
|
||||||
self initializeButtons.
|
|
||||||
|
|
||||||
self addChild: self toolbarElement as: #toolbar.
|
|
||||||
self toolbarElement
|
|
||||||
addItem: self editableTitleElement;
|
|
||||||
addItem: self newAddNewPageButton;
|
|
||||||
addItem: self removeButtonElement;
|
|
||||||
addItem: self importButtonElement;
|
|
||||||
addItem: self exportButtonElement;
|
|
||||||
addItem: self importMinidocsButtonElement.
|
|
||||||
|
|
||||||
self addAptitude: (BrLayoutResizerAptitude new
|
|
||||||
hInherit;
|
|
||||||
vAnyToFitContent;
|
|
||||||
hInherit: self toolbarElement;
|
|
||||||
vAnyToFitContent: self toolbarElement).
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #'*MiniDocs' }
|
|
||||||
LeHomeDatabaseHeaderElement >> initializeButtons [
|
|
||||||
self initializeRemoveButton.
|
|
||||||
self initializeImportButton.
|
|
||||||
self initializeExportButton.
|
|
||||||
self initializeMiniDocsImportButton.
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #'*MiniDocs' }
|
|
||||||
LeHomeDatabaseHeaderElement >> initializeMiniDocsImportButton [
|
|
||||||
self userData at: 'importMinidocsButtonElement' put: self newImportMiniDocsButton.
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #'*MiniDocs' }
|
|
||||||
LeHomeDatabaseHeaderElement >> newImportMiniDocsButton [
|
|
||||||
^ LeMiniDocsImport new
|
|
||||||
tooltip: 'Import document from link';
|
|
||||||
contentExtent: 200 @ 30
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #'*MiniDocs' }
|
|
||||||
LeHomeDatabaseHeaderElement >> updateToolbarButtons [
|
|
||||||
self updateRemoveButtonElement.
|
|
||||||
self exportButtonElement database: self database.
|
|
||||||
self importButtonElement database: self database.
|
|
||||||
self importMinidocsButtonElement database: self database.
|
|
||||||
]
|
|
@ -1,26 +0,0 @@
|
|||||||
Extension { #name : #LeJenkinsSnippet }
|
|
||||||
|
|
||||||
{ #category : #'*MiniDocs' }
|
|
||||||
LeJenkinsSnippet >> metadataUpdate [
|
|
||||||
| createEmailSanitized editEmailSanitized |
|
|
||||||
createEmailSanitized := self createEmail asString withoutXMLTagDelimiters.
|
|
||||||
editEmailSanitized := self editEmail asString withoutXMLTagDelimiters.
|
|
||||||
^ OrderedDictionary new
|
|
||||||
at: 'id' put: self uidString;
|
|
||||||
at: 'parent' put: self parent uuid;
|
|
||||||
at: 'created' put: self createTime asString;
|
|
||||||
at: 'modified' put: self latestEditTime asString;
|
|
||||||
at: 'creator' put: createEmailSanitized;
|
|
||||||
at: 'modifier' put: editEmailSanitized;
|
|
||||||
yourself
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #'*MiniDocs' }
|
|
||||||
LeJenkinsSnippet >> sanitizeMetadata [
|
|
||||||
self metadata keysAndValuesDo: [:k :v |
|
|
||||||
(v includesAny: #($< $>))
|
|
||||||
ifTrue: [
|
|
||||||
self metadata at: k put: (v copyWithoutAll: #($< $>))
|
|
||||||
]
|
|
||||||
]
|
|
||||||
]
|
|
@ -1,89 +0,0 @@
|
|||||||
Class {
|
|
||||||
#name : #LeMiniDocsImport,
|
|
||||||
#superclass : #BrButton,
|
|
||||||
#instVars : [
|
|
||||||
'contentExtent',
|
|
||||||
'database'
|
|
||||||
],
|
|
||||||
#category : #'MiniDocs-UI'
|
|
||||||
}
|
|
||||||
|
|
||||||
{ #category : #accessing }
|
|
||||||
LeMiniDocsImport >> contentExtent [
|
|
||||||
^ contentExtent
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #accessing }
|
|
||||||
LeMiniDocsImport >> contentExtent: aPoint [
|
|
||||||
self
|
|
||||||
assert: [ aPoint isNotNil ]
|
|
||||||
description: [ 'Extent must be non-nil' ].
|
|
||||||
contentExtent := aPoint
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #accessing }
|
|
||||||
LeMiniDocsImport >> createDropdownExpandedHandleButton [
|
|
||||||
^ BrButton new
|
|
||||||
icon: BrGlamorousVectorIcons downwards;
|
|
||||||
label: self tooltip;
|
|
||||||
aptitude: BrGlamorousButtonWithIconAndLabelAptitude
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #accessing }
|
|
||||||
LeMiniDocsImport >> createURLeditable [
|
|
||||||
| base editable |
|
|
||||||
base := BlElement new
|
|
||||||
background: (Color white);
|
|
||||||
size: 200 @ 30;
|
|
||||||
margin: (BlInsets all: 10);
|
|
||||||
yourself.
|
|
||||||
editable := BrEditableLabel new
|
|
||||||
aptitude: BrGlamorousEditableLabelAptitude new glamorousRegularFontAndSize;
|
|
||||||
text: 'Document link';
|
|
||||||
switchToEditor.
|
|
||||||
editable when: BrEditorAcceptWish do: [ :aWish |
|
|
||||||
self importDocumentFrom: aWish text asString.
|
|
||||||
].
|
|
||||||
base addChild: editable.
|
|
||||||
^ base
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #accessing }
|
|
||||||
LeMiniDocsImport >> database [
|
|
||||||
^ database
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #accessing }
|
|
||||||
LeMiniDocsImport >> database: aLeDatabase [
|
|
||||||
database := aLeDatabase
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #accessing }
|
|
||||||
LeMiniDocsImport >> importDocumentFrom: aURL [
|
|
||||||
^ self database importDocumentFrom: aURL.
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #accessing }
|
|
||||||
LeMiniDocsImport >> initialize [
|
|
||||||
super initialize.
|
|
||||||
|
|
||||||
self
|
|
||||||
icon: BrGlamorousVectorIcons downwards;
|
|
||||||
label: 'Add MiniDocs';
|
|
||||||
aptitude: BrGlamorousButtonWithIconAndLabelAptitude.
|
|
||||||
self addAptitude: (BrGlamorousWithDropdownAptitude
|
|
||||||
handle: [ self createDropdownExpandedHandleButton ]
|
|
||||||
content: [ self createURLeditable ]).
|
|
||||||
|
|
||||||
self aptitude - BrGlamorousButtonExteriorAptitude.
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #accessing }
|
|
||||||
LeMiniDocsImport >> tooltip [
|
|
||||||
^ self label
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #accessing }
|
|
||||||
LeMiniDocsImport >> tooltip: aString [
|
|
||||||
self label: aString
|
|
||||||
]
|
|
@ -1,26 +0,0 @@
|
|||||||
Extension { #name : #LeMockedSnippet }
|
|
||||||
|
|
||||||
{ #category : #'*MiniDocs' }
|
|
||||||
LeMockedSnippet >> metadataUpdate [
|
|
||||||
| createEmailSanitized editEmailSanitized |
|
|
||||||
createEmailSanitized := self createEmail asString withoutXMLTagDelimiters.
|
|
||||||
editEmailSanitized := self editEmail asString withoutXMLTagDelimiters.
|
|
||||||
^ OrderedDictionary new
|
|
||||||
at: 'id' put: self uidString;
|
|
||||||
at: 'parent' put: self parent uuid;
|
|
||||||
at: 'created' put: self createTime asString;
|
|
||||||
at: 'modified' put: self latestEditTime asString;
|
|
||||||
at: 'creator' put: createEmailSanitized;
|
|
||||||
at: 'modifier' put: editEmailSanitized;
|
|
||||||
yourself
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #'*MiniDocs' }
|
|
||||||
LeMockedSnippet >> sanitizeMetadata [
|
|
||||||
self metadata keysAndValuesDo: [:k :v |
|
|
||||||
(v includesAny: #($< $>))
|
|
||||||
ifTrue: [
|
|
||||||
self metadata at: k put: (v copyWithoutAll: #($< $>))
|
|
||||||
]
|
|
||||||
]
|
|
||||||
]
|
|
@ -3,7 +3,7 @@ Extension { #name : #LePage }
|
|||||||
{ #category : #'*MiniDocs' }
|
{ #category : #'*MiniDocs' }
|
||||||
LePage >> asHtmlFile [
|
LePage >> asHtmlFile [
|
||||||
|
|
||||||
self asMarkdownFileWithMetadataWrappers.
|
self asMarkdownFile.
|
||||||
self defaultPandocTemplate exists
|
self defaultPandocTemplate exists
|
||||||
ifFalse: [ MarkupFile installTemplate: 'https://mutabit.com/repos.fossil/mutabit/doc/trunk/plantillas/Pandoc/clean-menu-mod.html' into: self defaultPandocTemplate parent ].
|
ifFalse: [ MarkupFile installTemplate: 'https://mutabit.com/repos.fossil/mutabit/doc/trunk/plantillas/Pandoc/clean-menu-mod.html' into: self defaultPandocTemplate parent ].
|
||||||
|
|
||||||
@ -21,23 +21,29 @@ LePage >> asHtmlFile [
|
|||||||
LePage >> asMarkdeep [
|
LePage >> asMarkdeep [
|
||||||
| bodyStream markdeep |
|
| bodyStream markdeep |
|
||||||
bodyStream := '' writeStream.
|
bodyStream := '' writeStream.
|
||||||
bodyStream nextPutAll: self notebookMetadataSnippet asMarkdeep.
|
self preorderTraversal do: [:snippet |
|
||||||
self preorderTraversal
|
bodyStream nextPutAll: snippet asMarkdeep
|
||||||
do: [ :snippet | bodyStream nextPutAll: snippet asMarkdeep ].
|
].
|
||||||
markdeep := Markdeep new
|
markdeep := Markdeep new
|
||||||
title: self title;
|
title: self title;
|
||||||
body: bodyStream contents;
|
body: bodyStream contents;
|
||||||
metadata: self metadata;
|
navTop: self navTop.
|
||||||
file: self storage / self markdeepFileName;
|
self metadata keysAndValuesDo: [:k :v |
|
||||||
navTop: self navTop.
|
k = 'lang'
|
||||||
self metadata
|
ifTrue: [
|
||||||
at: 'authors'
|
markdeep head
|
||||||
ifPresent: [ :author | markdeep metadata at: 'authors' put: author ].
|
add: '<meta lang="', v,'">';
|
||||||
self metadata
|
yourself.
|
||||||
at: 'version'
|
]
|
||||||
ifPresent: [ :version | markdeep metadata at: 'version' put: version ].
|
ifFalse: [
|
||||||
markdeep head: nil.
|
markdeep head
|
||||||
^ markdeep
|
add: '<meta name="', k, '" content="', v,'">';
|
||||||
|
yourself.
|
||||||
|
]
|
||||||
|
].
|
||||||
|
self metadata at: 'authors' ifPresent: [:author | markdeep metadata at: 'authors' put: author ].
|
||||||
|
self metadata at: 'version' ifPresent: [:version | markdeep metadata at: 'version' put: version ].
|
||||||
|
^ markdeep.
|
||||||
]
|
]
|
||||||
|
|
||||||
{ #category : #'*MiniDocs' }
|
{ #category : #'*MiniDocs' }
|
||||||
@ -48,49 +54,27 @@ LePage >> asMarkdeepFile [
|
|||||||
|
|
||||||
{ #category : #'*MiniDocs' }
|
{ #category : #'*MiniDocs' }
|
||||||
LePage >> asMarkdown [
|
LePage >> asMarkdown [
|
||||||
"PENDING: to debug the output."
|
|
||||||
| bodyStream markdown |
|
| bodyStream markdown |
|
||||||
bodyStream := '' writeStream.
|
bodyStream := '' writeStream.
|
||||||
bodyStream
|
bodyStream
|
||||||
nextPutAll: '# ', self title; cr; cr.
|
nextPutAll: '---';
|
||||||
|
nextPutAll: String lf.
|
||||||
|
self metadata keysAndValuesDo: [ :k :v |
|
||||||
|
bodyStream
|
||||||
|
nextPutAll: k , ': "' , v, '"';
|
||||||
|
nextPutAll: String lf ].
|
||||||
|
bodyStream nextPutAll: '---' , String lf , String lf.
|
||||||
self preorderTraversal
|
self preorderTraversal
|
||||||
do: [ :snippet | bodyStream nextPutAll: snippet asMarkdown ].
|
do: [ :snippet | bodyStream nextPutAll: snippet asMarkdown ].
|
||||||
markdown := Markdown new
|
markdown := Markdown new contents: bodyStream contents.
|
||||||
contents: bodyStream contents promoteMarkdownHeaders;
|
|
||||||
metadata: (self metadata at: 'original' ifAbsentPut: Dictionary new).
|
|
||||||
^ markdown
|
^ markdown
|
||||||
]
|
]
|
||||||
|
|
||||||
{ #category : #'*MiniDocs' }
|
{ #category : #'*MiniDocs' }
|
||||||
LePage >> asMarkdownFileWithMetadataWrappers [
|
LePage >> asMarkdownFile [
|
||||||
| folder |
|
| folder |
|
||||||
folder := self storage.
|
folder := self storage.
|
||||||
^ MarkupFile exportAsFileOn: folder / self markdownFileName containing: self asMarkdownWithMetadataWrappers contents
|
^ MarkupFile exportAsFileOn: folder / self markdownFileName containing: self asMarkdown contents
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #'*MiniDocs' }
|
|
||||||
LePage >> asMarkdownWithMetadataWrappers [
|
|
||||||
| bodyStream markdown |
|
|
||||||
bodyStream := '' writeStream.
|
|
||||||
"bodyStream
|
|
||||||
nextPut: Character lf;
|
|
||||||
nextPutAll: '# ', self title; cr; cr."
|
|
||||||
self preorderTraversal
|
|
||||||
do: [ :snippet | bodyStream nextPutAll: snippet asMarkdownWithMetadataWrappers ].
|
|
||||||
markdown := Markdown new
|
|
||||||
contents: bodyStream contents promoteMarkdownHeaders;
|
|
||||||
title: self title;
|
|
||||||
metadata: self metadata.
|
|
||||||
^ markdown
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #'*MiniDocs' }
|
|
||||||
LePage >> config [
|
|
||||||
| configFile |
|
|
||||||
configFile := self storage / 'config.ston'.
|
|
||||||
configFile exists
|
|
||||||
ifTrue: [^ STON fromString: configFile contents ]
|
|
||||||
ifFalse: [ ^ nil ]
|
|
||||||
]
|
]
|
||||||
|
|
||||||
{ #category : #'*MiniDocs' }
|
{ #category : #'*MiniDocs' }
|
||||||
@ -101,52 +85,18 @@ LePage >> defaultPandocTemplate [
|
|||||||
|
|
||||||
{ #category : #'*MiniDocs' }
|
{ #category : #'*MiniDocs' }
|
||||||
LePage >> detectParentSnippetWithUid: uidString [
|
LePage >> detectParentSnippetWithUid: uidString [
|
||||||
uidString = self uid asString36 ifTrue: [ ^ self ].
|
"Answer a boolean indicating whether the supplied uid is present"
|
||||||
^ self preorderTraversal detect: [ :snippet | snippet uidString = uidString ]
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #'*MiniDocs' }
|
^ self preorderTraversal detect: [ :snippet | snippet uidString = uidString ] ifNone: [ ^ self ]
|
||||||
LePage >> exportMetadataToHead: markdeep [
|
|
||||||
self metadata
|
|
||||||
keysAndValuesDo: [ :k :v |
|
|
||||||
k = 'lang'
|
|
||||||
ifTrue: [ markdeep head
|
|
||||||
add: '<meta lang="' , v , '">';
|
|
||||||
yourself ]
|
|
||||||
ifFalse: [ markdeep head
|
|
||||||
add: '<meta name="' , k , '" content="' , v , '">';
|
|
||||||
yourself ] ]
|
|
||||||
]
|
]
|
||||||
|
|
||||||
{ #category : #'*MiniDocs' }
|
{ #category : #'*MiniDocs' }
|
||||||
LePage >> exportedFileName [
|
LePage >> exportedFileName [
|
||||||
| sanitized titleWords shortTitle |
|
| sanitized |
|
||||||
titleWords := self title splitOn: Character space.
|
sanitized := self title asDashedLowercase romanizeAccents copyWithoutAll: #($/ $:).
|
||||||
(titleWords size > 11)
|
|
||||||
ifTrue: [
|
|
||||||
titleWords := titleWords copyFrom: 1 to: 3.
|
|
||||||
shortTitle := titleWords joinUsing: Character space.
|
|
||||||
]
|
|
||||||
ifFalse: [shortTitle := self title].
|
|
||||||
sanitized := shortTitle asDashedLowercase romanizeAccents copyWithoutAll: #($/ $: $🢒 $,).
|
|
||||||
^ sanitized , '--' , (self uidString copyFrom: 1 to: 5)
|
^ sanitized , '--' , (self uidString copyFrom: 1 to: 5)
|
||||||
]
|
]
|
||||||
|
|
||||||
{ #category : #'*MiniDocs' }
|
|
||||||
LePage >> fromDictionary: aDictionary [
|
|
||||||
self
|
|
||||||
title: (aDictionary at: 'title');
|
|
||||||
basicUid: (UUID fromString36: (aDictionary at: 'id'));
|
|
||||||
createTime: (LeTime new
|
|
||||||
time: (aDictionary at: 'created') asDateAndTime);
|
|
||||||
editTime: (LeTime new
|
|
||||||
time: (aDictionary at: 'modified') asDateAndTime);
|
|
||||||
latestEditTime: (LeTime new
|
|
||||||
time: (aDictionary at: 'modified') asDateAndTime);
|
|
||||||
createEmail: (aDictionary at: 'creator');
|
|
||||||
editEmail: (aDictionary at: 'modifier').
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #'*MiniDocs' }
|
{ #category : #'*MiniDocs' }
|
||||||
LePage >> fromMarkdeepUrl: aString [
|
LePage >> fromMarkdeepUrl: aString [
|
||||||
| docTree pageMetadata |
|
| docTree pageMetadata |
|
||||||
@ -179,11 +129,8 @@ LePage >> latestEditTime: aLeTime [
|
|||||||
{ #category : #'*MiniDocs' }
|
{ #category : #'*MiniDocs' }
|
||||||
LePage >> localHostAddress [
|
LePage >> localHostAddress [
|
||||||
| localUrl route |
|
| localUrl route |
|
||||||
MiniDocsServer teapot server isRunning ifFalse: [ MiniDocsServer restart ].
|
MiniDocsServer teapot server isRunning ifFalse: [ MiniDocsServer start ].
|
||||||
route := self storage path segments joinUsing: '/'.
|
route := MiniDocsServer teapot staticRouter prefix joinUsing: '/'.
|
||||||
MiniDocsServer teapot
|
|
||||||
serveStatic: ('/', route, '/', self markdeepFileName)
|
|
||||||
from: self storage / self markdeepFileName.
|
|
||||||
localUrl := MiniDocsServer teapot server localUrl asString.
|
localUrl := MiniDocsServer teapot server localUrl asString.
|
||||||
^ localUrl, route, '/', self markdeepFileName
|
^ localUrl, route, '/', self markdeepFileName
|
||||||
]
|
]
|
||||||
@ -202,17 +149,17 @@ LePage >> markdownFileName [
|
|||||||
{ #category : #'*MiniDocs' }
|
{ #category : #'*MiniDocs' }
|
||||||
LePage >> metadata [
|
LePage >> metadata [
|
||||||
|
|
||||||
^ self metadataUpdate
|
^ self options at: 'metadata' ifAbsentPut: [ self metadataInit]
|
||||||
]
|
]
|
||||||
|
|
||||||
{ #category : #'*MiniDocs' }
|
{ #category : #'*MiniDocs' }
|
||||||
LePage >> metadataUpdate [
|
LePage >> metadataInit [
|
||||||
|
|
||||||
^ OrderedDictionary new
|
^ OrderedDictionary new
|
||||||
at: 'id' put: self uidString;
|
at: 'id' put: self uidString;
|
||||||
at: 'title' put: self contentAsString;
|
at: 'title' put: self contentAsString;
|
||||||
at: 'created' put: self createTime greaseString;
|
at: 'created' put: self createTime greaseString;
|
||||||
at: 'modified' put: self getLatestEditTime greaseString;
|
at: 'modified' put: self latestEditTime greaseString;
|
||||||
at: 'creator' put: self createEmail greaseString;
|
at: 'creator' put: self createEmail greaseString;
|
||||||
at: 'modifier' put: self editEmail greaseString;
|
at: 'modifier' put: self editEmail greaseString;
|
||||||
yourself
|
yourself
|
||||||
@ -227,30 +174,6 @@ LePage >> navTop [
|
|||||||
ifTrue: [ ^ topNavFile contents ]
|
ifTrue: [ ^ topNavFile contents ]
|
||||||
]
|
]
|
||||||
|
|
||||||
{ #category : #'*MiniDocs' }
|
|
||||||
LePage >> notebookMetadataSnippet [
|
|
||||||
| response |
|
|
||||||
response := LeTextSnippet new fromString: '<!-- See this snippet source code for this notebook''s metadata -->'.
|
|
||||||
response parent: self.
|
|
||||||
self optionAt: 'HedgeDoc' ifAbsent: [ ^ response ].
|
|
||||||
(response extra)
|
|
||||||
at: 'HedgeDoc' put: (self optionAt: 'HedgeDoc').
|
|
||||||
^ response
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #'*MiniDocs' }
|
|
||||||
LePage >> olderChild [
|
|
||||||
"I provide the last edited child node.
|
|
||||||
I'm useful to recalculate the age of a notebook."
|
|
||||||
| response|
|
|
||||||
response := self preorderTraversal first.
|
|
||||||
self preorderTraversal do: [:current |
|
|
||||||
current editTime >= response editTime
|
|
||||||
ifTrue: [ response := current ]
|
|
||||||
].
|
|
||||||
^ response
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #'*MiniDocs' }
|
{ #category : #'*MiniDocs' }
|
||||||
LePage >> options [
|
LePage >> options [
|
||||||
^ options
|
^ options
|
||||||
@ -268,11 +191,6 @@ LePage >> removeSnippetsMetadata [
|
|||||||
ifTrue: [ snippet options removeKey: 'metadata' ] ]
|
ifTrue: [ snippet options removeKey: 'metadata' ] ]
|
||||||
]
|
]
|
||||||
|
|
||||||
{ #category : #'*MiniDocs' }
|
|
||||||
LePage >> sanitizeMetadata [
|
|
||||||
self allChildrenDepthFirst do: [:snippet | snippet sanitizeMetadata ]
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #'*MiniDocs' }
|
{ #category : #'*MiniDocs' }
|
||||||
LePage >> sharedVariablesBindings [
|
LePage >> sharedVariablesBindings [
|
||||||
| codeSnippets shared |
|
| codeSnippets shared |
|
||||||
@ -297,25 +215,6 @@ LePage >> sharedVariablesBindings [
|
|||||||
^ shared asDictionary
|
^ shared asDictionary
|
||||||
]
|
]
|
||||||
|
|
||||||
{ #category : #'*MiniDocs' }
|
|
||||||
LePage >> splitAdmonitionSnippets [
|
|
||||||
"I'm used to clean after importing from HedgeDoc to ensure that a snippet contains only admonitions and extra content is put in a new cell."
|
|
||||||
| admonitionSnippets |
|
|
||||||
admonitionSnippets := self children select: [:node | node string startsWithMarkdownAdmonition ].
|
|
||||||
admonitionSnippets ifEmpty: [ ^ self ].
|
|
||||||
admonitionSnippets do: [:node | | nodeContent |
|
|
||||||
node ifNotNil: [
|
|
||||||
nodeContent := node string.
|
|
||||||
nodeContent startsWithMarkdownAdmonition
|
|
||||||
ifTrue: [ | snippetCommand |
|
|
||||||
snippetCommand := node splitSnippetCommandAtPosition: nodeContent admonitionEndingPosition.
|
|
||||||
snippetCommand execute.
|
|
||||||
node tagWith: (nodeContent lines first trimBoth withoutPrefix: ':::')
|
|
||||||
]
|
|
||||||
]
|
|
||||||
]
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #'*MiniDocs' }
|
{ #category : #'*MiniDocs' }
|
||||||
LePage >> storage [
|
LePage >> storage [
|
||||||
| current |
|
| current |
|
||||||
@ -325,15 +224,6 @@ LePage >> storage [
|
|||||||
^ self optionAt: 'storage'
|
^ self optionAt: 'storage'
|
||||||
]
|
]
|
||||||
|
|
||||||
{ #category : #'*MiniDocs' }
|
|
||||||
LePage >> uiAddCopyButtonFor: anAction [
|
|
||||||
<lePageAction>
|
|
||||||
^ anAction button
|
|
||||||
tooltip: 'Export Page';
|
|
||||||
icon: BrGlamorousVectorIcons changes;
|
|
||||||
action: [:aButton | aButton phlow spawnObject: (self page database addPageCopy: self page) ]
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #'*MiniDocs' }
|
{ #category : #'*MiniDocs' }
|
||||||
LePage >> uiDefineFolderFor: anAction [
|
LePage >> uiDefineFolderFor: anAction [
|
||||||
<lePageAction>
|
<lePageAction>
|
||||||
@ -369,16 +259,3 @@ LePage >> uiRefreshWebPreviewButtonFor: anAction [
|
|||||||
"TODO: If Chrome/Chromium are not installed, I should execute:"
|
"TODO: If Chrome/Chromium are not installed, I should execute:"
|
||||||
"WebBrowser openOn: self page localHostAddress" ]
|
"WebBrowser openOn: self page localHostAddress" ]
|
||||||
]
|
]
|
||||||
|
|
||||||
{ #category : #'*MiniDocs' }
|
|
||||||
LePage >> youngerChild [
|
|
||||||
"I provide the first create child node.
|
|
||||||
I'm useful to recalculate the age of a notebook."
|
|
||||||
| response|
|
|
||||||
response := self preorderTraversal first.
|
|
||||||
self preorderTraversal do: [:current |
|
|
||||||
current createTime <= response createTime
|
|
||||||
ifTrue: [ response := current ]
|
|
||||||
].
|
|
||||||
^ response
|
|
||||||
]
|
|
||||||
|
@ -1,26 +0,0 @@
|
|||||||
Extension { #name : #LePharoRewriteSnippet }
|
|
||||||
|
|
||||||
{ #category : #'*MiniDocs' }
|
|
||||||
LePharoRewriteSnippet >> metadataUpdate [
|
|
||||||
| createEmailSanitized editEmailSanitized |
|
|
||||||
createEmailSanitized := self createEmail asString withoutXMLTagDelimiters.
|
|
||||||
editEmailSanitized := self editEmail asString withoutXMLTagDelimiters.
|
|
||||||
^ OrderedDictionary new
|
|
||||||
at: 'id' put: self uidString;
|
|
||||||
at: 'parent' put: self parent uuid;
|
|
||||||
at: 'created' put: self createTime asString;
|
|
||||||
at: 'modified' put: self latestEditTime asString;
|
|
||||||
at: 'creator' put: createEmailSanitized;
|
|
||||||
at: 'modifier' put: editEmailSanitized;
|
|
||||||
yourself
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #'*MiniDocs' }
|
|
||||||
LePharoRewriteSnippet >> sanitizeMetadata [
|
|
||||||
self metadata keysAndValuesDo: [:k :v |
|
|
||||||
(v includesAny: #($< $>))
|
|
||||||
ifTrue: [
|
|
||||||
self metadata at: k put: (v copyWithoutAll: #($< $>))
|
|
||||||
]
|
|
||||||
]
|
|
||||||
]
|
|
@ -9,26 +9,21 @@ LePharoSnippet >> contentAsStringCustomized [
|
|||||||
]
|
]
|
||||||
|
|
||||||
{ #category : #'*MiniDocs' }
|
{ #category : #'*MiniDocs' }
|
||||||
LePharoSnippet >> fromDictionary: anOrderedDictionary [
|
LePharoSnippet >> contentFrom: markdeepDiv [
|
||||||
self
|
|
||||||
uid: (LeUID new uidString: (anOrderedDictionary at: 'id'));
|
|
||||||
parent: (anOrderedDictionary at: 'parent');
|
|
||||||
createTime: (LeTime new time: ((anOrderedDictionary at: 'created')asDateAndTime));
|
|
||||||
editTime: (LeTime new time: ((anOrderedDictionary at: 'modified') asDateAndTime));
|
|
||||||
editEmail: (anOrderedDictionary at: 'modifier');
|
|
||||||
createEmail: (anOrderedDictionary at: 'creator').
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #'*MiniDocs' }
|
| sanitizedStringText metadata joinedText |
|
||||||
LePharoSnippet >> fromMarkdeep: markdeepDiv [
|
metadata := STON fromString: (markdeepDiv attributes at: 'st-data').
|
||||||
|
sanitizedStringText := markdeepDiv contentString lines.
|
||||||
^ markdeepDiv asSnippetDictionary asLepiterSnippet
|
sanitizedStringText := sanitizedStringText copyFrom: 4 to: sanitizedStringText size -2.
|
||||||
]
|
joinedText := '' writeStream.
|
||||||
|
sanitizedStringText do: [ :line | joinedText nextPutAll: line; nextPut: Character lf ].
|
||||||
{ #category : #'*MiniDocs' }
|
self code: joinedText contents allButLast;
|
||||||
LePharoSnippet >> fromString: aString [
|
uid: (LeUID new uidString: (metadata at: 'id'));
|
||||||
|
parent: (metadata at: 'parent');
|
||||||
[ self coder forSource: aString ] onErrorDo: [ ]
|
createTime: (LeTime new time: ((metadata at: 'created')asDateAndTime));
|
||||||
|
editTime: (LeTime new time: ((metadata at: 'modified') asDateAndTime));
|
||||||
|
editEmail: (metadata at: 'modifier');
|
||||||
|
createEmail: (metadata at: 'creator')
|
||||||
]
|
]
|
||||||
|
|
||||||
{ #category : #'*MiniDocs' }
|
{ #category : #'*MiniDocs' }
|
||||||
|
@ -2,22 +2,11 @@ Extension { #name : #LePictureSnippet }
|
|||||||
|
|
||||||
{ #category : #'*MiniDocs' }
|
{ #category : #'*MiniDocs' }
|
||||||
LePictureSnippet >> asMarkdeep [
|
LePictureSnippet >> asMarkdeep [
|
||||||
| output curatedCaption captionLines |
|
| output |
|
||||||
captionLines := self caption lines.
|
|
||||||
(captionLines size <= 1)
|
|
||||||
ifTrue: [ curatedCaption := caption ]
|
|
||||||
ifFalse: [
|
|
||||||
curatedCaption := WriteStream on: ''.
|
|
||||||
curatedCaption nextPutAll: captionLines first.
|
|
||||||
captionLines allButFirstDo: [:line |
|
|
||||||
curatedCaption nextPutAll: ' ', line.
|
|
||||||
curatedCaption := curatedCaption contents.
|
|
||||||
]
|
|
||||||
].
|
|
||||||
output := WriteStream on: ''.
|
output := WriteStream on: ''.
|
||||||
output
|
output
|
||||||
nextPutAll: self metadataDiv;
|
nextPutAll: self metadataDiv;
|
||||||
nextPutAll: '![ ', curatedCaption ,' ](', self urlString, ')';
|
nextPutAll: '![ ', self caption ,' ](', self urlString, ')';
|
||||||
nextPut: Character lf;
|
nextPut: Character lf;
|
||||||
nextPutAll: '</div>';
|
nextPutAll: '</div>';
|
||||||
nextPut: Character lf;
|
nextPut: Character lf;
|
||||||
@ -25,60 +14,9 @@ LePictureSnippet >> asMarkdeep [
|
|||||||
^ output contents
|
^ output contents
|
||||||
]
|
]
|
||||||
|
|
||||||
{ #category : #'*MiniDocs' }
|
|
||||||
LePictureSnippet >> asMarkdownWithMetadataWrappers [
|
|
||||||
^ self asMarkdeep
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #'*MiniDocs' }
|
|
||||||
LePictureSnippet >> contentFrom: markdeepDiv [
|
|
||||||
| caption width |
|
|
||||||
caption := markdeepDiv contentString.
|
|
||||||
width := (markdeepDiv // 'img' @ 'width') stringValue.
|
|
||||||
self
|
|
||||||
optionAt: 'caption' put: caption;
|
|
||||||
optionAt: 'width' put: width.
|
|
||||||
self urlString: (markdeepDiv // 'img' @ 'src') stringValue.
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #'*MiniDocs' }
|
|
||||||
LePictureSnippet >> fromDictionary: anOrderedDictionary [
|
|
||||||
| sanitizedUrl|
|
|
||||||
sanitizedUrl := (anOrderedDictionary at: 'url').
|
|
||||||
sanitizedUrl := sanitizedUrl copyFrom: 5 to: sanitizedUrl size - 3.
|
|
||||||
self
|
|
||||||
uid: (LeUID new uidString: (anOrderedDictionary at: 'id'));
|
|
||||||
parent: (anOrderedDictionary at: 'parent');
|
|
||||||
createTime: (LeTime new time: ((anOrderedDictionary at: 'created')asDateAndTime));
|
|
||||||
editTime: (LeTime new time: ((anOrderedDictionary at: 'modified') asDateAndTime));
|
|
||||||
editEmail: (anOrderedDictionary at: 'modifier');
|
|
||||||
createEmail: (anOrderedDictionary at: 'creator');
|
|
||||||
urlString: sanitizedUrl;
|
|
||||||
caption: (anOrderedDictionary at: 'content') first
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #'*MiniDocs' }
|
|
||||||
LePictureSnippet >> fromMarkdeep: markdeepDiv [
|
|
||||||
^ markdeepDiv asSnippetDictionary asLepiterSnippet
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #'*MiniDocs' }
|
|
||||||
LePictureSnippet >> fromString: aStringArray [
|
|
||||||
"aStringArray should contain as first element the sanitized string and
|
|
||||||
as second the full original image Link string, which may contains links in the description."
|
|
||||||
| args urlTemp |
|
|
||||||
|
|
||||||
args := aStringArray second splitOn: ']('.
|
|
||||||
urlTemp := args last.
|
|
||||||
urlTemp := urlTemp copyFrom: 1 to: urlTemp size - 1.
|
|
||||||
self caption: aStringArray first.
|
|
||||||
self urlString: urlTemp.
|
|
||||||
^ self
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #'*MiniDocs' }
|
{ #category : #'*MiniDocs' }
|
||||||
LePictureSnippet >> metadata [
|
LePictureSnippet >> metadata [
|
||||||
^ self metadataInit
|
^ self optionAt: 'metadata' ifAbsentPut: [ self metadataInit ]
|
||||||
]
|
]
|
||||||
|
|
||||||
{ #category : #'*MiniDocs' }
|
{ #category : #'*MiniDocs' }
|
||||||
@ -88,31 +26,13 @@ LePictureSnippet >> metadataDiv [
|
|||||||
output
|
output
|
||||||
nextPutAll: '<div st-class="' , self class greaseString , '"';
|
nextPutAll: '<div st-class="' , self class greaseString , '"';
|
||||||
nextPut: Character lf;
|
nextPut: Character lf;
|
||||||
nextPutAll: ' st-data="' , (STON toStringPretty: self metadata) , '">';
|
nextPutAll: ' st-data="' , (STON toString: self metadata) , '">'.
|
||||||
nextPut: Character lf.
|
^ output.
|
||||||
^ output contents withInternetLineEndings.
|
|
||||||
|
|
||||||
]
|
]
|
||||||
|
|
||||||
{ #category : #'*MiniDocs' }
|
{ #category : #'*MiniDocs' }
|
||||||
LePictureSnippet >> metadataInit [
|
LePictureSnippet >> metadataInit [
|
||||||
| surrogate |
|
|
||||||
self parent
|
|
||||||
ifNil: [ surrogate := nil]
|
|
||||||
ifNotNil: [ surrogate := self parent uidString ].
|
|
||||||
^ OrderedDictionary new
|
|
||||||
at: 'id' put: self uidString;
|
|
||||||
at: 'parent' put: surrogate;
|
|
||||||
at: 'url' put: '<!--',self contentAsString, '-->';
|
|
||||||
at: 'created' put: self createTime asString;
|
|
||||||
at: 'modified' put: self latestEditTime asString;
|
|
||||||
at: 'creator' put: self createEmail asString withoutXMLTagDelimiters;
|
|
||||||
at: 'modifier' put: self editEmail asString withoutXMLTagDelimiters;
|
|
||||||
yourself
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #'*MiniDocs' }
|
|
||||||
LePictureSnippet >> metadataUpdate [
|
|
||||||
| surrogate |
|
| surrogate |
|
||||||
self parent
|
self parent
|
||||||
ifNil: [ surrogate := nil]
|
ifNil: [ surrogate := nil]
|
||||||
@ -122,17 +42,7 @@ LePictureSnippet >> metadataUpdate [
|
|||||||
at: 'parent' put: surrogate;
|
at: 'parent' put: surrogate;
|
||||||
at: 'created' put: self createTime asString;
|
at: 'created' put: self createTime asString;
|
||||||
at: 'modified' put: self latestEditTime asString;
|
at: 'modified' put: self latestEditTime asString;
|
||||||
at: 'creator' put: self createEmail asString withoutXMLTagDelimiters;
|
at: 'creator' put: self createEmail asString;
|
||||||
at: 'modifier' put: self editEmail asString withoutXMLTagDelimiters;
|
at: 'modifier' put: self editEmail asString;
|
||||||
yourself
|
yourself
|
||||||
]
|
]
|
||||||
|
|
||||||
{ #category : #'*MiniDocs' }
|
|
||||||
LePictureSnippet >> sanitizeMetadata [
|
|
||||||
self metadata keysAndValuesDo: [:k :v |
|
|
||||||
(v includesAny: #($< $>))
|
|
||||||
ifTrue: [
|
|
||||||
self metadata at: k put: (v copyWithoutAll: #($< $>))
|
|
||||||
]
|
|
||||||
]
|
|
||||||
]
|
|
||||||
|
@ -1,26 +0,0 @@
|
|||||||
Extension { #name : #LeSmaCCRewriteSnippet }
|
|
||||||
|
|
||||||
{ #category : #'*MiniDocs' }
|
|
||||||
LeSmaCCRewriteSnippet >> metadataUpdate [
|
|
||||||
| createEmailSanitized editEmailSanitized |
|
|
||||||
createEmailSanitized := self createEmail asString withoutXMLTagDelimiters.
|
|
||||||
editEmailSanitized := self editEmail asString withoutXMLTagDelimiters.
|
|
||||||
^ OrderedDictionary new
|
|
||||||
at: 'id' put: self uidString;
|
|
||||||
at: 'parent' put: self parent uuid;
|
|
||||||
at: 'created' put: self createTime asString;
|
|
||||||
at: 'modified' put: self latestEditTime asString;
|
|
||||||
at: 'creator' put: createEmailSanitized;
|
|
||||||
at: 'modifier' put: editEmailSanitized;
|
|
||||||
yourself
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #'*MiniDocs' }
|
|
||||||
LeSmaCCRewriteSnippet >> sanitizeMetadata [
|
|
||||||
self metadata keysAndValuesDo: [:k :v |
|
|
||||||
(v includesAny: #($< $>))
|
|
||||||
ifTrue: [
|
|
||||||
self metadata at: k put: (v copyWithoutAll: #($< $>))
|
|
||||||
]
|
|
||||||
]
|
|
||||||
]
|
|
@ -7,26 +7,10 @@ LeSnippet class >> fromMetaMarkdeep: div [
|
|||||||
metadata := STON fromString:(div xpath: '@st-data') stringValue.
|
metadata := STON fromString:(div xpath: '@st-data') stringValue.
|
||||||
snippet := className asClass new.
|
snippet := className asClass new.
|
||||||
snippet injectMetadataFrom: metadata.
|
snippet injectMetadataFrom: metadata.
|
||||||
snippet fromMarkdeep: div.
|
snippet contentFrom: div.
|
||||||
^ snippet.
|
^ snippet.
|
||||||
]
|
]
|
||||||
|
|
||||||
{ #category : #'*MiniDocs' }
|
|
||||||
LeSnippet >> metadata [
|
|
||||||
| createEmailSanitized editEmailSanitized |
|
|
||||||
createEmailSanitized := self createEmail asString withoutXMLTagDelimiters.
|
|
||||||
editEmailSanitized := self editEmail asString withoutXMLTagDelimiters.
|
|
||||||
self optionAt: 'metadata' ifAbsentPut: [ OrderedDictionary new ].
|
|
||||||
^ (self optionAt: 'metadata')
|
|
||||||
at: 'id' put: self uidString;
|
|
||||||
at: 'parent' put: self parent uid asString36;
|
|
||||||
at: 'created' put: self createTime asString;
|
|
||||||
at: 'modified' put: self latestEditTime asString;
|
|
||||||
at: 'creator' put: createEmailSanitized;
|
|
||||||
at: 'modifier' put: editEmailSanitized;
|
|
||||||
yourself
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #'*MiniDocs' }
|
{ #category : #'*MiniDocs' }
|
||||||
LeSnippet >> moveToPageTitled: pageName [
|
LeSnippet >> moveToPageTitled: pageName [
|
||||||
| db origin destination thisSnippet |
|
| db origin destination thisSnippet |
|
||||||
|
@ -1,25 +1,5 @@
|
|||||||
Extension { #name : #LeTextCoderSnippetElement }
|
Extension { #name : #LeTextCoderSnippetElement }
|
||||||
|
|
||||||
{ #category : #'*MiniDocs' }
|
|
||||||
LeTextCoderSnippetElement >> asLePage [
|
|
||||||
| currentSnippet newPage |
|
|
||||||
currentSnippet := self snippet.
|
|
||||||
newPage := LePage new.
|
|
||||||
newPage
|
|
||||||
title: (currentSnippet text asString trimLeft: [:char | char = $# ]) trim.
|
|
||||||
self page database
|
|
||||||
addPage: newPage.
|
|
||||||
currentSnippet allChildrenBreadthFirstDo: [:child |
|
|
||||||
child moveToPageTitled: newPage title.
|
|
||||||
].
|
|
||||||
^ newPage
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #'*MiniDocs' }
|
|
||||||
LeTextCoderSnippetElement >> asSnippetViewModel [
|
|
||||||
^ self snippetContent
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #'*MiniDocs' }
|
{ #category : #'*MiniDocs' }
|
||||||
LeTextCoderSnippetElement >> moveToPageTitled: pageName [
|
LeTextCoderSnippetElement >> moveToPageTitled: pageName [
|
||||||
| db origin destination |
|
| db origin destination |
|
||||||
|
@ -2,14 +2,9 @@ Extension { #name : #LeTextSnippet }
|
|||||||
|
|
||||||
{ #category : #'*MiniDocs' }
|
{ #category : #'*MiniDocs' }
|
||||||
LeTextSnippet >> asLePage [
|
LeTextSnippet >> asLePage [
|
||||||
| page title currentSnippet |
|
| page |
|
||||||
title := self contentAsString markdownHeaders associations first value.
|
|
||||||
title := (title trimBoth: [:char | char = $# ]) trimmed.
|
|
||||||
page := LePage new
|
page := LePage new
|
||||||
initializeTitle: title.
|
initializeTitle: self contentAsString.
|
||||||
currentSnippet := LeTextSnippet new
|
|
||||||
string: self contentAsString.
|
|
||||||
page addSnippet: currentSnippet.
|
|
||||||
self database addPage: page.
|
self database addPage: page.
|
||||||
self childrenDo: [:child |
|
self childrenDo: [:child |
|
||||||
child moveToPageTitled: page title
|
child moveToPageTitled: page title
|
||||||
@ -19,34 +14,39 @@ LeTextSnippet >> asLePage [
|
|||||||
]
|
]
|
||||||
|
|
||||||
{ #category : #'*MiniDocs' }
|
{ #category : #'*MiniDocs' }
|
||||||
LeTextSnippet >> fromDictionary: anOrderedDictionary [
|
LeTextSnippet >> contentFrom: markdeepDiv [
|
||||||
self
|
|
||||||
uid: (LeUID new uidString: (anOrderedDictionary at: 'id'));
|
|
||||||
parent: (anOrderedDictionary at: 'parent');
|
|
||||||
createTime: (LeTime new time: ((anOrderedDictionary at: 'created')asDateAndTime));
|
|
||||||
editTime: (LeTime new time: ((anOrderedDictionary at: 'modified') asDateAndTime));
|
|
||||||
editEmail: (anOrderedDictionary at: 'modifier');
|
|
||||||
createEmail: (anOrderedDictionary at: 'creator')
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #'*MiniDocs' }
|
| sanitizedStringText metadata |
|
||||||
LeTextSnippet >> fromMarkdeep: markdeepDiv [
|
metadata := STON fromString: (markdeepDiv attributes at: 'st-data').
|
||||||
|
sanitizedStringText := markdeepDiv contentString.
|
||||||
^ markdeepDiv asSnippetDictionary asLepiterSnippet
|
sanitizedStringText := sanitizedStringText allButFirst.
|
||||||
]
|
sanitizedStringText := sanitizedStringText allButLast.
|
||||||
|
self string: sanitizedStringText;
|
||||||
{ #category : #'*MiniDocs' }
|
uid: (LeUID new uidString: (metadata at: 'id'));
|
||||||
LeTextSnippet >> fromString: aString [
|
parent: (metadata at: 'parent');
|
||||||
|
createTime: (LeTime new time: ((metadata at: 'created')asDateAndTime));
|
||||||
self
|
editTime: (LeTime new time: ((metadata at: 'modified') asDateAndTime));
|
||||||
string: aString;
|
editEmail: (metadata at: 'modifier');
|
||||||
uid: LeUID new.
|
createEmail: (metadata at: 'creator')
|
||||||
]
|
]
|
||||||
|
|
||||||
{ #category : #'*MiniDocs' }
|
{ #category : #'*MiniDocs' }
|
||||||
LeTextSnippet >> metadata [
|
LeTextSnippet >> metadata [
|
||||||
|
|
||||||
^ self metadataUpdate
|
^ self optionAt: 'metadata' ifAbsentPut: [ self metadataInit ]
|
||||||
|
]
|
||||||
|
|
||||||
|
{ #category : #'*MiniDocs' }
|
||||||
|
LeTextSnippet >> metadataInit [
|
||||||
|
|
||||||
|
^ OrderedDictionary new
|
||||||
|
at: 'id' put: self uidString;
|
||||||
|
at: 'parent' put: self parentId;
|
||||||
|
at: 'created' put: self createTime asString;
|
||||||
|
at: 'modified' put: self latestEditTime asString;
|
||||||
|
at: 'creator' put: self createEmail asString;
|
||||||
|
at: 'modifier' put: self editEmail asString;
|
||||||
|
yourself
|
||||||
]
|
]
|
||||||
|
|
||||||
{ #category : #'*MiniDocs' }
|
{ #category : #'*MiniDocs' }
|
||||||
@ -57,23 +57,11 @@ LeTextSnippet >> options [
|
|||||||
{ #category : #'*MiniDocs' }
|
{ #category : #'*MiniDocs' }
|
||||||
LeTextSnippet >> parentId [
|
LeTextSnippet >> parentId [
|
||||||
self parent ifNil: [ ^ self ].
|
self parent ifNil: [ ^ self ].
|
||||||
(self parent isString) ifTrue: [^ self parent].
|
|
||||||
^ self parent uidString.
|
^ self parent uidString.
|
||||||
]
|
]
|
||||||
|
|
||||||
{ #category : #'*MiniDocs' }
|
{ #category : #'*MiniDocs' }
|
||||||
LeTextSnippet >> tagWith: aString [
|
LeTextSnippet >> taggedWith: aString [
|
||||||
self tags add: aString.
|
self metadata at: 'tags' ifPresent: [ (self metadata at: 'tags') add: aString; yourself ] ifAbsentPut: [ Set new ].
|
||||||
]
|
^ self metadata at: 'tags'
|
||||||
|
|
||||||
{ #category : #'*MiniDocs' }
|
|
||||||
LeTextSnippet >> withFollowingSnippets [
|
|
||||||
"I'm the same method implemented for PharoSnippets,
|
|
||||||
but present also here as a way to improve moving prose snippets from pages.
|
|
||||||
"
|
|
||||||
| snippets stop start |
|
|
||||||
snippets := self parent children asArray.
|
|
||||||
start := snippets indexOf: self.
|
|
||||||
stop := snippets size.
|
|
||||||
^ snippets copyFrom: start to: stop
|
|
||||||
]
|
]
|
||||||
|
@ -2,62 +2,45 @@ Extension { #name : #LeTextualSnippet }
|
|||||||
|
|
||||||
{ #category : #'*MiniDocs' }
|
{ #category : #'*MiniDocs' }
|
||||||
LeTextualSnippet >> asMarkdeep [
|
LeTextualSnippet >> asMarkdeep [
|
||||||
|
"Inspired by Alpine.js and Assembler CSS 'x-' properties, we are going to use
|
||||||
|
'st-' properties as a way to extend divs metadata regarding its contents."
|
||||||
|
|
||||||
| output |
|
| output |
|
||||||
output := WriteStream on: ''.
|
output := WriteStream on: ''.
|
||||||
output
|
output
|
||||||
nextPutAll: self metadataDiv;
|
nextPutAll: '<div st-class="' , self class greaseString , '"';
|
||||||
|
nextPut: Character lf;
|
||||||
|
nextPutAll: ' st-data="' , (STON toString: self metadata) , '">';
|
||||||
|
nextPut: Character lf;
|
||||||
nextPutAll: self markdeepCustomOpener;
|
nextPutAll: self markdeepCustomOpener;
|
||||||
nextPutAll: self contentAsStringAnnotated;
|
nextPutAll: self contentAsString;
|
||||||
nextPut: Character lf;
|
nextPut: Character lf;
|
||||||
nextPutAll: self markdeepCustomCloser;
|
nextPutAll: self markdeepCustomCloser;
|
||||||
nextPutAll: '</div>';
|
nextPutAll: '</div>';
|
||||||
nextPut: Character lf;
|
nextPut: Character lf;
|
||||||
nextPut: Character lf.
|
nextPut: Character lf.
|
||||||
^ output contents withInternetLineEndings
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #'*MiniDocs' }
|
|
||||||
LeTextualSnippet >> asMarkdown [
|
|
||||||
|
|
||||||
| output |
|
|
||||||
output := '' writeStream.
|
|
||||||
output
|
|
||||||
nextPutAll: self contentAsStringCustomized; lf.
|
|
||||||
^ output contents
|
^ output contents
|
||||||
]
|
]
|
||||||
|
|
||||||
{ #category : #'*MiniDocs' }
|
{ #category : #'*MiniDocs' }
|
||||||
LeTextualSnippet >> asMarkdownWithMetadataWrappers [
|
LeTextualSnippet >> asMarkdown [
|
||||||
"Inspired by Alpine.js and Assembler CSS 'x-' properties, we are going to use
|
"Inspired by Alpine.js and Assembler CSS 'x-' properties, we are going to use
|
||||||
'st-' properties as a way to extend divs metadata regarding its contents."
|
'st-' properties as a way to extend divs metadata regarding its contents."
|
||||||
| output |
|
| output |
|
||||||
output := '' writeStream.
|
output := '' writeStream.
|
||||||
output
|
output
|
||||||
nextPutAll: self metadataDiv;
|
nextPutAll: '<div st-class="', self class asString, '"'; lf;
|
||||||
|
nextPutAll: ' st-data="', (STON toString: self metadata), '">'; lf;
|
||||||
nextPutAll: self markdownCustomOpener;
|
nextPutAll: self markdownCustomOpener;
|
||||||
nextPutAll: self contentAsStringCustomized; lf;
|
nextPutAll: self contentAsStringCustomized; lf;
|
||||||
nextPutAll: self markdownCustomCloser;
|
nextPutAll: self markdownCustomCloser;
|
||||||
nextPutAll: '</div>'; lf; lf.
|
nextPutAll: '</div>'; lf; lf.
|
||||||
^ output contents withInternetLineEndings
|
^ output contents
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #'*MiniDocs' }
|
|
||||||
LeTextualSnippet >> contentAsStringAnnotated [
|
|
||||||
self ast ifNotNil: [ ^ self processSnippetAnnotations ].
|
|
||||||
^ self contentAsString
|
|
||||||
]
|
]
|
||||||
|
|
||||||
{ #category : #'*MiniDocs' }
|
{ #category : #'*MiniDocs' }
|
||||||
LeTextualSnippet >> contentAsStringCustomized [
|
LeTextualSnippet >> contentAsStringCustomized [
|
||||||
(self contentAsString beginsWith: '#')
|
^ self contentAsString
|
||||||
ifTrue: [ ^ '#', self contentAsString ]
|
|
||||||
ifFalse: [ ^ self contentAsString ]
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #'*MiniDocs' }
|
|
||||||
LeTextualSnippet >> extra [
|
|
||||||
^ self optionAt: 'extra' ifAbsentPut: [ Dictionary new ]
|
|
||||||
]
|
]
|
||||||
|
|
||||||
{ #category : #'*MiniDocs' }
|
{ #category : #'*MiniDocs' }
|
||||||
@ -83,84 +66,26 @@ LeTextualSnippet >> markdownCustomOpener [
|
|||||||
{ #category : #'*MiniDocs' }
|
{ #category : #'*MiniDocs' }
|
||||||
LeTextualSnippet >> metadata [
|
LeTextualSnippet >> metadata [
|
||||||
|
|
||||||
^ self metadataUpdate
|
^ self optionAt: 'metadata' ifAbsentPut: [ self metadataInit ]
|
||||||
]
|
]
|
||||||
|
|
||||||
{ #category : #'*MiniDocs' }
|
{ #category : #'*MiniDocs' }
|
||||||
LeTextualSnippet >> metadataDiv [
|
LeTextualSnippet >> metadataInit [
|
||||||
"Inspired by Alpine.js and Assembler CSS 'x-' properties, we are going to use
|
| surrogate |
|
||||||
'st-' properties as a way to extend divs metadata regarding its contents."
|
self parent
|
||||||
"PENDING: this is repeated in several snippets. Can be abstracted up in a common object of the class hierarchy?"
|
ifNil: [ surrogate := nil]
|
||||||
| output |
|
ifNotNil: [ surrogate := self parent uidString ].
|
||||||
output := WriteStream on: ''.
|
|
||||||
output
|
|
||||||
nextPutAll: '<div st-class="' , self class greaseString , '"';
|
|
||||||
nextPut: Character lf;
|
|
||||||
nextPutAll: ' st-data="' , (STON toStringPretty: self metadata) , '">';
|
|
||||||
nextPut: Character lf.
|
|
||||||
^ output contents withInternetLineEndings.
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #'*MiniDocs' }
|
|
||||||
LeTextualSnippet >> metadataUpdate [
|
|
||||||
| createEmailSanitized editEmailSanitized |
|
|
||||||
createEmailSanitized := self createEmail asString withoutXMLTagDelimiters.
|
|
||||||
editEmailSanitized := self editEmail asString withoutXMLTagDelimiters.
|
|
||||||
^ OrderedDictionary new
|
^ OrderedDictionary new
|
||||||
at: 'id' put: self uidString;
|
at: 'id' put: self uidString;
|
||||||
at: 'parent' put: (self parent ifNotNil: [self parent uidString ]);
|
at: 'parent' put: surrogate;
|
||||||
at: 'created' put: self createTime asString;
|
at: 'created' put: self createTime asString;
|
||||||
at: 'modified' put: self latestEditTime asString;
|
at: 'modified' put: self latestEditTime asString;
|
||||||
at: 'creator' put: createEmailSanitized;
|
at: 'creator' put: self createEmail asString;
|
||||||
at: 'modifier' put: editEmailSanitized;
|
at: 'modifier' put: self editEmail asString;
|
||||||
at: 'extra' put: self extra;
|
|
||||||
yourself
|
yourself
|
||||||
]
|
]
|
||||||
|
|
||||||
{ #category : #'*MiniDocs' }
|
|
||||||
LeTextualSnippet >> processSnippetAnnotations [
|
|
||||||
| exported substitutions annotations pageConfig |
|
|
||||||
annotations := self ast parts
|
|
||||||
select: [ :each | each className includesSubstring: 'AnnotationNode' ].
|
|
||||||
annotations ifEmpty: [ ^ self contentAsString ].
|
|
||||||
substitutions := OrderedDictionary new.
|
|
||||||
pageConfig := self page config.
|
|
||||||
annotations
|
|
||||||
do: [ :each |
|
|
||||||
| key type value color |
|
|
||||||
key := each source.
|
|
||||||
type := (key splitOn: ':') first copyWithoutAll: '{{'.
|
|
||||||
value := key copyFrom: type size + 4 to: key size - 2.
|
|
||||||
pageConfig
|
|
||||||
ifNil: [ color := 'default' ]
|
|
||||||
ifNotNil: [ | colors |
|
|
||||||
colors := pageConfig at: 'annotationColors' ifAbsent: [ nil ].
|
|
||||||
colors
|
|
||||||
ifNotNil: [ color := colors
|
|
||||||
at: type
|
|
||||||
ifAbsent: [ colors at: 'defaultColor' ifAbsentPut: [ 'default' ] ] ] ].
|
|
||||||
substitutions
|
|
||||||
at: key
|
|
||||||
put: '<span st-class="' , type , '" style="color:' , color , '">' , value , '</span>' ].
|
|
||||||
exported := self contentAsString.
|
|
||||||
substitutions
|
|
||||||
keysAndValuesDo: [ :k :v | exported := exported copyReplaceAll: k with: v ].
|
|
||||||
^ exported
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #'*MiniDocs' }
|
|
||||||
LeTextualSnippet >> sanitizeMetadata [
|
|
||||||
self options ifNil: [^ self ].
|
|
||||||
self options removeKey: 'metadata' ifAbsent: [^ self ].
|
|
||||||
self metadata keysAndValuesDo: [:k :v |
|
|
||||||
(v asString includesAny: #($< $>))
|
|
||||||
ifTrue: [
|
|
||||||
self metadata at: k put: (v asString copyWithoutXMLDelimiters)
|
|
||||||
]
|
|
||||||
]
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #'*MiniDocs' }
|
{ #category : #'*MiniDocs' }
|
||||||
LeTextualSnippet >> tags [
|
LeTextualSnippet >> tags [
|
||||||
^ self extra at: 'tags' ifAbsentPut: [ Set new ]
|
^ self metadata at: 'tags' ifAbsentPut: [ Set new ]
|
||||||
]
|
]
|
||||||
|
@ -1,21 +0,0 @@
|
|||||||
Extension { #name : #LeUnknownSnippet }
|
|
||||||
|
|
||||||
{ #category : #'*MiniDocs' }
|
|
||||||
LeUnknownSnippet >> metadataUpdate [
|
|
||||||
| surrogate |
|
|
||||||
self parent
|
|
||||||
ifNil: [ surrogate := nil]
|
|
||||||
ifNotNil: [
|
|
||||||
self parent isString
|
|
||||||
ifTrue: [ surrogate := self parent]
|
|
||||||
ifFalse: [ surrogate := self parent uidString ]
|
|
||||||
].
|
|
||||||
^ OrderedDictionary new
|
|
||||||
at: 'id' put: self uidString;
|
|
||||||
at: 'parent' put: surrogate;
|
|
||||||
at: 'created' put: self createTime asString;
|
|
||||||
at: 'modified' put: self latestEditTime asString;
|
|
||||||
at: 'creator' put: self createEmail asString;
|
|
||||||
at: 'modifier' put: self editEmail asString;
|
|
||||||
yourself
|
|
||||||
]
|
|
@ -1,26 +0,0 @@
|
|||||||
Extension { #name : #LeWardleyMapSnippet }
|
|
||||||
|
|
||||||
{ #category : #'*MiniDocs' }
|
|
||||||
LeWardleyMapSnippet >> metadataUpdate [
|
|
||||||
| createEmailSanitized editEmailSanitized |
|
|
||||||
createEmailSanitized := self createEmail asString withoutXMLTagDelimiters.
|
|
||||||
editEmailSanitized := self editEmail asString withoutXMLTagDelimiters.
|
|
||||||
^ OrderedDictionary new
|
|
||||||
at: 'id' put: self uidString;
|
|
||||||
at: 'parent' put: self parent uuid;
|
|
||||||
at: 'created' put: self createTime asString;
|
|
||||||
at: 'modified' put: self latestEditTime asString;
|
|
||||||
at: 'creator' put: createEmailSanitized;
|
|
||||||
at: 'modifier' put: editEmailSanitized;
|
|
||||||
yourself
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #'*MiniDocs' }
|
|
||||||
LeWardleyMapSnippet >> sanitizeMetadata [
|
|
||||||
self metadata keysAndValuesDo: [:k :v |
|
|
||||||
(v includesAny: #($< $>))
|
|
||||||
ifTrue: [
|
|
||||||
self metadata at: k put: (v copyWithoutAll: #($< $>))
|
|
||||||
]
|
|
||||||
]
|
|
||||||
]
|
|
@ -1,26 +0,0 @@
|
|||||||
Extension { #name : #LeWordSnippet }
|
|
||||||
|
|
||||||
{ #category : #'*MiniDocs' }
|
|
||||||
LeWordSnippet >> metadataUpdate [
|
|
||||||
| createEmailSanitized editEmailSanitized |
|
|
||||||
createEmailSanitized := self createEmail asString withoutXMLTagDelimiters.
|
|
||||||
editEmailSanitized := self editEmail asString withoutXMLTagDelimiters.
|
|
||||||
^ OrderedDictionary new
|
|
||||||
at: 'id' put: self uidString;
|
|
||||||
at: 'parent' put: self parent uuid;
|
|
||||||
at: 'created' put: self createTime asString;
|
|
||||||
at: 'modified' put: self latestEditTime asString;
|
|
||||||
at: 'creator' put: createEmailSanitized;
|
|
||||||
at: 'modifier' put: editEmailSanitized;
|
|
||||||
yourself
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #'*MiniDocs' }
|
|
||||||
LeWordSnippet >> sanitizeMetadata [
|
|
||||||
self metadata keysAndValuesDo: [:k :v |
|
|
||||||
(v includesAny: #($< $>))
|
|
||||||
ifTrue: [
|
|
||||||
self metadata at: k put: (v copyWithoutAll: #($< $>))
|
|
||||||
]
|
|
||||||
]
|
|
||||||
]
|
|
@ -16,7 +16,7 @@ LeYoutubeReferenceSnippet >> asMarkdeep [
|
|||||||
|
|
||||||
{ #category : #'*MiniDocs' }
|
{ #category : #'*MiniDocs' }
|
||||||
LeYoutubeReferenceSnippet >> metadata [
|
LeYoutubeReferenceSnippet >> metadata [
|
||||||
^ self optionAt: 'metadata' ifAbsentPut: [ self metadataUpdate ]
|
^ self optionAt: 'metadata' ifAbsentPut: [ self metadataInit ]
|
||||||
]
|
]
|
||||||
|
|
||||||
{ #category : #'*MiniDocs' }
|
{ #category : #'*MiniDocs' }
|
||||||
@ -26,12 +26,12 @@ LeYoutubeReferenceSnippet >> metadataDiv [
|
|||||||
output
|
output
|
||||||
nextPutAll: '<div st-class="' , self class greaseString , '"';
|
nextPutAll: '<div st-class="' , self class greaseString , '"';
|
||||||
nextPut: Character lf;
|
nextPut: Character lf;
|
||||||
nextPutAll: ' st-data="' , (STON toStringPretty: self metadata) , '">'.
|
nextPutAll: ' st-data="' , (STON toString: self metadata) , '">'.
|
||||||
^ output contents withInternetLineEndings.
|
^ output.
|
||||||
]
|
]
|
||||||
|
|
||||||
{ #category : #'*MiniDocs' }
|
{ #category : #'*MiniDocs' }
|
||||||
LeYoutubeReferenceSnippet >> metadataUpdate [
|
LeYoutubeReferenceSnippet >> metadataInit [
|
||||||
| surrogate |
|
| surrogate |
|
||||||
self parent
|
self parent
|
||||||
ifNil: [ surrogate := nil]
|
ifNil: [ surrogate := nil]
|
||||||
@ -45,13 +45,3 @@ LeYoutubeReferenceSnippet >> metadataUpdate [
|
|||||||
at: 'modifier' put: self editEmail asString;
|
at: 'modifier' put: self editEmail asString;
|
||||||
yourself
|
yourself
|
||||||
]
|
]
|
||||||
|
|
||||||
{ #category : #'*MiniDocs' }
|
|
||||||
LeYoutubeReferenceSnippet >> sanitizeMetadata [
|
|
||||||
self metadata keysAndValuesDo: [:k :v |
|
|
||||||
(v includesAny: #($< $>))
|
|
||||||
ifTrue: [
|
|
||||||
self metadata at: k put: (v copyWithoutAll: #($< $>))
|
|
||||||
]
|
|
||||||
]
|
|
||||||
]
|
|
||||||
|
@ -1,33 +0,0 @@
|
|||||||
Class {
|
|
||||||
#name : #Logseq,
|
|
||||||
#superclass : #Object,
|
|
||||||
#instVars : [
|
|
||||||
'folder'
|
|
||||||
],
|
|
||||||
#category : #'MiniDocs-Model'
|
|
||||||
}
|
|
||||||
|
|
||||||
{ #category : #accessing }
|
|
||||||
Logseq >> assets [
|
|
||||||
^ self folder / 'assets'
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #accessing }
|
|
||||||
Logseq >> folder [
|
|
||||||
^ folder
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #accessing }
|
|
||||||
Logseq >> folder: aFolder [
|
|
||||||
folder := aFolder
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #accessing }
|
|
||||||
Logseq >> journals [
|
|
||||||
self folder / 'journals'
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #accessing }
|
|
||||||
Logseq >> pages [
|
|
||||||
^self folder/ 'pages'
|
|
||||||
]
|
|
@ -5,6 +5,7 @@ Class {
|
|||||||
#name : #Markdeep,
|
#name : #Markdeep,
|
||||||
#superclass : #Markdown,
|
#superclass : #Markdown,
|
||||||
#instVars : [
|
#instVars : [
|
||||||
|
'title',
|
||||||
'comments',
|
'comments',
|
||||||
'tail',
|
'tail',
|
||||||
'language',
|
'language',
|
||||||
@ -29,25 +30,16 @@ Markdeep class >> fromPubPubTOC: orderedDictionary folder: folder index: ordina
|
|||||||
^ self new fromMarkdownFile: testFile.
|
^ self new fromMarkdownFile: testFile.
|
||||||
]
|
]
|
||||||
|
|
||||||
{ #category : #accessing }
|
|
||||||
Markdeep >> asMarkdownWithMetadataWrappers [
|
|
||||||
^ Markdown new
|
|
||||||
metadata: self metadata;
|
|
||||||
body: self body;
|
|
||||||
file: self markdownFile
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #'instance creation' }
|
{ #category : #'instance creation' }
|
||||||
Markdeep >> authors [
|
Markdeep >> authors [
|
||||||
self metadata at: 'authors' ifAbsentPut: [ Dictionary new ].
|
self metadata at: 'authors' ifPresent: [:k | ^ '**', k, '**' ].
|
||||||
"self metadata at: 'authors' ifNotEmpty: [:k | ^ '**', k, '**' ]
|
^ ''.
|
||||||
" ^ ''.
|
|
||||||
]
|
]
|
||||||
|
|
||||||
{ #category : #'instance creation' }
|
{ #category : #'instance creation' }
|
||||||
Markdeep >> authorsString [
|
Markdeep >> authorsString [
|
||||||
self authors
|
self authors
|
||||||
ifEmpty: [ ^ '' ] ifNotEmpty: [ ^ ' ', self authors ]
|
ifNil: [ ^ '' ] ifNotNil: [ ^ ' ', self authors ]
|
||||||
]
|
]
|
||||||
|
|
||||||
{ #category : #accessing }
|
{ #category : #accessing }
|
||||||
@ -65,15 +57,10 @@ Markdeep >> bodyReplaceAll: original with: replacement [
|
|||||||
self body: (self body copyReplaceAll: original with: replacement)
|
self body: (self body copyReplaceAll: original with: replacement)
|
||||||
]
|
]
|
||||||
|
|
||||||
{ #category : #accessing }
|
|
||||||
Markdeep >> cleanMetadata [
|
|
||||||
metadata := nil
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #accessing }
|
{ #category : #accessing }
|
||||||
Markdeep >> commentPubPubDelimiters [
|
Markdeep >> commentPubPubDelimiters [
|
||||||
| commented openners |
|
| commented openners |
|
||||||
openners := #('::: {.pub-body-component}' '::: pub-body-component' '::: {.editor .Prosemirror}' '::: {.pub-notes}').
|
openners := #('::: {.pub-body-component}' '::: {.editor .Prosemirror}' '::: {.pub-notes}').
|
||||||
commented := self body.
|
commented := self body.
|
||||||
openners do: [:openner |
|
openners do: [:openner |
|
||||||
commented := commented copyReplaceAll: openner with: '<!--@div-open ', openner, '-->'
|
commented := commented copyReplaceAll: openner with: '<!--@div-open ', openner, '-->'
|
||||||
@ -126,9 +113,7 @@ Markdeep >> commentsSupport [
|
|||||||
|
|
||||||
{ #category : #accessing }
|
{ #category : #accessing }
|
||||||
Markdeep >> config [
|
Markdeep >> config [
|
||||||
| configFile |
|
|
||||||
configFile := self folder / 'config.ston'.
|
|
||||||
configFile exists ifTrue: [ ^ config := STON fromString: configFile contents ].
|
|
||||||
^ config ifNil: [ config := Dictionary new]
|
^ config ifNil: [ config := Dictionary new]
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -146,10 +131,10 @@ Markdeep >> contents [
|
|||||||
output
|
output
|
||||||
nextPutAll: self headContents; lf; lf;
|
nextPutAll: self headContents; lf; lf;
|
||||||
nextPutAll: ' **', self title trimmed accentedCharactersCorrection, '**'; lf;
|
nextPutAll: ' **', self title trimmed accentedCharactersCorrection, '**'; lf;
|
||||||
nextPutAll: self authorsString ; lf;
|
nextPutAll: self authorsString ; lf;
|
||||||
nextPutAll: '', self version; lf;
|
nextPutAll: '', self version; lf;
|
||||||
nextPutAll: self navTop; lf; lf;
|
nextPutAll: self navTop; lf; lf;
|
||||||
nextPutAll: self body; lf; lf;
|
nextPutAll: self body; lf; lf;
|
||||||
nextPutAll: self tail; lf; lf; lf; lf;
|
nextPutAll: self tail; lf; lf; lf; lf;
|
||||||
nextPutAll: self commentsSupport.
|
nextPutAll: self commentsSupport.
|
||||||
^ output contents.
|
^ output contents.
|
||||||
@ -171,68 +156,6 @@ Markdeep >> converPubPubFootnoteBetween: footnote and: nextFootnote in: footnote
|
|||||||
^ response contents
|
^ response contents
|
||||||
]
|
]
|
||||||
|
|
||||||
{ #category : #accessing }
|
|
||||||
Markdeep >> extractTitleFrom: docTree [
|
|
||||||
| tempTitle |
|
|
||||||
tempTitle := ((docTree children
|
|
||||||
detect: [ :node | node className = 'PPCMIndentedCode' ]) children
|
|
||||||
detect: [ :subnode | subnode text trimmed beginsWith: '**' ]) text trimmed.
|
|
||||||
self title: (tempTitle copyFrom: 3 to: tempTitle size - 2).
|
|
||||||
^ tempTitle
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #accessing }
|
|
||||||
Markdeep >> extractYamlMetadataFrom: documentTree [
|
|
||||||
| yamlComment response |
|
|
||||||
yamlComment := documentTree children
|
|
||||||
detect: [:node | node className = 'PPCMHtmlBlock' and: [node text trimmed beginsWith: '<!--@yaml']]
|
|
||||||
ifNone: [ ^ nil ].
|
|
||||||
response := '' writeStream.
|
|
||||||
yamlComment children allButFirst allButLast do: [:each |
|
|
||||||
response nextPutAll: each text; cr
|
|
||||||
].
|
|
||||||
^ {YAML2JSON fromString: response contents . yamlComment }
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #accessing }
|
|
||||||
Markdeep >> file: aFileReference [
|
|
||||||
file := aFileReference.
|
|
||||||
self fillInContentsFrom: aFileReference
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #accessing }
|
|
||||||
Markdeep >> fillInContentsFrom: aFileReference [
|
|
||||||
| docTree docTreeChildren headTree bodyStartLine bodyEndLine contentLines rawMetadata |
|
|
||||||
aFileReference exists ifFalse: [ ^ self ].
|
|
||||||
docTree := (Markdown new contents: aFileReference contents) documentTree.
|
|
||||||
docTreeChildren := docTree children.
|
|
||||||
headTree := docTreeChildren
|
|
||||||
detect: [ :node |
|
|
||||||
node className = 'PPCMParagraph'
|
|
||||||
and: [ (node children detect: [ :subnode | subnode text = '<head>' ]) isNotNil ] ]
|
|
||||||
ifNone: [ ^self ].
|
|
||||||
headTree children allButFirst allButLast
|
|
||||||
do: [ :node | node className = 'PPCMHtml' ifTrue: [ self head add: node text ] ].
|
|
||||||
self head: self head asSet asOrderedCollection.
|
|
||||||
rawMetadata := (self extractYamlMetadataFrom: docTree).
|
|
||||||
rawMetadata ifNotNil: [self metadata: rawMetadata first].
|
|
||||||
self title ifNil: [
|
|
||||||
self title: (self metadata at: 'title' ifAbsent: [self extractTitleFrom: docTree]).
|
|
||||||
self title: (self title trimBoth: [ :char | char = $" ]).
|
|
||||||
self metadata at: 'title' put: self title].
|
|
||||||
contentLines := self file contents lines.
|
|
||||||
bodyStartLine := (contentLines
|
|
||||||
detectIndex: [ :line | line includesSubstring: '<!--@yaml' ] ifNone: [ ^ self ]) + rawMetadata second children size.
|
|
||||||
bodyEndLine := contentLines detectIndex: [:line | line includesSubstring: '<!-- Markdeep'] ifNone: [ 0 ].
|
|
||||||
self body: (contentLines copyFrom: bodyStartLine to: bodyEndLine - 1 ) asStringWithCr.
|
|
||||||
^ self .
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #accessing }
|
|
||||||
Markdeep >> folder [
|
|
||||||
^ self file parent
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #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"
|
||||||
@ -244,7 +167,6 @@ Markdeep >> fontAwesomeHeader [
|
|||||||
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 file: aFileReference, 'html'.
|
|
||||||
^ self.
|
^ self.
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -269,11 +191,8 @@ Markdeep >> gtTextFor: aView [
|
|||||||
|
|
||||||
{ #category : #accessing }
|
{ #category : #accessing }
|
||||||
Markdeep >> head [
|
Markdeep >> head [
|
||||||
|
^ head ifNil: [ head := OrderedCollection new.
|
||||||
^ head ifNil: [
|
head add: self fontAwesomeHeader; yourself ]
|
||||||
head := OrderedCollection new.
|
|
||||||
head add: self fontAwesomeHeader; yourself.
|
|
||||||
].
|
|
||||||
]
|
]
|
||||||
|
|
||||||
{ #category : #accessing }
|
{ #category : #accessing }
|
||||||
@ -294,11 +213,6 @@ Markdeep >> headContents [
|
|||||||
nextPutAll: line;
|
nextPutAll: line;
|
||||||
nextPut: Character lf
|
nextPut: Character lf
|
||||||
].
|
].
|
||||||
self metadata keysAndValuesDo: [:k :v |
|
|
||||||
k = 'lang'
|
|
||||||
ifTrue: [ stream nextPutAll: ' <meta lang="', v,'">'; cr. ]
|
|
||||||
ifFalse: [ stream nextPutAll: ' <meta name="', k, '" content="', v,'">'; cr. ]
|
|
||||||
].
|
|
||||||
stream
|
stream
|
||||||
nextPutAll: '</head>';
|
nextPutAll: '</head>';
|
||||||
nextPut: Character lf.
|
nextPut: Character lf.
|
||||||
@ -334,15 +248,12 @@ Markdeep >> markdownFile [
|
|||||||
{ #category : #accessing }
|
{ #category : #accessing }
|
||||||
Markdeep >> markdownFile: aFileReference [
|
Markdeep >> markdownFile: aFileReference [
|
||||||
"Where the Mardown file associated with me is stored. Used for sync. and import/export purposes."
|
"Where the Mardown file associated with me is stored. Used for sync. and import/export purposes."
|
||||||
self file: aFileReference, 'html'
|
self config at: 'markdownFile' put: aFileReference
|
||||||
]
|
]
|
||||||
|
|
||||||
{ #category : #'instance creation' }
|
{ #category : #'instance creation' }
|
||||||
Markdeep >> metadata [
|
Markdeep >> metadata [
|
||||||
metadata ifNil: [^ metadata := OrderedDictionary new ].
|
^ metadata ifNil: [ metadata := OrderedDictionary new ]
|
||||||
(metadata isNil and: [ self file contents isNil ])
|
|
||||||
ifTrue: [ metadata := OrderedDictionary new ].
|
|
||||||
^ metadata
|
|
||||||
]
|
]
|
||||||
|
|
||||||
{ #category : #accessing }
|
{ #category : #accessing }
|
||||||
@ -383,13 +294,20 @@ Markdeep >> options [
|
|||||||
]
|
]
|
||||||
]
|
]
|
||||||
|
|
||||||
|
{ #category : #printing }
|
||||||
|
Markdeep >> printOn: aStream [
|
||||||
|
super printOn: aStream.
|
||||||
|
aStream
|
||||||
|
nextPutAll: '( ', self title accentedCharactersCorrection, ' )'
|
||||||
|
]
|
||||||
|
|
||||||
{ #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 file: aFileReference, 'html'.
|
self file: aFileReference, 'html'.
|
||||||
markdownContent := Markdown fromFile: aFileReference.
|
markdownContent := Markdown fromFile: aFileReference.
|
||||||
self metadata: markdownContent metadataAsYAML.
|
self metadata: markdownContent yamlMetadata.
|
||||||
self body: (markdownContent commentYAMLMetadata contents).
|
self body: (markdownContent commentYAMLMetadata contents).
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -433,8 +351,7 @@ Markdeep >> pubPubFootnotesLinesRangeFor: contentSection [
|
|||||||
| beginningLine endingLine |
|
| beginningLine endingLine |
|
||||||
beginningLine := contentSection lines size + 1.
|
beginningLine := contentSection lines size + 1.
|
||||||
contentSection lines doWithIndex: [:line :i |
|
contentSection lines doWithIndex: [:line :i |
|
||||||
((line includesSubstring: '::: {.pub-notes}') or: [line includesSubstring: '::: pub-notes'])
|
(line includesSubstring: '::: {.pub-notes}') ifTrue: [ beginningLine := i ].
|
||||||
ifTrue: [ beginningLine := i ].
|
|
||||||
(i > beginningLine and: [ line beginsWith: ':::' ])
|
(i > beginningLine and: [ line beginsWith: ':::' ])
|
||||||
ifTrue: [
|
ifTrue: [
|
||||||
endingLine := i.
|
endingLine := i.
|
||||||
@ -548,8 +465,7 @@ please visit the HTML version or download the PDF.
|
|||||||
{ #category : #accessing }
|
{ #category : #accessing }
|
||||||
Markdeep >> removeCCByLicenseDiv [
|
Markdeep >> removeCCByLicenseDiv [
|
||||||
| licenseDiv|
|
| licenseDiv|
|
||||||
licenseDiv := '
|
licenseDiv := '<div>
|
||||||
<div>
|
|
||||||
|
|
||||||
**License:** [Creative Commons Attribution 4.0 International License
|
**License:** [Creative Commons Attribution 4.0 International License
|
||||||
(CC-BY 4.0)](https://creativecommons.org/licenses/by/4.0/)
|
(CC-BY 4.0)](https://creativecommons.org/licenses/by/4.0/)
|
||||||
@ -649,7 +565,7 @@ Markdeep >> tail: anObject [
|
|||||||
{ #category : #accessing }
|
{ #category : #accessing }
|
||||||
Markdeep >> title [
|
Markdeep >> title [
|
||||||
|
|
||||||
^ title
|
^ title ifNil: [ title := self metadata at: 'title' ifAbsent: [ '' ] ]
|
||||||
]
|
]
|
||||||
|
|
||||||
{ #category : #accessing }
|
{ #category : #accessing }
|
||||||
|
@ -9,8 +9,7 @@ Class {
|
|||||||
#superclass : #MarkupFile,
|
#superclass : #MarkupFile,
|
||||||
#instVars : [
|
#instVars : [
|
||||||
'metadata',
|
'metadata',
|
||||||
'body',
|
'body'
|
||||||
'title'
|
|
||||||
],
|
],
|
||||||
#category : #'MiniDocs-Core'
|
#category : #'MiniDocs-Core'
|
||||||
}
|
}
|
||||||
@ -20,22 +19,20 @@ Markdown class >> fromFile: aFileReference [
|
|||||||
^ self new fromFile: aFileReference
|
^ self new fromFile: aFileReference
|
||||||
]
|
]
|
||||||
|
|
||||||
|
{ #category : #utilities }
|
||||||
|
Markdown class >> yamlMetadataDelimiter [
|
||||||
|
^ '---'
|
||||||
|
|
||||||
|
]
|
||||||
|
|
||||||
{ #category : #accessing }
|
{ #category : #accessing }
|
||||||
Markdown >> asMarkdeep [
|
Markdown >> asMarkdeep [
|
||||||
^ Markdeep new
|
^ Markdeep new
|
||||||
body: self body;
|
body: self body;
|
||||||
|
markdownFile: self file;
|
||||||
commentYAMLMetadata
|
commentYAMLMetadata
|
||||||
]
|
]
|
||||||
|
|
||||||
{ #category : #accessing }
|
|
||||||
Markdown >> asMarkdownTiddler [
|
|
||||||
^ Tiddler new
|
|
||||||
title: self title;
|
|
||||||
text: self contents;
|
|
||||||
type: 'text/x-markdown';
|
|
||||||
created: Tiddler nowLocal.
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #accessing }
|
{ #category : #accessing }
|
||||||
Markdown >> body [
|
Markdown >> body [
|
||||||
^ body
|
^ body
|
||||||
@ -49,7 +46,7 @@ Markdown >> body: aString [
|
|||||||
{ #category : #operation }
|
{ #category : #operation }
|
||||||
Markdown >> commentYAMLMetadata [
|
Markdown >> commentYAMLMetadata [
|
||||||
| newContents |
|
| newContents |
|
||||||
self contents detectYAMLMetadata ifFalse: [ ^ self ].
|
self detectYAMLMetadata ifFalse: [ ^ self ].
|
||||||
newContents := '' writeStream.
|
newContents := '' writeStream.
|
||||||
newContents nextPutAll: '<!--@yaml'; lf.
|
newContents nextPutAll: '<!--@yaml'; lf.
|
||||||
newContents nextPutAll: self yamlMetadataString.
|
newContents nextPutAll: self yamlMetadataString.
|
||||||
@ -66,27 +63,48 @@ Markdown >> containsYAMLMetadataClosing [
|
|||||||
|
|
||||||
{ #category : #accessing }
|
{ #category : #accessing }
|
||||||
Markdown >> contents [
|
Markdown >> contents [
|
||||||
| response metadataString |
|
^ body
|
||||||
response := WriteStream on: ''.
|
|
||||||
metadataString := self metadataAsYAML
|
|
||||||
ifEmpty: [ '' ]
|
|
||||||
ifNotEmpty: [ '---', String cr, self metadataAsYAML, String cr, '---', String cr ].
|
|
||||||
response
|
|
||||||
nextPutAll: metadataString;
|
|
||||||
nextPutAll: (self body ifNil: [ '' ]).
|
|
||||||
^ response contents withInternetLineEndings
|
|
||||||
]
|
]
|
||||||
|
|
||||||
{ #category : #accessing }
|
{ #category : #accessing }
|
||||||
Markdown >> contents: aString [
|
Markdown >> contents: anObject [
|
||||||
body := aString
|
body := anObject
|
||||||
|
]
|
||||||
|
|
||||||
|
{ #category : #accessing }
|
||||||
|
Markdown >> contentsWithoutYAMLMetadata [
|
||||||
|
| newContents |
|
||||||
|
self detectYAMLMetadata ifFalse: [ ^ self ].
|
||||||
|
newContents := '' writeStream.
|
||||||
|
(self lines copyFrom: self yamlMetadataClosingLineNumber + 2 to: self lines size) do: [ :line |
|
||||||
|
newContents nextPutAll: line; crlf ].
|
||||||
|
^ newContents contents.
|
||||||
|
]
|
||||||
|
|
||||||
|
{ #category : #operation }
|
||||||
|
Markdown >> deleteYAMLMetadata [
|
||||||
|
| newContents |
|
||||||
|
self detectYAMLMetadata ifFalse: [ ^ self ].
|
||||||
|
newContents := '' writeStream.
|
||||||
|
(self lines copyFrom: self yamlMetadataClosingLineNumber + 1 to: self lines size) do: [ :line |
|
||||||
|
newContents nextPutAll: line; lf;lf ].
|
||||||
|
^ newContents contents.
|
||||||
|
]
|
||||||
|
|
||||||
|
{ #category : #utilities }
|
||||||
|
Markdown >> detectYAMLMetadata [
|
||||||
|
| lines |
|
||||||
|
lines := self lines.
|
||||||
|
^ self startsWithYAMLMetadataDelimiter
|
||||||
|
and: [ lines allButFirst
|
||||||
|
detect: [ :currentLine | currentLine beginsWith: self class yamlMetadataDelimiter ]
|
||||||
|
ifFound: [ ^ true ] ifNone: [ ^ false ] ]
|
||||||
]
|
]
|
||||||
|
|
||||||
{ #category : #accessing }
|
{ #category : #accessing }
|
||||||
Markdown >> documentTree [
|
Markdown >> documentTree [
|
||||||
| parser|
|
| parser|
|
||||||
self contents ifNil: [^ nil].
|
parser := PPCommonMarkBlockParser new parse: self contents.
|
||||||
parser := PPCommonMarkBlockParser new parse: self body.
|
|
||||||
^ parser accept: CMBlockVisitor new
|
^ parser accept: CMBlockVisitor new
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -103,12 +121,7 @@ Markdown >> exportAsFileOn: aFileReference [
|
|||||||
aFileReference ensureDelete.
|
aFileReference ensureDelete.
|
||||||
aFileReference exists ifFalse: [ aFileReference ensureCreateFile ].
|
aFileReference exists ifFalse: [ aFileReference ensureCreateFile ].
|
||||||
aFileReference writeStreamDo: [ :stream |
|
aFileReference writeStreamDo: [ :stream |
|
||||||
stream nextPutAll: self contents withInternetLineEndings ].
|
stream nextPutAll: self contents ].
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #accessing }
|
|
||||||
Markdown >> exportAsHTML [
|
|
||||||
^ Pandoc markdownToHtml: self file
|
|
||||||
]
|
]
|
||||||
|
|
||||||
{ #category : #operation }
|
{ #category : #operation }
|
||||||
@ -142,7 +155,7 @@ Markdown >> exportMetadataAsYaml [
|
|||||||
|
|
||||||
{ #category : #accessing }
|
{ #category : #accessing }
|
||||||
Markdown >> file [
|
Markdown >> file [
|
||||||
^ file ifNil: [ file := FileLocator temp / 'temporalMarkdeep.md' ]
|
^ file ifNil: [ file := FileLocator temp / (NanoID generate asLowercase, '.md') ]
|
||||||
]
|
]
|
||||||
|
|
||||||
{ #category : #accessing }
|
{ #category : #accessing }
|
||||||
@ -153,24 +166,15 @@ Markdown >> file: aFileReference [
|
|||||||
|
|
||||||
{ #category : #'instance creation' }
|
{ #category : #'instance creation' }
|
||||||
Markdown >> fromFile: aFileReference [
|
Markdown >> fromFile: aFileReference [
|
||||||
self fromString: aFileReference contents.
|
self contents: aFileReference contents.
|
||||||
self file: aFileReference.
|
self file: aFileReference.
|
||||||
]
|
]
|
||||||
|
|
||||||
{ #category : #'instance creation' }
|
{ #category : #'instance creation' }
|
||||||
Markdown >> fromString: markdownString [
|
Markdown >> fromString: markdownString [
|
||||||
| yamlMetadataRaw bodyTemp |
|
self contents: markdownString.
|
||||||
yamlMetadataRaw := (YamlHeaderParser parse: markdownString).
|
self populateMetadata.
|
||||||
bodyTemp := '' writeStream.
|
self contents: self contentsWithoutYAMLMetadata
|
||||||
(yamlMetadataRaw removeKey: 'body') do: [:paragraph |
|
|
||||||
bodyTemp nextPutAll: paragraph; cr; cr
|
|
||||||
].
|
|
||||||
self body: bodyTemp contents withInternetLineEndings.
|
|
||||||
(yamlMetadataRaw sanitizeMultilineValuesWith: markdownString)
|
|
||||||
ifNotNil: [
|
|
||||||
self metadata
|
|
||||||
ifEmpty: [ self metadata: yamlMetadataRaw ]
|
|
||||||
ifNotEmpty: [ self metadata at: 'hedgeDoc' put: yamlMetadataRaw ]].
|
|
||||||
]
|
]
|
||||||
|
|
||||||
{ #category : #accessing }
|
{ #category : #accessing }
|
||||||
@ -181,17 +185,8 @@ Markdown >> gtTextFor: aView [
|
|||||||
text: [ self contents ]
|
text: [ self contents ]
|
||||||
]
|
]
|
||||||
|
|
||||||
{ #category : #accessing }
|
|
||||||
Markdown >> headerAsTitle [
|
|
||||||
| headerNode |
|
|
||||||
headerNode := self documentTree children
|
|
||||||
detect: [ :node | node className = 'PPCMHeader' and: [ node level = 1 ] ] ifNone: [ ^ 'Untitled' ].
|
|
||||||
^ headerNode text
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #utilities }
|
{ #category : #utilities }
|
||||||
Markdown >> lines [
|
Markdown >> lines [
|
||||||
self file ifNotNil: [^ self file contents lines ].
|
|
||||||
^ self contents lines.
|
^ self contents lines.
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -200,7 +195,6 @@ Markdown >> metadata [
|
|||||||
|
|
||||||
^ metadata ifNil: [ metadata := Dictionary new].
|
^ metadata ifNil: [ metadata := Dictionary new].
|
||||||
|
|
||||||
|
|
||||||
]
|
]
|
||||||
|
|
||||||
{ #category : #accessing }
|
{ #category : #accessing }
|
||||||
@ -209,12 +203,6 @@ Markdown >> metadata: rawMeta [
|
|||||||
metadata := rawMeta
|
metadata := rawMeta
|
||||||
]
|
]
|
||||||
|
|
||||||
{ #category : #accessing }
|
|
||||||
Markdown >> metadataAsYAML [
|
|
||||||
self metadata isEmptyOrNil ifTrue: [ ^ '' ].
|
|
||||||
^ (YQ jsonToYaml: self metadata) accentedCharactersCorrection
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #persistence }
|
{ #category : #persistence }
|
||||||
Markdown >> notifyExportAsFileOn: aFileReference [
|
Markdown >> notifyExportAsFileOn: aFileReference [
|
||||||
self exportAsFileOn: aFileReference.
|
self exportAsFileOn: aFileReference.
|
||||||
@ -223,25 +211,62 @@ Markdown >> notifyExportAsFileOn: aFileReference [
|
|||||||
]
|
]
|
||||||
|
|
||||||
{ #category : #accessing }
|
{ #category : #accessing }
|
||||||
Markdown >> options [
|
Markdown >> populateMetadata [
|
||||||
^ self metadata at: 'options' ifAbsentPut: [ self defaultOptions]
|
| rawMeta |
|
||||||
|
rawMeta := MiniDocs yamlToJson: self yamlMetadataString.
|
||||||
|
rawMeta associationsDo: [ :assoc |
|
||||||
|
assoc value = 'false' ifTrue: [ assoc value: false ].
|
||||||
|
assoc value = 'true' ifTrue: [ assoc value: true ] ].
|
||||||
|
self metadata: rawMeta
|
||||||
]
|
]
|
||||||
|
|
||||||
{ #category : #accessing }
|
{ #category : #accessing }
|
||||||
Markdown >> printOn: aStream [
|
Markdown >> printOn: aStream [
|
||||||
| response |
|
|
||||||
super printOn: aStream.
|
super printOn: aStream.
|
||||||
response := self title ifNil: [ 'Untitled' ].
|
|
||||||
aStream
|
aStream
|
||||||
nextPutAll: '( ', response , ' )'
|
nextPutAll: '( ', (self metadata at: 'title' ifAbsent: ['untitled']), ' )'
|
||||||
|
]
|
||||||
|
|
||||||
|
{ #category : #utilities }
|
||||||
|
Markdown >> startsWithYAMLMetadataDelimiter [
|
||||||
|
^ self lines first beginsWith: self class yamlMetadataDelimiter
|
||||||
|
|
||||||
]
|
]
|
||||||
|
|
||||||
{ #category : #accessing }
|
{ #category : #accessing }
|
||||||
Markdown >> title [
|
Markdown >> yamlMetadata [
|
||||||
^ title ifNil: [ title:= self headerAsTitle ]
|
^ MiniDocs yamlToJson: self yamlMetadataString
|
||||||
]
|
]
|
||||||
|
|
||||||
{ #category : #accessing }
|
{ #category : #utilities }
|
||||||
Markdown >> title: aString [
|
Markdown >> yamlMetadataClosingLineNumber [
|
||||||
title := aString
|
"I return the line where the closing of the YAML metadata occurs or 0 if no closing is found."
|
||||||
|
self startsWithYAMLMetadataDelimiter ifFalse: [ ^ self ].
|
||||||
|
self lines allButFirst doWithIndex: [ :currentLine :i |
|
||||||
|
(currentLine beginsWith: self class yamlMetadataDelimiter) ifTrue: [ ^ i + 1 ]]
|
||||||
|
|
||||||
|
]
|
||||||
|
|
||||||
|
{ #category : #operation }
|
||||||
|
Markdown >> yamlMetadataString [
|
||||||
|
| output yamlLines |
|
||||||
|
self detectYAMLMetadata ifFalse: [ ^ nil ].
|
||||||
|
yamlLines := self lines copyFrom: 2 to: self yamlMetadataClosingLineNumber - 1.
|
||||||
|
output := '' writeStream.
|
||||||
|
yamlLines do: [ :line |
|
||||||
|
output
|
||||||
|
nextPutAll: line;
|
||||||
|
nextPut: Character lf. ].
|
||||||
|
^ output contents
|
||||||
|
]
|
||||||
|
|
||||||
|
{ #category : #utilities }
|
||||||
|
Markdown >> yamlMetadataStringWithDelimiters [
|
||||||
|
| output |
|
||||||
|
self yamlMetadataString ifNil: [ ^ nil ].
|
||||||
|
output := String new writeStream.
|
||||||
|
output nextPutAll: self class yamlMetadataDelimiter; cr.
|
||||||
|
output nextPutAll: self yamlMetadataString.
|
||||||
|
output nextPutAll: self class yamlMetadataDelimiter; cr.
|
||||||
|
^ output contents.
|
||||||
]
|
]
|
||||||
|
@ -11,16 +11,13 @@ Class {
|
|||||||
}
|
}
|
||||||
|
|
||||||
{ #category : #persistence }
|
{ #category : #persistence }
|
||||||
MarkupFile class >> exportAsFileOn: aFileReferenceOrFileName containing: anObject [
|
MarkupFile class >> exportAsFileOn: aFileReferenceOrFileName containing: text [
|
||||||
| file preprocessed |
|
| file |
|
||||||
file := aFileReferenceOrFileName asFileReference.
|
file := aFileReferenceOrFileName asFileReference.
|
||||||
file ensureDelete.
|
file ensureDelete.
|
||||||
file exists ifFalse: [ file ensureCreateFile ].
|
file exists ifFalse: [ file ensureCreateFile ].
|
||||||
(#('String' 'ByteString' 'WideString') includes: anObject className )
|
|
||||||
ifTrue: [ preprocessed := anObject ]
|
|
||||||
ifFalse: [preprocessed := STON toStringPretty: anObject ].
|
|
||||||
file writeStreamDo: [ :stream |
|
file writeStreamDo: [ :stream |
|
||||||
stream nextPutAll: preprocessed ].
|
stream nextPutAll: text withUnixLineEndings].
|
||||||
self inform: 'Exported as: ', String cr, file fullName.
|
self inform: 'Exported as: ', String cr, file fullName.
|
||||||
^ file
|
^ file
|
||||||
]
|
]
|
||||||
|
@ -10,7 +10,7 @@ Class {
|
|||||||
{ #category : #accessing }
|
{ #category : #accessing }
|
||||||
MiniDocs class >> altKeys [
|
MiniDocs class >> altKeys [
|
||||||
^ BlAlternativeCombination new
|
^ BlAlternativeCombination new
|
||||||
combination: (BlSingleKeyCombination key:BlKeyboardKey altLeft)
|
key: (BlSingleKeyCombination key:BlKeyboardKey altLeft)
|
||||||
or: (BlSingleKeyCombination key:BlKeyboardKey altRight)
|
or: (BlSingleKeyCombination key:BlKeyboardKey altRight)
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -34,17 +34,15 @@ MiniDocs class >> altShiftRightCombo [
|
|||||||
|
|
||||||
{ #category : #accessing }
|
{ #category : #accessing }
|
||||||
MiniDocs class >> appFolder [
|
MiniDocs class >> appFolder [
|
||||||
| tempFolder |
|
| tempFolder userDataFolder |
|
||||||
tempFolder := ExoRepo userDataFolder / 'Mutabit' / 'MiniDocs'.
|
userDataFolder := Smalltalk os isWindows
|
||||||
|
ifTrue: [ FileLocator home / 'AppData' / 'Local' ]
|
||||||
|
ifFalse: [ FileLocator userData ].
|
||||||
|
tempFolder := userDataFolder / 'Mutabit' / 'MiniDocs'.
|
||||||
tempFolder exists ifFalse: [ tempFolder ensureCreateDirectory ].
|
tempFolder exists ifFalse: [ tempFolder ensureCreateDirectory ].
|
||||||
^ tempFolder
|
^ tempFolder
|
||||||
]
|
]
|
||||||
|
|
||||||
{ #category : #accessing }
|
|
||||||
MiniDocs class >> exportAsSton: anObject on: aFileReference [
|
|
||||||
MarkupFile exportAsFileOn: aFileReference containing: (STON toStringPretty: anObject) withInternetLineEndings
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #accessing }
|
{ #category : #accessing }
|
||||||
MiniDocs class >> importGrafoscopioFile: aFileReference [
|
MiniDocs class >> importGrafoscopioFile: aFileReference [
|
||||||
|
|
||||||
@ -89,7 +87,7 @@ MiniDocs class >> keyboardShortcutsRemapping [
|
|||||||
{ #category : #accessing }
|
{ #category : #accessing }
|
||||||
MiniDocs class >> shiftKeys [
|
MiniDocs class >> shiftKeys [
|
||||||
^ BlAlternativeCombination new
|
^ BlAlternativeCombination new
|
||||||
combination: (BlSingleKeyCombination key:BlKeyboardKey shiftLeft)
|
key: (BlSingleKeyCombination key:BlKeyboardKey shiftLeft)
|
||||||
or: (BlSingleKeyCombination key:BlKeyboardKey shiftRight)
|
or: (BlSingleKeyCombination key:BlKeyboardKey shiftRight)
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -97,7 +95,6 @@ MiniDocs class >> shiftKeys [
|
|||||||
MiniDocs class >> yamlToJson: yamlString [
|
MiniDocs class >> yamlToJson: yamlString [
|
||||||
"This method uses a external binary written in Nim, as the native Pharo parser for YAML, written in PetitParser,
|
"This method uses a external binary written in Nim, as the native Pharo parser for YAML, written in PetitParser,
|
||||||
was less robust and unable to parse correctly the same strings as the external one."
|
was less robust and unable to parse correctly the same strings as the external one."
|
||||||
yamlString ifNil: [ ^ Dictionary new ].
|
|
||||||
self yamlToJsonBinary exists ifFalse: [ self installYamlToJson ].
|
self yamlToJsonBinary exists ifFalse: [ self installYamlToJson ].
|
||||||
|
|
||||||
OSSUnixSubprocess new
|
OSSUnixSubprocess new
|
||||||
@ -105,7 +102,7 @@ MiniDocs class >> yamlToJson: yamlString [
|
|||||||
arguments: {yamlString};
|
arguments: {yamlString};
|
||||||
redirectStdout;
|
redirectStdout;
|
||||||
runAndWaitOnExitDo: [ :process :outString |
|
runAndWaitOnExitDo: [ :process :outString |
|
||||||
^ (STONJSON fromString: outString allButFirst accentedCharactersCorrection) first
|
^ (STONJSON fromString: outString allButFirst) first
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -39,7 +39,7 @@ MiniDocsServer class >> restart [
|
|||||||
|
|
||||||
{ #category : #accessing }
|
{ #category : #accessing }
|
||||||
MiniDocsServer class >> singleton [
|
MiniDocsServer class >> singleton [
|
||||||
^ singleton ifNil: [ singleton := MiniDocsServer teapot ]
|
^ singleton
|
||||||
]
|
]
|
||||||
|
|
||||||
{ #category : #accessing }
|
{ #category : #accessing }
|
||||||
|
55
src/MiniDocs/NanoID.class.st
Normal file
55
src/MiniDocs/NanoID.class.st
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
"
|
||||||
|
I'm run an implementation of the [Nano ID](https://github.com/ai/nanoid) tiny, secure URL-friendly unique string ID generator via its [Nim implementation](https://github.com/icyphox/nanoid.nim).
|
||||||
|
|
||||||
|
The Nim script has hard coded:
|
||||||
|
|
||||||
|
* a [base 58 encoding](https://medium.com/concerning-pharo/understanding-base58-encoding-23e673e37ff6) alphabet to avoid similar looking letter and the use of non-alphanumeric characters.
|
||||||
|
* a 12 characters length output, which gives [a pretty low probability collision](https://zelark.github.io/nano-id-cc/) for the previous alphabet:
|
||||||
|
~616 years needed, in order to have a 1% probability of at least one collision at a speed of 1000 IDs per hour.
|
||||||
|
This is more than enough for our unique IDs applications, mostly in the documentation context,
|
||||||
|
which consists of hand crafted and/or programmatically produced notes ,
|
||||||
|
for example in data narratives, book(lets) and TiddlyWiki tiddlers of tens or hundreds of notes at most,
|
||||||
|
unevenly produced between hours, days and/or weeks..
|
||||||
|
|
||||||
|
The `External` tag is related on its dependency on other programming languages and frameworks,
|
||||||
|
though the dependency should be loaded by just loading a small binary with no dependencies.
|
||||||
|
"
|
||||||
|
Class {
|
||||||
|
#name : #NanoID,
|
||||||
|
#superclass : #Object,
|
||||||
|
#category : #'MiniDocs-External'
|
||||||
|
}
|
||||||
|
|
||||||
|
{ #category : #accessing }
|
||||||
|
NanoID class >> binaryFile [
|
||||||
|
^ MiniDocs appFolder / self scriptSourceCode basenameWithoutExtension
|
||||||
|
]
|
||||||
|
|
||||||
|
{ #category : #accessing }
|
||||||
|
NanoID class >> generate [
|
||||||
|
self binaryFile exists ifFalse: [ NanoID install].
|
||||||
|
OSSUnixSubprocess new
|
||||||
|
command: self binaryFile fullName;
|
||||||
|
redirectStdout;
|
||||||
|
redirectStdout;
|
||||||
|
runAndWaitOnExitDo: [ :process :outString | ^ outString copyWithoutAll: (Character lf asString) ]
|
||||||
|
]
|
||||||
|
|
||||||
|
{ #category : #accessing }
|
||||||
|
NanoID class >> install [
|
||||||
|
"For the moment, only Gnu/Linux and Mac are supported.
|
||||||
|
IMPORTANT: Nimble, Nim's package manager should be installed, as this process doesn't verify its proper installation."
|
||||||
|
self binaryFile exists ifTrue: [ ^ MiniDocs appFolder ].
|
||||||
|
Nimble install: 'nanoid'.
|
||||||
|
OSSUnixSubprocess new
|
||||||
|
command: 'nim';
|
||||||
|
arguments: {'c'. self scriptSourceCode fullName};
|
||||||
|
runAndWaitOnExitDo: [ :process :outString |
|
||||||
|
(self scriptSourceCode parent / (self scriptSourceCode) basenameWithoutExtension) moveToPageTitled: MiniDocs appFolder asFileReference.
|
||||||
|
^ MiniDocs appFolder ]
|
||||||
|
]
|
||||||
|
|
||||||
|
{ #category : #accessing }
|
||||||
|
NanoID class >> scriptSourceCode [
|
||||||
|
^ FileLocator image parent / 'pharo-local/iceberg/Offray/MiniDocs/src/nanoIdGen.nim'
|
||||||
|
]
|
82
src/MiniDocs/Nimble.class.st
Normal file
82
src/MiniDocs/Nimble.class.st
Normal file
@ -0,0 +1,82 @@
|
|||||||
|
"
|
||||||
|
I'm a helper class modelling the common uses of the Nim's [Nimble package manager](https://github.com/nim-lang/nimble).
|
||||||
|
This was evolved in the context of the [Grafoscopio](mutabit.com/grafoscopio/en.html) community exploration and prototyping of interactive documentation.
|
||||||
|
"
|
||||||
|
Class {
|
||||||
|
#name : #Nimble,
|
||||||
|
#superclass : #Object,
|
||||||
|
#category : #'MiniDocs-External'
|
||||||
|
}
|
||||||
|
|
||||||
|
{ #category : #accessing }
|
||||||
|
Nimble class >> detect: packageName [
|
||||||
|
^ self installed
|
||||||
|
detect: [ :dependency | dependency beginsWith: packageName ]
|
||||||
|
ifFound: [ ^ true ]
|
||||||
|
ifNone: [ ^ false ]
|
||||||
|
]
|
||||||
|
|
||||||
|
{ #category : #accessing }
|
||||||
|
Nimble class >> install: packageName [
|
||||||
|
(self detect: packageName) ifTrue: [ ^ self ].
|
||||||
|
self installPackagesList.
|
||||||
|
OSSUnixSubprocess new
|
||||||
|
command: 'nimble';
|
||||||
|
arguments: {'install'.
|
||||||
|
packageName};
|
||||||
|
redirectStdout;
|
||||||
|
redirectStderr;
|
||||||
|
runAndWaitOnExitDo: [ :process :outString :errString |
|
||||||
|
process isSuccess
|
||||||
|
ifTrue: [ Transcript show: 'Command exited correctly with output: ', outString. ]
|
||||||
|
ifFalse: [
|
||||||
|
^ 'Command exit with error status: ', process exitStatusInterpreter printString, String cr,
|
||||||
|
'Stderr contents: ', errString.
|
||||||
|
]
|
||||||
|
]
|
||||||
|
]
|
||||||
|
|
||||||
|
{ #category : #accessing }
|
||||||
|
Nimble class >> installPackagesList [
|
||||||
|
|
||||||
|
(FileLocator home / '.nimble' / 'packages_official.json') exists
|
||||||
|
ifTrue: [ ^ self ].
|
||||||
|
OSSUnixSubprocess new
|
||||||
|
command: 'nimble';
|
||||||
|
arguments: #('refresh');
|
||||||
|
redirectStdout;
|
||||||
|
runAndWaitOnExitDo: [ :process :outString | ^ outString ]
|
||||||
|
]
|
||||||
|
|
||||||
|
{ #category : #accessing }
|
||||||
|
Nimble class >> installed [
|
||||||
|
|
||||||
|
Smalltalk os isWindows
|
||||||
|
ifTrue: [ | process |
|
||||||
|
process := GtExternalProcessBuilder new
|
||||||
|
command: 'nimble.exe';
|
||||||
|
args: #('list' '--installed');
|
||||||
|
output.
|
||||||
|
^ process stdout lines ].
|
||||||
|
|
||||||
|
OSSUnixSubprocess new
|
||||||
|
command: 'nimble';
|
||||||
|
arguments: #('list' '--installed');
|
||||||
|
redirectStdout;
|
||||||
|
redirectStderr;
|
||||||
|
runAndWaitOnExitDo: [ :process :outString :errString |
|
||||||
|
process isSuccess
|
||||||
|
ifTrue: [ ^ outString lines ];
|
||||||
|
ifFalse: [ ^ nil ]
|
||||||
|
]
|
||||||
|
]
|
||||||
|
|
||||||
|
{ #category : #accessing }
|
||||||
|
Nimble class >> version [
|
||||||
|
|
||||||
|
OSSUnixSubprocess new
|
||||||
|
command: 'nimble';
|
||||||
|
arguments: #('--version');
|
||||||
|
redirectStdout;
|
||||||
|
runAndWaitOnExitDo: [ :process :outString | ^ outString ]
|
||||||
|
]
|
@ -1,100 +0,0 @@
|
|||||||
Extension { #name : #OrderedDictionary }
|
|
||||||
|
|
||||||
{ #category : #'*MiniDocs' }
|
|
||||||
OrderedDictionary >> addErrata: noteString [
|
|
||||||
self errata add: noteString
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #'*MiniDocs' }
|
|
||||||
OrderedDictionary >> asLepiterSnippet [
|
|
||||||
| response |
|
|
||||||
self at: 'className' ifAbsent: [ ^ nil ].
|
|
||||||
response := (self at: 'className') asClass new.
|
|
||||||
[ response fromDictionary: self ] onErrorDo: [ ].
|
|
||||||
[ response fromString: (self at: 'content') ] onErrorDo: [ ].
|
|
||||||
self at: 'origin' ifPresent: [ response metadata at: 'origin' put: (self at: 'origin') ].
|
|
||||||
self at: 'errata' ifPresent: [ response metadata at: 'errata' put: (self at: 'errata') ].
|
|
||||||
^ response
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #'*MiniDocs' }
|
|
||||||
OrderedDictionary >> asYAML [
|
|
||||||
^ (YQ jsonToYaml: self) accentedCharactersCorrection.
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #'*MiniDocs' }
|
|
||||||
OrderedDictionary >> errata [
|
|
||||||
^ self at: 'errata' ifAbsentPut: [ OrderedCollection new]
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #'*MiniDocs' }
|
|
||||||
OrderedDictionary >> redefineTimestampsBefore: dateAndTime [
|
|
||||||
self at: 'modified' put: dateAndTime asDateAndTime.
|
|
||||||
self at: 'created' put: dateAndTime asDateAndTime - 1 second.
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #'*MiniDocs' }
|
|
||||||
OrderedDictionary >> replaceNilsWith: aCharacter [
|
|
||||||
self associationsDo: [:each |
|
|
||||||
each value ifNil: [self at: each key put: aCharacter].
|
|
||||||
each value isDictionary ifTrue: [each value replaceNilsWith: aCharacter].
|
|
||||||
each value isArray ifTrue: [ | newArray|
|
|
||||||
newArray := (each value asDataSeries replaceNilsWith: aCharacter) asArray.
|
|
||||||
self at: each key put: newArray
|
|
||||||
]
|
|
||||||
]
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #'*MiniDocs' }
|
|
||||||
OrderedDictionary >> replaceWithUniqueNilsAndBooleansStartingAt: anInteger [
|
|
||||||
| totalNils shortUID |
|
|
||||||
totalNils := self flattened asDataSeries countNils.
|
|
||||||
shortUID := [NanoID generate copyFrom: 1 to: 3].
|
|
||||||
self associations doWithIndex: [:assoc :i | | subIndex |
|
|
||||||
subIndex := anInteger asString, '-', i asString.
|
|
||||||
assoc value
|
|
||||||
ifNil: [ self at: assoc key put: 'nil-', subIndex ].
|
|
||||||
assoc value isBoolean
|
|
||||||
ifTrue: [ self at: assoc key put: assoc value asString, '-', subIndex ].
|
|
||||||
assoc value isDictionary ifTrue: [assoc replaceWithUniqueNilsAndBooleansStartingAt: i].
|
|
||||||
assoc value isArray
|
|
||||||
ifTrue: [ self at: assoc key put: (assoc value replaceWithUniqueNilsAndBooleans)]
|
|
||||||
]
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #'*MiniDocs' }
|
|
||||||
OrderedDictionary >> sanitizeMultilineValuesWith: aString [
|
|
||||||
| toSanitize response |
|
|
||||||
toSanitize := OrderedCollection new.
|
|
||||||
response := OrderedCollection new.
|
|
||||||
self keysAndValuesDo: [:k :v |
|
|
||||||
(v isString and: [v lines size > 1])
|
|
||||||
ifTrue: [
|
|
||||||
aString lines
|
|
||||||
detect: [:line | line includesSubstring: k ]
|
|
||||||
ifFound: [:line | | sanitized|
|
|
||||||
sanitized := (line withoutPrefix: k, ':'), String cr,
|
|
||||||
v indentedWithExtraSpaces: 4.
|
|
||||||
self at: k put: sanitized ]
|
|
||||||
]
|
|
||||||
].
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #'*MiniDocs' }
|
|
||||||
OrderedDictionary >> treeView [
|
|
||||||
| view |
|
|
||||||
view := GtMondrian new.
|
|
||||||
view nodes
|
|
||||||
stencil: [ :x |
|
|
||||||
BlElement new
|
|
||||||
border: (BlBorder paint: Color black);
|
|
||||||
geometry: BlEllipseGeometry new;
|
|
||||||
layout: (BlLinearLayout new alignCenter);
|
|
||||||
addChild: (BlTextElement text: (x asRopedText fontSize: 10)) ];
|
|
||||||
with: (self flatCollectAsSet: #yourself) , self keys.
|
|
||||||
view edges
|
|
||||||
stencil: [ :x | BlLineElement new border: (BlBorder paint: (Color blue alpha: 0.5) width: 4) ];
|
|
||||||
connect: self associations from: #key toAll: #value.
|
|
||||||
view layout tree.
|
|
||||||
^ view
|
|
||||||
]
|
|
@ -1,162 +0,0 @@
|
|||||||
"
|
|
||||||
I model the interaction between Pandoc and Grafoscopio.
|
|
||||||
"
|
|
||||||
Class {
|
|
||||||
#name : #Pandoc,
|
|
||||||
#superclass : #Object,
|
|
||||||
#classInstVars : [
|
|
||||||
'executable'
|
|
||||||
],
|
|
||||||
#category : #'MiniDocs-Core'
|
|
||||||
}
|
|
||||||
|
|
||||||
{ #category : #'*MiniDocs' }
|
|
||||||
Pandoc class >> convertString: aString from: inputFormat to: outputFormat [
|
|
||||||
OSSUnixSubprocess new
|
|
||||||
shellCommand: 'echo "', aString , '" | pandoc -f ', inputFormat,' -t ', outputFormat;
|
|
||||||
redirectStdout;
|
|
||||||
runAndWaitOnExitDo: [ :command :outString |
|
|
||||||
^ outString
|
|
||||||
].
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #'as yet unclassified' }
|
|
||||||
Pandoc class >> downloadLuaFilters [
|
|
||||||
self luaFilters do: [ :filter | | filterUrl |
|
|
||||||
filterUrl := filter asUrl.
|
|
||||||
(FileLocator temp asFileReference / (filterUrl segments last)) exists
|
|
||||||
ifFalse: [
|
|
||||||
ZnClient new
|
|
||||||
url: filterUrl;
|
|
||||||
downloadTo: FileLocator temp ] ]
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #accessing }
|
|
||||||
Pandoc class >> executable [
|
|
||||||
^ executable ifNil: [ self executableLocation ]
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #accessing }
|
|
||||||
Pandoc class >> executable: aFileReference [
|
|
||||||
executable := aFileReference
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #accessing }
|
|
||||||
Pandoc class >> executableLocation [
|
|
||||||
| location |
|
|
||||||
location := '/usr/bin/pandoc'.
|
|
||||||
location asFileReference exists
|
|
||||||
ifTrue: [ ^ location ]
|
|
||||||
ifFalse: [ self definePandocExecutable ]
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #utility }
|
|
||||||
Pandoc class >> extractImagesInUnixFor: aFileReference withFilter: aLuaFilter [
|
|
||||||
"I use Pandoc Lua scripting capabilities to extract al images links in aFileReference"
|
|
||||||
|
|
||||||
OSSUnixSubprocess new
|
|
||||||
command: 'pandoc';
|
|
||||||
arguments: {aFileReference fullName . '--lua-filter=',aLuaFilter fullName };
|
|
||||||
redirectStdout;
|
|
||||||
redirectStderr;
|
|
||||||
runAndWaitOnExitDo: [ :process :outString :errString |
|
|
||||||
process isSuccess
|
|
||||||
ifTrue: [
|
|
||||||
^ ((Soup fromString: outString) findAllTags: 'td') collect: [ :each | each next ] ]
|
|
||||||
ifFalse: [
|
|
||||||
"OSSUnixProcessExitStatus has a nice #printOn: "
|
|
||||||
Transcript show: 'Command exit with error status: ', process exitStatusInterpreter printString; cr.
|
|
||||||
Transcript show: 'Stderr contents: ', errString.
|
|
||||||
]
|
|
||||||
]
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #accessing }
|
|
||||||
Pandoc class >> htmlStringToMarkdown: aString [
|
|
||||||
|
|
||||||
OSSUnixSubprocess new
|
|
||||||
shellCommand: 'echo "', aString , '" | pandoc -f markdown -t html';
|
|
||||||
redirectStdout;
|
|
||||||
runAndWaitOnExitDo: [ :command :outString |
|
|
||||||
^ outString
|
|
||||||
].
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #converters }
|
|
||||||
Pandoc class >> htmlToMarkdown: inputFile [
|
|
||||||
|
|
||||||
| outputFile |
|
|
||||||
outputFile := FileLocator temp / 'body.md'.
|
|
||||||
outputFile ensureDelete.
|
|
||||||
outputFile ensureCreateFile.
|
|
||||||
OSSUnixSubprocess new
|
|
||||||
command: 'pandoc';
|
|
||||||
arguments: {'-f'. 'html'. '-t'. 'markdown'. '--atx-headers'. inputFile fullName.
|
|
||||||
'--output'. outputFile fullName };
|
|
||||||
redirectStdout;
|
|
||||||
redirectStderr;
|
|
||||||
runAndWaitOnExitDo: [ :process :outString :errString |
|
|
||||||
process isSuccess
|
|
||||||
ifTrue: [ ^ outputFile contents ]
|
|
||||||
ifFalse: [ ^inputFile contents ]
|
|
||||||
]
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #'as yet unclassified' }
|
|
||||||
Pandoc class >> listImagesFrom: aFileReference [
|
|
||||||
"I provide a list of all images contained in aFile."
|
|
||||||
|
|
||||||
| filter commandString outputString |
|
|
||||||
filter := FileLocator temp asFileReference / 'image-links.lua'.
|
|
||||||
filter exists
|
|
||||||
ifFalse: [ self downloadLuaFilters ].
|
|
||||||
commandString := 'pandoc ' , aFileReference fullName
|
|
||||||
, ' --lua-filter=' , filter fullName.
|
|
||||||
^ self extractImagesInUnixFor: aFileReference withFilter: filter
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #utility }
|
|
||||||
Pandoc class >> luaFilters [
|
|
||||||
"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.
|
|
||||||
|
|
||||||
For more information about Lua filters see:
|
|
||||||
|
|
||||||
https://pandoc.org/lua-filters.html
|
|
||||||
"
|
|
||||||
|
|
||||||
| filters |
|
|
||||||
filters := OrderedCollection new.
|
|
||||||
filters
|
|
||||||
add: 'http://mutabit.com/repos.fossil/dataweek/doc/tip/Artefactos/Scripts/image-links.lua'.
|
|
||||||
^ filters
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #converters }
|
|
||||||
Pandoc class >> markdownToHtml: inputFile [
|
|
||||||
|
|
||||||
(Smalltalk os isUnix or: [ Smalltalk os isMacOS ]) ifTrue: [ ^ self markdownToHtmlOnUnix: inputFile ].
|
|
||||||
Smalltalk os isWindows ifTrue: [ ^ self markdownToHtmlOnWindows: inputFile ].
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #converters }
|
|
||||||
Pandoc class >> markdownToHtmlOnUnix: inputFile [
|
|
||||||
|
|
||||||
| outputFile |
|
|
||||||
|
|
||||||
outputFile := inputFile parent / (inputFile basenameWithoutExtension , '.html').
|
|
||||||
outputFile ensureDelete.
|
|
||||||
outputFile ensureCreateFile.
|
|
||||||
GtSubprocessWithInMemoryOutput new
|
|
||||||
shellCommand: 'pandoc -f markdown+startnum+task_lists --standalone -t html ', inputFile fullName, ' --output ', outputFile fullName;
|
|
||||||
runAndWait;
|
|
||||||
stdout.
|
|
||||||
^ outputFile.
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #converters }
|
|
||||||
Pandoc class >> markdownToHtmlOnWindows: inputFile [
|
|
||||||
|
|
||||||
"ToDo: This command still doesn't receive any arguments."
|
|
||||||
^ (LibC resultOfCommand: 'pandoc ', inputFile fullName) correctAccentedCharacters.
|
|
||||||
]
|
|
@ -1,11 +0,0 @@
|
|||||||
Extension { #name : #Pandoc }
|
|
||||||
|
|
||||||
{ #category : #'*MiniDocs' }
|
|
||||||
Pandoc class >> convertString: aString from: inputFormat to: outputFormat [
|
|
||||||
OSSUnixSubprocess new
|
|
||||||
shellCommand: 'echo "', aString , '" | pandoc -f ', inputFormat,' -t ', outputFormat;
|
|
||||||
redirectStdout;
|
|
||||||
runAndWaitOnExitDo: [ :command :outString |
|
|
||||||
^ outString
|
|
||||||
].
|
|
||||||
]
|
|
139
src/MiniDocs/PubPub.class.st
Normal file
139
src/MiniDocs/PubPub.class.st
Normal file
@ -0,0 +1,139 @@
|
|||||||
|
Class {
|
||||||
|
#name : #PubPub,
|
||||||
|
#superclass : #Object,
|
||||||
|
#instVars : [
|
||||||
|
'address',
|
||||||
|
'tableOfContents',
|
||||||
|
'titles',
|
||||||
|
'folder',
|
||||||
|
'currentLanguage',
|
||||||
|
'languages'
|
||||||
|
],
|
||||||
|
#category : #'MiniDocs-Model'
|
||||||
|
}
|
||||||
|
|
||||||
|
{ #category : #accessing }
|
||||||
|
PubPub >> addTableOfContents: anOrderedDictionary [
|
||||||
|
self tableOfContents
|
||||||
|
at: (self currentLanguage) put: anOrderedDictionary;
|
||||||
|
yourself
|
||||||
|
]
|
||||||
|
|
||||||
|
{ #category : #accessing }
|
||||||
|
PubPub >> addTitle: aString [
|
||||||
|
self titles
|
||||||
|
at: (self currentLanguage) put: aString
|
||||||
|
]
|
||||||
|
|
||||||
|
{ #category : #accessing }
|
||||||
|
PubPub >> address [
|
||||||
|
^ address
|
||||||
|
]
|
||||||
|
|
||||||
|
{ #category : #accessing }
|
||||||
|
PubPub >> address: anUrl [
|
||||||
|
address := anUrl
|
||||||
|
]
|
||||||
|
|
||||||
|
{ #category : #accessing }
|
||||||
|
PubPub >> currentLanguage [
|
||||||
|
^ currentLanguage
|
||||||
|
]
|
||||||
|
|
||||||
|
{ #category : #accessing }
|
||||||
|
PubPub >> currentLanguage: twoLettersInISO639_1 [
|
||||||
|
currentLanguage := twoLettersInISO639_1
|
||||||
|
]
|
||||||
|
|
||||||
|
{ #category : #accessing }
|
||||||
|
PubPub >> defaultTitle [
|
||||||
|
^ self titles associations first value
|
||||||
|
]
|
||||||
|
|
||||||
|
{ #category : #accessing }
|
||||||
|
PubPub >> downloadContents [
|
||||||
|
| workingDirectory |
|
||||||
|
workingDirectory := self folder / self currentLanguage / 'book'.
|
||||||
|
self tableOfContents keysAndValuesDo: [ :name :chapterAddress | |currentFileName|
|
||||||
|
currentFileName := name, '--', chapterAddress, '.md'.
|
||||||
|
(workingDirectory / currentFileName) asFileReference ensureDelete.
|
||||||
|
(workingDirectory / 'markdown') asFileReference ensureDelete.
|
||||||
|
ZnClient new
|
||||||
|
get: self address, 'pub/', chapterAddress, '/download/markdown';
|
||||||
|
downloadTo: workingDirectory .
|
||||||
|
workingDirectory / 'markdown' renameTo: currentFileName
|
||||||
|
].
|
||||||
|
^ workingDirectory
|
||||||
|
]
|
||||||
|
|
||||||
|
{ #category : #accessing }
|
||||||
|
PubPub >> exportMarkdeepFiles [
|
||||||
|
| markdownFiles markdeepDocs |
|
||||||
|
markdownFiles := self languageFolder allChildren select: [:file |
|
||||||
|
file basename endsWith: '.md'
|
||||||
|
].
|
||||||
|
markdeepDocs := markdownFiles collect: [:file |
|
||||||
|
(Markdeep fromMarkdownFile:file)
|
||||||
|
].
|
||||||
|
markdeepDocs do: [:each |
|
||||||
|
each fromPubPubToMarkdeep exportAsFile
|
||||||
|
].
|
||||||
|
^ self languageFolder
|
||||||
|
]
|
||||||
|
|
||||||
|
{ #category : #accessing }
|
||||||
|
PubPub >> extractAllContentsRaw [
|
||||||
|
^ self frontPage xpath: '//div[@class="layout-pubs-block"]'
|
||||||
|
]
|
||||||
|
|
||||||
|
{ #category : #accessing }
|
||||||
|
PubPub >> extractRawTableOfContents [
|
||||||
|
^ self extractAllContentsRaw first xpath: '//div[contains(concat(" ",normalize-space(@class)," "), " pub-preview-component ")]'
|
||||||
|
]
|
||||||
|
|
||||||
|
{ #category : #accessing }
|
||||||
|
PubPub >> extractTableOfContents [
|
||||||
|
^ self extractRawTableOfContents collect: [:each |
|
||||||
|
PubPubContent fromXML: each
|
||||||
|
]
|
||||||
|
]
|
||||||
|
|
||||||
|
{ #category : #accessing }
|
||||||
|
PubPub >> folder [
|
||||||
|
^ folder ensureCreateDirectory
|
||||||
|
]
|
||||||
|
|
||||||
|
{ #category : #accessing }
|
||||||
|
PubPub >> folder: localDirectory [
|
||||||
|
folder := localDirectory
|
||||||
|
]
|
||||||
|
|
||||||
|
{ #category : #accessing }
|
||||||
|
PubPub >> frontPage [
|
||||||
|
"This should scrap contents of the book's front-page and translate them into Markdeep,
|
||||||
|
according to our templates."
|
||||||
|
^ (XMLHTMLParser on: (self address asUrl retrieveContents)) parseDocument
|
||||||
|
]
|
||||||
|
|
||||||
|
{ #category : #accessing }
|
||||||
|
PubPub >> languageFolder [
|
||||||
|
^ self folder / self currentLanguage
|
||||||
|
]
|
||||||
|
|
||||||
|
{ #category : #accessing }
|
||||||
|
PubPub >> printOn: aStream [
|
||||||
|
super printOn: aStream.
|
||||||
|
aStream
|
||||||
|
nextPutAll: '(',self defaultTitle, ' | ', self address, ' )'
|
||||||
|
]
|
||||||
|
|
||||||
|
{ #category : #accessing }
|
||||||
|
PubPub >> tableOfContents [
|
||||||
|
tableOfContents ifNil: [^ tableOfContents := Dictionary new].
|
||||||
|
^ tableOfContents at: self currentLanguage
|
||||||
|
]
|
||||||
|
|
||||||
|
{ #category : #accessing }
|
||||||
|
PubPub >> titles [
|
||||||
|
^ titles ifNil: [titles := OrderedDictionary new]
|
||||||
|
]
|
@ -5,9 +5,7 @@ Class {
|
|||||||
'title',
|
'title',
|
||||||
'language',
|
'language',
|
||||||
'url',
|
'url',
|
||||||
'thumbnail',
|
'thumbnail'
|
||||||
'work',
|
|
||||||
'contents'
|
|
||||||
],
|
],
|
||||||
#category : #'MiniDocs-Model'
|
#category : #'MiniDocs-Model'
|
||||||
}
|
}
|
||||||
@ -17,40 +15,6 @@ PubPubContent class >> fromXML: anXMLElement [
|
|||||||
^ self new fromXML: anXMLElement
|
^ self new fromXML: anXMLElement
|
||||||
]
|
]
|
||||||
|
|
||||||
{ #category : #accessing }
|
|
||||||
PubPubContent >> asMarkdeepFrontPageElement [
|
|
||||||
| response anchorName anchorLink markdeepFile |
|
|
||||||
response := '' writeStream.
|
|
||||||
anchorName := '[', self title,']'.
|
|
||||||
markdeepFile := './book/', self shortName,'--',self id,'.md.html'.
|
|
||||||
anchorLink := '(', markdeepFile,')'.
|
|
||||||
response
|
|
||||||
nextPutAll: '<big>', anchorName, anchorLink,'</big><br><br>';
|
|
||||||
nextPutAll: String lf.
|
|
||||||
self thumbnail ifNotNil: [ |image|
|
|
||||||
image := '
|
|
||||||
<img
|
|
||||||
src=', self thumbnail,
|
|
||||||
' width="55%"
|
|
||||||
style="width: 400px; height: 220px; object-fit: cover;"
|
|
||||||
/>'.
|
|
||||||
response nextPutAll: '<a href="',markdeepFile,'">', image, '</a>'
|
|
||||||
].
|
|
||||||
response
|
|
||||||
nextPutAll: String lf, String lf.
|
|
||||||
^ response contents
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #accessing }
|
|
||||||
PubPubContent >> contents: anObject [
|
|
||||||
contents := anObject
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #accessing }
|
|
||||||
PubPubContent >> fileName [
|
|
||||||
^ self shortName,'--', self id, '.md'
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #accessing }
|
{ #category : #accessing }
|
||||||
PubPubContent >> fromXML: aXMLElement [
|
PubPubContent >> fromXML: aXMLElement [
|
||||||
| image anchor|
|
| image anchor|
|
||||||
@ -73,23 +37,6 @@ PubPubContent >> id [
|
|||||||
^ (self url splitOn: $/) last
|
^ (self url splitOn: $/) last
|
||||||
]
|
]
|
||||||
|
|
||||||
{ #category : #'as yet unclassified' }
|
|
||||||
PubPubContent >> language: aString [
|
|
||||||
language := aString
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #accessing }
|
|
||||||
PubPubContent >> next [
|
|
||||||
^ self nextInstance
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #accessing }
|
|
||||||
PubPubContent >> previous [
|
|
||||||
| index |
|
|
||||||
index := self work tableOfContents detectIndex: [:pubContent | pubContent = self ] ifNone: [ ^ nil ].
|
|
||||||
^ self work tableOfContents at: index - 1.
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #accessing }
|
{ #category : #accessing }
|
||||||
PubPubContent >> printOn: aStream [
|
PubPubContent >> printOn: aStream [
|
||||||
super printOn: aStream.
|
super printOn: aStream.
|
||||||
@ -107,11 +54,6 @@ PubPubContent >> shortName [
|
|||||||
^ sanitized
|
^ sanitized
|
||||||
]
|
]
|
||||||
|
|
||||||
{ #category : #accessing }
|
|
||||||
PubPubContent >> thumbnail [
|
|
||||||
^ thumbnail
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #accessing }
|
{ #category : #accessing }
|
||||||
PubPubContent >> thumbnail: anURL [
|
PubPubContent >> thumbnail: anURL [
|
||||||
thumbnail := anURL
|
thumbnail := anURL
|
||||||
@ -136,13 +78,3 @@ PubPubContent >> url [
|
|||||||
PubPubContent >> url: anObject [
|
PubPubContent >> url: anObject [
|
||||||
url := anObject
|
url := anObject
|
||||||
]
|
]
|
||||||
|
|
||||||
{ #category : #accessing }
|
|
||||||
PubPubContent >> work [
|
|
||||||
^ work
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #accessing }
|
|
||||||
PubPubContent >> work: aPubPubWork [
|
|
||||||
work := aPubPubWork
|
|
||||||
]
|
|
||||||
|
@ -11,7 +11,7 @@ Class {
|
|||||||
'footnoteLabel',
|
'footnoteLabel',
|
||||||
'footnoteContent'
|
'footnoteContent'
|
||||||
],
|
],
|
||||||
#category : #'MiniDocs-Model'
|
#category : #MiniDocs
|
||||||
}
|
}
|
||||||
|
|
||||||
{ #category : #accessing }
|
{ #category : #accessing }
|
||||||
|
@ -1,240 +0,0 @@
|
|||||||
Class {
|
|
||||||
#name : #PubPubWork,
|
|
||||||
#superclass : #Object,
|
|
||||||
#instVars : [
|
|
||||||
'address',
|
|
||||||
'tableOfContents',
|
|
||||||
'titles',
|
|
||||||
'folder',
|
|
||||||
'currentLanguage',
|
|
||||||
'languages'
|
|
||||||
],
|
|
||||||
#category : #'MiniDocs-Model'
|
|
||||||
}
|
|
||||||
|
|
||||||
{ #category : #accessing }
|
|
||||||
PubPubWork >> addTableOfContents: anOrderedDictionary [
|
|
||||||
self tableOfContents
|
|
||||||
at: (self currentLanguage) put: anOrderedDictionary;
|
|
||||||
yourself
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #accessing }
|
|
||||||
PubPubWork >> addTitle: aString [
|
|
||||||
self titles
|
|
||||||
at: (self currentLanguage) put: aString
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #accessing }
|
|
||||||
PubPubWork >> address [
|
|
||||||
^ address
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #accessing }
|
|
||||||
PubPubWork >> address: anUrl [
|
|
||||||
address := anUrl
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #accessing }
|
|
||||||
PubPubWork >> bookishFolder [
|
|
||||||
^ { 'en' -> 'book'.
|
|
||||||
'es' -> 'libro'} asDictionary
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #accessing }
|
|
||||||
PubPubWork >> currentLanguage [
|
|
||||||
^ currentLanguage
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #accessing }
|
|
||||||
PubPubWork >> currentLanguage: twoLettersInISO639_1 [
|
|
||||||
currentLanguage := twoLettersInISO639_1
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #accessing }
|
|
||||||
PubPubWork >> defaultOptions [
|
|
||||||
^ { 'sourceCodeLink' -> true .
|
|
||||||
'commentsProvider' -> 'Hypothesis' } asDictionary
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #accessing }
|
|
||||||
PubPubWork >> defaultTitle [
|
|
||||||
^ self titles associations first value
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #accessing }
|
|
||||||
PubPubWork >> downloadContents [
|
|
||||||
| workingDirectory |
|
|
||||||
workingDirectory := self workingDirectory.
|
|
||||||
self tableOfContentsDictionary
|
|
||||||
keysAndValuesDo: [ :name :chapterAddress |
|
|
||||||
| currentFileName |
|
|
||||||
currentFileName := name , '--' , chapterAddress , '.md'.
|
|
||||||
(workingDirectory / currentFileName) asFileReference ensureDelete.
|
|
||||||
(workingDirectory / 'markdown') asFileReference ensureDelete.
|
|
||||||
ZnClient new
|
|
||||||
get: self address , 'pub/' , chapterAddress , '/download/markdown';
|
|
||||||
downloadTo: workingDirectory.
|
|
||||||
workingDirectory / 'markdown' renameTo: currentFileName ].
|
|
||||||
^ workingDirectory
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #accessing }
|
|
||||||
PubPubWork >> downloadContents2 [
|
|
||||||
| workingDirectory |
|
|
||||||
workingDirectory := self folder / self currentLanguage / 'book'.
|
|
||||||
self tableOfContentsDictionary keysAndValuesDo: [ :name :chapterAddress | |currentFileName|
|
|
||||||
currentFileName := name, '--', chapterAddress, '.md'.
|
|
||||||
(workingDirectory / currentFileName) asFileReference ensureDelete.
|
|
||||||
(workingDirectory / 'markdown') asFileReference ensureDelete.
|
|
||||||
ZnClient new
|
|
||||||
get: self address, 'pub/', chapterAddress, '/download/markdown';
|
|
||||||
downloadTo: workingDirectory .
|
|
||||||
workingDirectory / 'markdown' renameTo: currentFileName
|
|
||||||
].
|
|
||||||
^ workingDirectory
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #accessing }
|
|
||||||
PubPubWork >> exportToHTML [
|
|
||||||
self markdownFiles
|
|
||||||
do: [ :file | | doc |
|
|
||||||
doc := Markdown new fromFile: file.
|
|
||||||
doc exportAsHTML ].
|
|
||||||
^ self markdownFiles first parent
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #accessing }
|
|
||||||
PubPubWork >> exportToMarkdeep [
|
|
||||||
| markdeepDocs |
|
|
||||||
|
|
||||||
markdeepDocs := self markdownFiles
|
|
||||||
collect: [ :file | Markdeep fromMarkdownFile: file ].
|
|
||||||
markdeepDocs do: [ :each | each fromPubPubToMarkdeep exportAsFile ].
|
|
||||||
^ self languageFolder
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #accessing }
|
|
||||||
PubPubWork >> extractAllContentsRaw [
|
|
||||||
^ self frontPage xpath: '//div[@class="layout-pubs-block"]'
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #accessing }
|
|
||||||
PubPubWork >> extractRawTableOfContents [
|
|
||||||
^ self extractAllContentsRaw first xpath: '//div[contains(concat(" ",normalize-space(@class)," "), " pub-preview-component ")]'
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #accessing }
|
|
||||||
PubPubWork >> folder [
|
|
||||||
^ folder ensureCreateDirectory
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #accessing }
|
|
||||||
PubPubWork >> folder: localDirectory [
|
|
||||||
folder := localDirectory
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #accessing }
|
|
||||||
PubPubWork >> frontPage [
|
|
||||||
"This should scrap contents of the book's front-page and translate them into Markdeep,
|
|
||||||
according to our templates."
|
|
||||||
^ (XMLHTMLParser on: (self address asUrl retrieveContents)) parseDocument
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #accessing }
|
|
||||||
PubPubWork >> languageFolder [
|
|
||||||
^ self folder / self currentLanguage
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #accessing }
|
|
||||||
PubPubWork >> markdeepFrontPage [
|
|
||||||
| frontPage markdeepIndex |
|
|
||||||
frontPage := Markdeep new.
|
|
||||||
frontPage
|
|
||||||
title: self defaultTitle;
|
|
||||||
file: self languageFolder / 'frontPage.md.html'.
|
|
||||||
markdeepIndex := '' writeStream.
|
|
||||||
self tableOfContents do: [:pubPubContent|
|
|
||||||
markdeepIndex
|
|
||||||
nextPutAll: pubPubContent asMarkdeepFrontPageElement
|
|
||||||
].
|
|
||||||
frontPage body: markdeepIndex contents.
|
|
||||||
^ frontPage
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #accessing }
|
|
||||||
PubPubWork >> markdownFiles [
|
|
||||||
^ self languageFolder allChildren
|
|
||||||
select: [ :file | file basename endsWith: '.md' ]
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #accessing }
|
|
||||||
PubPubWork >> populateContents [
|
|
||||||
self tableOfContents isEmptyOrNil
|
|
||||||
ifTrue: [ self populateTableOfContents ].
|
|
||||||
self workingDirectory children ifEmpty: [self downloadContents].
|
|
||||||
self tableOfContents do: [:pubPubContent | | contentFile|
|
|
||||||
contentFile := self workingDirectory / pubPubContent fileName.
|
|
||||||
contentFile exists
|
|
||||||
ifTrue: [ pubPubContent contents: (Markdown new fromFile: contentFile) ]
|
|
||||||
]
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #accessing }
|
|
||||||
PubPubWork >> populateTableOfContents [
|
|
||||||
| contentsCollection |
|
|
||||||
contentsCollection := self extractRawTableOfContents collect: [:each |
|
|
||||||
(PubPubContent fromXML: each)
|
|
||||||
language: self currentLanguage;
|
|
||||||
work: self
|
|
||||||
].
|
|
||||||
self addTableOfContents: contentsCollection asOrderedCollection
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #accessing }
|
|
||||||
PubPubWork >> printOn: aStream [
|
|
||||||
super printOn: aStream.
|
|
||||||
aStream
|
|
||||||
nextPutAll: '(',self defaultTitle, ' | ', self address, ' )'
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #accessing }
|
|
||||||
PubPubWork >> tableOfContents [
|
|
||||||
tableOfContents ifNil: [ ^ tableOfContents := Dictionary new].
|
|
||||||
^ tableOfContents at: self currentLanguage
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #accessing }
|
|
||||||
PubPubWork >> tableOfContents: anObject [
|
|
||||||
tableOfContents := anObject
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #accessing }
|
|
||||||
PubPubWork >> tableOfContentsDictionary [
|
|
||||||
| response |
|
|
||||||
response := OrderedDictionary new.
|
|
||||||
self tableOfContents do: [:content |
|
|
||||||
response
|
|
||||||
at: content shortName put: content id
|
|
||||||
].
|
|
||||||
^ response
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #accessing }
|
|
||||||
PubPubWork >> titles [
|
|
||||||
^ titles ifNil: [titles := OrderedDictionary new]
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #accessing }
|
|
||||||
PubPubWork >> viewContentsFor: aView [
|
|
||||||
<gtView>
|
|
||||||
^ aView list
|
|
||||||
title: 'Contents';
|
|
||||||
priority: 10;
|
|
||||||
items: [ self tableOfContents ]
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #accessing }
|
|
||||||
PubPubWork >> workingDirectory [
|
|
||||||
^ self folder / self currentLanguage / (self bookishFolder at: self currentLanguage)
|
|
||||||
]
|
|
@ -4,7 +4,7 @@ Extension { #name : #String }
|
|||||||
String >> accentedCharactersCorrection [
|
String >> accentedCharactersCorrection [
|
||||||
| modified corrections |
|
| modified corrections |
|
||||||
corrections := {
|
corrections := {
|
||||||
'ó' -> 'ó' . 'Ã' -> 'Ó' . 'ú' -> 'ú' . 'ñ' -> 'ñ' . 'Ã' -> 'Ñ' .
|
'ó' -> 'ó' . 'ú' -> 'ú' . 'ñ' -> 'ñ' .
|
||||||
'Ã' -> 'í' . 'á' -> 'á' . 'é' -> 'é' . 'â' -> $' asString} asDictionary.
|
'Ã' -> 'í' . 'á' -> 'á' . 'é' -> 'é' . 'â' -> $' asString} asDictionary.
|
||||||
modified := self copy.
|
modified := self copy.
|
||||||
corrections keysAndValuesDo: [ :k :v |
|
corrections keysAndValuesDo: [ :k :v |
|
||||||
@ -13,41 +13,6 @@ String >> accentedCharactersCorrection [
|
|||||||
^ modified
|
^ modified
|
||||||
]
|
]
|
||||||
|
|
||||||
{ #category : #'*MiniDocs' }
|
|
||||||
String >> admonitionBorderLines [
|
|
||||||
| response |
|
|
||||||
response := OrderedDictionary new.
|
|
||||||
self lines doWithIndex: [:line :index |
|
|
||||||
(self admonitionBorders includes: line trimBoth)
|
|
||||||
ifTrue: [ response at: index put: line trimBoth ]
|
|
||||||
].
|
|
||||||
^ response
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #'*MiniDocs' }
|
|
||||||
String >> admonitionBorders [
|
|
||||||
"For the moment I only work with the admonition starting border
|
|
||||||
as adding the closing one would imply to redo the #markdownSplitted
|
|
||||||
method implementing a proper parser, which, ATM is overkill."
|
|
||||||
| response |
|
|
||||||
response := #('info' 'success' 'warning' 'danger') collect: [ :each | ':::', each ].
|
|
||||||
^ response "copyWith: ':::'"
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #'*MiniDocs' }
|
|
||||||
String >> admonitionEndingPosition [
|
|
||||||
| response |
|
|
||||||
response := 0.
|
|
||||||
self startsWithMarkdownAdmonition ifFalse: [ ^ response ].
|
|
||||||
self lines do: [:line |
|
|
||||||
response > 0 ifTrue: [ response := response + 1 ].
|
|
||||||
(line trimBoth = ':::')
|
|
||||||
ifFalse: [ response := response + line size ]
|
|
||||||
ifTrue: [ ^ response := response + line size. ]
|
|
||||||
].
|
|
||||||
^ response
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #'*MiniDocs' }
|
{ #category : #'*MiniDocs' }
|
||||||
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'."
|
||||||
@ -55,119 +20,6 @@ String >> asDashedLowercase [
|
|||||||
^ '-' join: (self substrings collect: [:each | each asLowercase ])
|
^ '-' join: (self substrings collect: [:each | each asLowercase ])
|
||||||
]
|
]
|
||||||
|
|
||||||
{ #category : #'*MiniDocs' }
|
|
||||||
String >> asInteger [
|
|
||||||
"Return the integer present in the receiver, or nil. In case of float, returns the integer part."
|
|
||||||
"'1' asInteger >>> 1"
|
|
||||||
"'-1' asInteger >>> -1"
|
|
||||||
"'10' asInteger >>> 10"
|
|
||||||
"'a' asInteger >>> nil"
|
|
||||||
"'1.234' asInteger >>> 1"
|
|
||||||
^ (self copyWithoutAll: '_') asSignedInteger
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #'*MiniDocs' }
|
|
||||||
String >> contentsWithoutYAMLMetadata [
|
|
||||||
| newContents |
|
|
||||||
self detectYAMLMetadata ifFalse: [ ^ self ].
|
|
||||||
newContents := '' writeStream.
|
|
||||||
(self lines copyFrom: self yamlMetadataClosingLineNumber + 2 to: self lines size) do: [ :line |
|
|
||||||
newContents nextPutAll: line; cr ].
|
|
||||||
^ newContents contents.
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #'*MiniDocs' }
|
|
||||||
String >> deleteYAMLMetadata [
|
|
||||||
| newContents |
|
|
||||||
self detectYAMLMetadata ifFalse: [ ^ self ].
|
|
||||||
newContents := '' writeStream.
|
|
||||||
(self lines copyFrom: self yamlMetadataClosingLineNumber + 1 to: self lines size) do: [ :line |
|
|
||||||
newContents nextPutAll: line; lf;lf ].
|
|
||||||
^ newContents contents.
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #'*MiniDocs' }
|
|
||||||
String >> demoteMarkdownHeaders [
|
|
||||||
| response |
|
|
||||||
response := self contents lines.
|
|
||||||
self markdownHeaders associations allButFirstDo: [ :assoc |
|
|
||||||
response at: assoc key put: '#', assoc value ].
|
|
||||||
^ response asStringWithCr withInternetLineEndings
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #'*MiniDocs' }
|
|
||||||
String >> detectYAMLMetadata [
|
|
||||||
| lines |
|
|
||||||
lines := self lines.
|
|
||||||
^ self startsWithYAMLMetadataDelimiter
|
|
||||||
and: [ lines allButFirst
|
|
||||||
detect: [ :currentLine | currentLine beginsWith: self class yamlMetadataDelimiter ]
|
|
||||||
ifFound: [ ^ true ] ifNone: [ ^ false ] ]
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #'*MiniDocs' }
|
|
||||||
String >> indentedWithExtraSpaces: spaceNumber [
|
|
||||||
| response indent |
|
|
||||||
response := '' writeStream.
|
|
||||||
indent := String new.
|
|
||||||
spaceNumber timesRepeat: [ indent := indent, ' ' ].
|
|
||||||
self lines do: [:line | response nextPutAll: indent, line, String lf ].
|
|
||||||
^ response contents
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #'*MiniDocs' }
|
|
||||||
String >> markdownHeaders [
|
|
||||||
| response headers |
|
|
||||||
headers := (LeTextSnippet string: self contents) ast // #LeHeaderNode collect: [ :each | each headerFullName asString ].
|
|
||||||
response := OrderedDictionary new.
|
|
||||||
self lines doWithIndex: [:line :index |
|
|
||||||
(line beginsWithAnyOf: headers)
|
|
||||||
ifTrue: [ response at: index put: line ]
|
|
||||||
].
|
|
||||||
^ response
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #'*MiniDocs' }
|
|
||||||
String >> markdownSplitLines [
|
|
||||||
"I'm useful for conversions between the HedgeDoc Markdown variant and Lepiter page snippets.
|
|
||||||
I provide broad places to where semantic breaks should be located in a page,
|
|
||||||
depending on headers or admonitions to create pages snippets with similar divisions.
|
|
||||||
Further page splits should be provided manually by the document author."
|
|
||||||
| response |
|
|
||||||
response := OrderedDictionary new.
|
|
||||||
response := response
|
|
||||||
addAll: self markdownHeaders;
|
|
||||||
addAll: self admonitionBorderLines;
|
|
||||||
yourself.
|
|
||||||
^ (response associations sorted: [ :x :y | x key < y key ]) asOrderedDictionary
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #'*MiniDocs' }
|
|
||||||
String >> markdownSplitted [
|
|
||||||
| response lastPart |
|
|
||||||
self markdownSplitLines ifEmpty: [ ^ self ].
|
|
||||||
response := OrderedCollection new.
|
|
||||||
self markdownSplitLines keys allButLast doWithIndex: [:key :index | | nextLine part |
|
|
||||||
nextLine := (self markdownSplitLines keys at: index + 1) - 1.
|
|
||||||
part := self lines copyFrom: key to: nextLine.
|
|
||||||
response add: part.
|
|
||||||
].
|
|
||||||
lastPart := self lines
|
|
||||||
copyFrom: self markdownSplitLines keys last
|
|
||||||
to: self lines size.
|
|
||||||
response add: lastPart.
|
|
||||||
^ response
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #'*MiniDocs' }
|
|
||||||
String >> promoteMarkdownHeaders [
|
|
||||||
| response |
|
|
||||||
response := self contents lines.
|
|
||||||
self markdownHeaders associationsDo: [ :assoc |
|
|
||||||
response at: assoc key put: assoc value allButFirst ].
|
|
||||||
^ response asStringWithCr withInternetLineEndings
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #'*MiniDocs' }
|
{ #category : #'*MiniDocs' }
|
||||||
String >> romanizeAccents [
|
String >> romanizeAccents [
|
||||||
| modified corrections |
|
| modified corrections |
|
||||||
@ -180,61 +32,3 @@ String >> romanizeAccents [
|
|||||||
].
|
].
|
||||||
^ modified
|
^ modified
|
||||||
]
|
]
|
||||||
|
|
||||||
{ #category : #'*MiniDocs' }
|
|
||||||
String >> startsWithMarkdownAdmonition [
|
|
||||||
self lines ifEmpty: [ ^ false ].
|
|
||||||
^ self admonitionBorders includes: self lines first trimBoth
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #'*MiniDocs' }
|
|
||||||
String >> startsWithYAMLMetadataDelimiter [
|
|
||||||
self lines ifEmpty: [^false].
|
|
||||||
^ self lines first beginsWith: self class yamlMetadataDelimiter
|
|
||||||
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #'*MiniDocs' }
|
|
||||||
String >> withoutXMLTagDelimiters [
|
|
||||||
^ self copyWithoutAll: #($< $>)
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #'*MiniDocs' }
|
|
||||||
String >> yamlMetadataClosingLineNumber [
|
|
||||||
"I return the line where the closing of the YAML metadata occurs or 0 if no closing is found."
|
|
||||||
self startsWithYAMLMetadataDelimiter ifFalse: [ ^ self ].
|
|
||||||
self lines allButFirst doWithIndex: [ :currentLine :i |
|
|
||||||
(currentLine beginsWith: self class yamlMetadataDelimiter) ifTrue: [ ^ i + 1 ]]
|
|
||||||
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #'*MiniDocs' }
|
|
||||||
String class >> yamlMetadataDelimiter [
|
|
||||||
^ '---'
|
|
||||||
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #'*MiniDocs' }
|
|
||||||
String >> yamlMetadataString [
|
|
||||||
| output yamlLines |
|
|
||||||
self detectYAMLMetadata ifFalse: [ ^nil ].
|
|
||||||
self lines ifEmpty: [ ^nil ].
|
|
||||||
yamlLines := self lines copyFrom: 2 to: self yamlMetadataClosingLineNumber - 1.
|
|
||||||
output := '' writeStream.
|
|
||||||
yamlLines do: [ :line |
|
|
||||||
output
|
|
||||||
nextPutAll: line;
|
|
||||||
nextPut: Character lf. ].
|
|
||||||
^ output contents
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #'*MiniDocs' }
|
|
||||||
String >> yamlMetadataStringWithDelimiters [
|
|
||||||
| output |
|
|
||||||
self yamlMetadataString ifNil: [ ^ nil ].
|
|
||||||
output := String new writeStream.
|
|
||||||
output nextPutAll: self class yamlMetadataDelimiter; cr.
|
|
||||||
output nextPutAll: self yamlMetadataString.
|
|
||||||
output nextPutAll: self class yamlMetadataDelimiter; cr.
|
|
||||||
^ output contents.
|
|
||||||
]
|
|
||||||
|
@ -1,9 +0,0 @@
|
|||||||
Extension { #name : #XMLDocument }
|
|
||||||
|
|
||||||
{ #category : #'*MiniDocs' }
|
|
||||||
XMLDocument >> detectMarkdeepTitle [
|
|
||||||
| titleLine |
|
|
||||||
titleLine := (self nodesCollect: [:node | node contentString ]) first lines
|
|
||||||
detect: [:line | line includesSubstring: ' **'] ifNone: ['Untitled'].
|
|
||||||
^ titleLine trimmed trimBoth: [:char | char = $* ]
|
|
||||||
]
|
|
@ -1,53 +0,0 @@
|
|||||||
Extension { #name : #XMLElement }
|
|
||||||
|
|
||||||
{ #category : #'*MiniDocs' }
|
|
||||||
XMLElement >> asSnippetDictionary [
|
|
||||||
| response |
|
|
||||||
response := STON fromString: (self attributes at: 'st-data').
|
|
||||||
response at: 'className' put: (self attributes at: 'st-class').
|
|
||||||
response at: 'content' put: self sanitizedContent.
|
|
||||||
^ response
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #'*MiniDocs' }
|
|
||||||
XMLElement >> extractMarkdownImageLinkData [
|
|
||||||
| linkParserNodes sanitizedText linkParser |
|
|
||||||
linkParser := (PPCommonMarkBlockParser parse: (self contentString trimBoth: [:each | each = Character lf]) allButFirst)
|
|
||||||
accept: CMBlockVisitor new.
|
|
||||||
linkParserNodes := linkParser children first children.
|
|
||||||
linkParserNodes size = 1
|
|
||||||
ifTrue: [ sanitizedText := linkParserNodes first label text ]
|
|
||||||
ifFalse: [ sanitizedText := '' writeStream.
|
|
||||||
linkParserNodes allButLast
|
|
||||||
do: [ :each |
|
|
||||||
each className = 'PPCMText'
|
|
||||||
ifTrue: [ sanitizedText nextPutAll: each text allButFirst ].
|
|
||||||
each className = 'PPCMLink'
|
|
||||||
ifTrue: [ sanitizedText nextPutAll: each printString ] ].
|
|
||||||
sanitizedText := sanitizedText contents ].
|
|
||||||
^ {sanitizedText . self contentString }
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #'*MiniDocs' }
|
|
||||||
XMLElement >> sanitizedContent [
|
|
||||||
| className sanitizedText |
|
|
||||||
className := self attributes at: 'st-class'.
|
|
||||||
className = 'LeTextSnippet'
|
|
||||||
ifTrue: [ sanitizedText := self contentString.
|
|
||||||
sanitizedText := sanitizedText allButFirst.
|
|
||||||
sanitizedText := sanitizedText allButLast ].
|
|
||||||
className = 'LePharoSnippet'
|
|
||||||
ifTrue: [ | joinedText |
|
|
||||||
sanitizedText := self contentString lines.
|
|
||||||
sanitizedText := sanitizedText copyFrom: 4 to: sanitizedText size - 2.
|
|
||||||
joinedText := '' writeStream.
|
|
||||||
sanitizedText
|
|
||||||
do: [ :line |
|
|
||||||
joinedText
|
|
||||||
nextPutAll: line;
|
|
||||||
nextPut: Character lf ].
|
|
||||||
sanitizedText := joinedText contents allButLast ].
|
|
||||||
className = 'LePictureSnippet'
|
|
||||||
ifTrue: [ sanitizedText := self extractMarkdownImageLinkData ].
|
|
||||||
^ sanitizedText
|
|
||||||
]
|
|
29
src/MiniDocs/YQ.class.st
Normal file
29
src/MiniDocs/YQ.class.st
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
"
|
||||||
|
The `External` tag is related on its dependency on other programming languages and frameworks,
|
||||||
|
though the dependency should be loaded by just loading a small binary with no dependencies.
|
||||||
|
"
|
||||||
|
Class {
|
||||||
|
#name : #YQ,
|
||||||
|
#superclass : #Object,
|
||||||
|
#category : #'MiniDocs-External'
|
||||||
|
}
|
||||||
|
|
||||||
|
{ #category : #accessing }
|
||||||
|
YQ class >> binaryDownloadLinkFor: operativeSystem on: processor [
|
||||||
|
| binaryName binaryDownloadData |
|
||||||
|
binaryName := 'yq_', operativeSystem , '_', processor.
|
||||||
|
binaryDownloadData := ((self lastReleaseData at: 'assets')
|
||||||
|
select: [:each | (each at: 'name') beginsWith: binaryName ]) first.
|
||||||
|
^ binaryDownloadData at: 'browser_download_url'
|
||||||
|
]
|
||||||
|
|
||||||
|
{ #category : #accessing }
|
||||||
|
YQ class >> install [
|
||||||
|
^ self lastReleaseData
|
||||||
|
]
|
||||||
|
|
||||||
|
{ #category : #accessing }
|
||||||
|
YQ class >> lastReleaseData [
|
||||||
|
^ (STONJSON
|
||||||
|
fromString: 'https://api.github.com/repos/mikefarah/yq/releases' asUrl retrieveContents) first
|
||||||
|
]
|
@ -1,10 +0,0 @@
|
|||||||
Extension { #name : #ZnConstants }
|
|
||||||
|
|
||||||
{ #category : #'*MiniDocs' }
|
|
||||||
ZnConstants class >> maximumLineLength [
|
|
||||||
"Return the maximum line length to accept.
|
|
||||||
Used by ZnLineReader and thus for reading request/status lines as well as headers.
|
|
||||||
This helps to protect us from malicious content."
|
|
||||||
|
|
||||||
^ 5096 "8192"
|
|
||||||
]
|
|
@ -23,8 +23,3 @@ PPCMBlockQuote >> initialize [
|
|||||||
PPCMBlockQuote >> isBlockLevel [
|
PPCMBlockQuote >> isBlockLevel [
|
||||||
^ true
|
^ true
|
||||||
]
|
]
|
||||||
|
|
||||||
{ #category : #accessing }
|
|
||||||
PPCMBlockQuote >> viewBody [
|
|
||||||
^ (self className ,' ', self text) asRopedText.
|
|
||||||
]
|
|
||||||
|
@ -39,8 +39,9 @@ PPCMLink >> printOn: aStream [
|
|||||||
super initialize.
|
super initialize.
|
||||||
^ aStream
|
^ aStream
|
||||||
nextPutAll:
|
nextPutAll:
|
||||||
'[',self label text,']',
|
self label text,
|
||||||
'(',self destination,')'
|
' -> ',
|
||||||
|
self destination
|
||||||
]
|
]
|
||||||
|
|
||||||
{ #category : #accessing }
|
{ #category : #accessing }
|
||||||
|
Loading…
Reference in New Issue
Block a user