This commit is contained in:
ruidajo 2024-03-20 17:41:37 -05:00
commit 655ee2e935
10 changed files with 314 additions and 69 deletions

View File

@ -13,19 +13,17 @@ BaselineOfMiniDocs >> baseline: spec [
"Dependencies"
spec
baseline: 'Mustache' with: [ spec repository: 'github://noha/mustache' ];
baseline: 'Temple' with: [ spec repository: 'github://astares/Pharo-Temple/src' ];
baseline: 'Teapot' with: [ spec repository: 'github://zeroflag/Teapot/source' ];
baseline: 'Tealight' with: [ spec repository: 'github://astares/Tealight:main/src' ];
baseline: 'LepiterBuildingBlocs' with: [spec repository: 'github://botwhytho/LepiterBuildingBlocs:main/src'];
baseline: 'PetitParser' with: [
spec
loads: #('Minimal' 'Core' 'Tests' 'Islands');
repository: 'github://moosetechnology/PetitParser:v3.x.x/src'
].
baseline: 'PetitParser' with: [ spec repository: 'github://moosetechnology/PetitParser:v3.x.x/src' ].
"self fossil: spec."
self xmlParserHTML: spec.
"Packages"
spec
package: 'PetitMarkdown' with: [ spec requires: #('PetitParser')];
package: 'MiniDocs' with: [ spec requires: #('Mustache' 'Tealight' 'PetitMarkdown')].
package: 'MiniDocs' with: [ spec requires: #('Mustache' 'Temple' 'Teapot' 'Tealight' 'PetitMarkdown')].
"Groups"

View File

@ -8,16 +8,16 @@ Class {
}
{ #category : #accessing }
HedgeDocGrammar >> start [
| any |
any := #any asPParser.
^ (self yamlMetadata / any starLazy), youtubeEmbeddedLink
HedgeDocGrammar >> metadataAsYAML [
"I parse the header of the hedgedoc document for YAML metadata."
^ '---' asPParser token, #any asPParser starLazy token, '---' asPParser token
]
{ #category : #accessing }
HedgeDocGrammar >> yamlMetadata [
"I parse the header of the hedgedoc document for YAML metadata."
^ '---' asPParser token, #any asPParser starLazy token, '---' asPParser token
HedgeDocGrammar >> start [
| any |
any := #any asPParser.
^ (self metadataAsYAML / any starLazy), youtubeEmbeddedLink
]
{ #category : #accessing }

View File

@ -0,0 +1,33 @@
Class {
#name : #Logseq,
#superclass : #Object,
#instVars : [
'folder'
],
#category : #MiniDocs
}
{ #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'
]

View File

@ -30,9 +30,17 @@ Markdeep class >> fromPubPubTOC: orderedDictionary folder: folder index: ordina
^ self new fromMarkdownFile: testFile.
]
{ #category : #accessing }
Markdeep >> asMarkdown [
^ Markdown new
metadata: self metadata;
body: self body;
file: self markdownFile
]
{ #category : #'instance creation' }
Markdeep >> authors [
self metadata at: 'authors' ifPresent: [:k | ^ '**', k, '**' ].
self metadata at: 'authors' ifPresent: [:k | ^ '**', k, '**' ] ifAbsentPut: [ Dictionary new ].
^ ''.
]
@ -57,6 +65,11 @@ Markdeep >> bodyReplaceAll: original with: replacement [
self body: (self body copyReplaceAll: original with: replacement)
]
{ #category : #accessing }
Markdeep >> cleanMetadata [
metadata := nil
]
{ #category : #accessing }
Markdeep >> commentPubPubDelimiters [
| commented openners |
@ -158,6 +171,63 @@ Markdeep >> converPubPubFootnoteBetween: footnote and: nextFootnote in: footnote
^ 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
@ -199,8 +269,11 @@ Markdeep >> gtTextFor: aView [
{ #category : #accessing }
Markdeep >> head [
^ head ifNil: [ head := OrderedCollection new.
head add: self fontAwesomeHeader; yourself ]
^ head ifNil: [
head := OrderedCollection new.
head add: self fontAwesomeHeader; yourself.
].
]
{ #category : #accessing }
@ -261,7 +334,10 @@ Markdeep >> markdownFile: aFileReference [
{ #category : #'instance creation' }
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 }
@ -315,7 +391,7 @@ Markdeep >> processMarkdownFor: aFileReference [
| markdownContent |
self file: aFileReference, 'html'.
markdownContent := Markdown fromFile: aFileReference.
self metadata: markdownContent yamlMetadata.
self metadata: markdownContent metadataAsYAML.
self body: (markdownContent commentYAMLMetadata contents).
]

View File

@ -62,7 +62,11 @@ Markdown >> containsYAMLMetadataClosing [
{ #category : #accessing }
Markdown >> contents [
^ body
| response |
response := WriteStream on: ''.
response
nextPutAll: self body.
^ response contents
]
{ #category : #accessing }
@ -103,6 +107,7 @@ Markdown >> detectYAMLMetadata [
{ #category : #accessing }
Markdown >> documentTree [
| parser|
self contents ifNil: [^ nil].
parser := PPCommonMarkBlockParser new parse: self contents.
^ parser accept: CMBlockVisitor new
]
@ -120,7 +125,12 @@ Markdown >> exportAsFileOn: aFileReference [
aFileReference ensureDelete.
aFileReference exists ifFalse: [ aFileReference ensureCreateFile ].
aFileReference writeStreamDo: [ :stream |
stream nextPutAll: self contents ].
stream nextPutAll: self contents withInternetLineEndings ].
]
{ #category : #accessing }
Markdown >> exportAsHTML [
^ Pandoc markdownToHtml: self file
]
{ #category : #operation }
@ -167,6 +177,7 @@ Markdown >> file: aFileReference [
Markdown >> fromFile: aFileReference [
self contents: aFileReference contents.
self file: aFileReference.
self populateMetadata
]
{ #category : #'instance creation' }
@ -186,6 +197,7 @@ Markdown >> gtTextFor: aView [
{ #category : #utilities }
Markdown >> lines [
self file ifNotNil: [^ self file contents lines ].
^ self contents lines.
]
@ -202,6 +214,12 @@ Markdown >> metadata: rawMeta [
metadata := rawMeta
]
{ #category : #accessing }
Markdown >> metadataAsYAML [
self metadata isEmptyOrNil ifTrue: [ ^ '' ].
^ YQ jsonToYaml: self metadata
]
{ #category : #persistence }
Markdown >> notifyExportAsFileOn: aFileReference [
self exportAsFileOn: aFileReference.
@ -209,14 +227,14 @@ Markdown >> notifyExportAsFileOn: aFileReference [
^ aFileReference
]
{ #category : #accessing }
Markdown >> options [
^ self metadata at: 'options' ifAbsentPut: [ self defaultOptions]
]
{ #category : #accessing }
Markdown >> populateMetadata [
| 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
self metadata: (YAML2JSON fromString: self yamlMetadataString)
]
{ #category : #accessing }
@ -233,11 +251,6 @@ Markdown >> startsWithYAMLMetadataDelimiter [
]
{ #category : #accessing }
Markdown >> yamlMetadata [
^ MiniDocs yamlToJson: self yamlMetadataString
]
{ #category : #utilities }
Markdown >> yamlMetadataClosingLineNumber [
"I return the line where the closing of the YAML metadata occurs or 0 if no closing is found."

View File

@ -122,12 +122,13 @@ Pandoc class >> markdownToHtml: inputFile [
Pandoc class >> markdownToHtmlOnUnix: inputFile [
| outputFile |
outputFile := FileLocator temp / (inputFile basenameWithoutExtension , '.html').
outputFile := inputFile parent / (inputFile basenameWithoutExtension , '.html').
outputFile ensureDelete.
outputFile ensureCreateFile.
OSSUnixSubprocess new
command: 'pandoc';
arguments: {'-f'. 'markdown+startnum+task_lists'. '-t'. 'html'. inputFile fullName.
arguments: {'-f'. 'markdown+startnum+task_lists'. '--standalone'. '-t'. 'html'. inputFile fullName.
'--output'. outputFile fullName };
redirectStdout;
redirectStderr;

View File

@ -5,7 +5,9 @@ Class {
'title',
'language',
'url',
'thumbnail'
'thumbnail',
'work',
'contents'
],
#category : #'MiniDocs-Model'
}
@ -39,6 +41,16 @@ PubPubContent >> asMarkdeepFrontPageElement [
^ response contents
]
{ #category : #accessing }
PubPubContent >> contents: anObject [
contents := anObject
]
{ #category : #accessing }
PubPubContent >> fileName [
^ self shortName,'--', self id, '.md'
]
{ #category : #accessing }
PubPubContent >> fromXML: aXMLElement [
| image anchor|
@ -66,6 +78,18 @@ 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 }
PubPubContent >> printOn: aStream [
super printOn: aStream.
@ -112,3 +136,13 @@ PubPubContent >> url [
PubPubContent >> url: anObject [
url := anObject
]
{ #category : #accessing }
PubPubContent >> work [
^ work
]
{ #category : #accessing }
PubPubContent >> work: aPubPubWork [
work := aPubPubWork
]

View File

@ -1,5 +1,5 @@
Class {
#name : #PubPub,
#name : #PubPubWork,
#superclass : #Object,
#instVars : [
'address',
@ -13,45 +13,74 @@ Class {
}
{ #category : #accessing }
PubPub >> addTableOfContents: anOrderedDictionary [
PubPubWork >> addTableOfContents: anOrderedDictionary [
self tableOfContents
at: (self currentLanguage) put: anOrderedDictionary;
yourself
]
{ #category : #accessing }
PubPub >> addTitle: aString [
PubPubWork >> addTitle: aString [
self titles
at: (self currentLanguage) put: aString
]
{ #category : #accessing }
PubPub >> address [
PubPubWork >> address [
^ address
]
{ #category : #accessing }
PubPub >> address: anUrl [
PubPubWork >> address: anUrl [
address := anUrl
]
{ #category : #accessing }
PubPub >> currentLanguage [
PubPubWork >> bookishFolder [
^ { 'en' -> 'book'.
'es' -> 'libro'} asDictionary
]
{ #category : #accessing }
PubPubWork >> currentLanguage [
^ currentLanguage
]
{ #category : #accessing }
PubPub >> currentLanguage: twoLettersInISO639_1 [
PubPubWork >> currentLanguage: twoLettersInISO639_1 [
currentLanguage := twoLettersInISO639_1
]
{ #category : #accessing }
PubPub >> defaultTitle [
PubPubWork >> defaultOptions [
^ { 'sourceCodeLink' -> true .
'commentsProvider' -> 'Hypothesis' } asDictionary
]
{ #category : #accessing }
PubPubWork >> defaultTitle [
^ self titles associations first value
]
{ #category : #accessing }
PubPub >> downloadContents [
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|
@ -67,54 +96,58 @@ PubPub >> downloadContents [
]
{ #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
].
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 }
PubPub >> extractAllContentsRaw [
PubPubWork >> extractAllContentsRaw [
^ self frontPage xpath: '//div[@class="layout-pubs-block"]'
]
{ #category : #accessing }
PubPub >> extractRawTableOfContents [
PubPubWork >> extractRawTableOfContents [
^ self extractAllContentsRaw first xpath: '//div[contains(concat(" ",normalize-space(@class)," "), " pub-preview-component ")]'
]
{ #category : #accessing }
PubPub >> folder [
PubPubWork >> folder [
^ folder ensureCreateDirectory
]
{ #category : #accessing }
PubPub >> folder: localDirectory [
PubPubWork >> folder: localDirectory [
folder := localDirectory
]
{ #category : #accessing }
PubPub >> frontPage [
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 }
PubPub >> languageFolder [
PubPubWork >> languageFolder [
^ self folder / self currentLanguage
]
{ #category : #accessing }
PubPub >> markdeepFrontPage [
PubPubWork >> markdeepFrontPage [
| frontPage markdeepIndex |
frontPage := Markdeep new.
frontPage
@ -130,35 +163,54 @@ PubPub >> markdeepFrontPage [
]
{ #category : #accessing }
PubPub >> populateTableOfContents [
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
language: self currentLanguage;
work: self
].
self addTableOfContents: contentsCollection asOrderedCollection
]
{ #category : #accessing }
PubPub >> printOn: aStream [
PubPubWork >> printOn: aStream [
super printOn: aStream.
aStream
nextPutAll: '(',self defaultTitle, ' | ', self address, ' )'
]
{ #category : #accessing }
PubPub >> tableOfContents [
PubPubWork >> tableOfContents [
tableOfContents ifNil: [ ^ tableOfContents := Dictionary new].
^ tableOfContents at: self currentLanguage
]
{ #category : #accessing }
PubPub >> tableOfContents: anObject [
PubPubWork >> tableOfContents: anObject [
tableOfContents := anObject
]
{ #category : #accessing }
PubPub >> tableOfContentsDictionary [
PubPubWork >> tableOfContentsDictionary [
| response |
response := OrderedDictionary new.
self tableOfContents do: [:content |
@ -169,6 +221,20 @@ PubPub >> tableOfContentsDictionary [
]
{ #category : #accessing }
PubPub >> titles [
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)
]

View File

@ -17,11 +17,30 @@ YQ class >> binaryDownloadLinkFor: operativeSystem on: processor [
^ binaryDownloadData at: 'browser_download_url'
]
{ #category : #accessing }
YQ class >> binaryFile [
"Starting with location on Arch Linux and its derivates. Multidistro and multiOS support should be added."
^ FileLocator root / 'usr/bin/yq'
]
{ #category : #accessing }
YQ class >> install [
^ self lastReleaseData
]
{ #category : #accessing }
YQ class >> jsonToYaml: aDictionary [
| jsonFile |
self binaryFile exists ifFalse: [ YQ install].
jsonFile := MarkupFile exportAsFileOn: FileLocator temp / 'data.json' containing: aDictionary.
OSSUnixSubprocess new
shellCommand: 'cat ', jsonFile fullName,' | yq -y';
redirectStdout;
runAndWaitOnExitDo: [ :command :outString |
^ outString
].
]
{ #category : #accessing }
YQ class >> lastReleaseData [
^ (STONJSON

View File

@ -23,3 +23,8 @@ PPCMBlockQuote >> initialize [
PPCMBlockQuote >> isBlockLevel [
^ true
]
{ #category : #accessing }
PPCMBlockQuote >> viewBody [
^ (self className ,' ', self text) asRopedText.
]