MiniDocs/src/MiniDocs/LePage.extension.st

334 lines
9.2 KiB
Smalltalk

Extension { #name : #LePage }
{ #category : #'*MiniDocs' }
LePage >> asHtmlFile [
self asMarkdownFile.
self defaultPandocTemplate exists
ifFalse: [ MarkupFile installTemplate: 'https://mutabit.com/repos.fossil/mutabit/doc/trunk/plantillas/Pandoc/clean-menu-mod.html' into: self defaultPandocTemplate parent ].
OSSUnixSubprocess new
command: 'pandoc' ;
arguments: {
self markdownFileName. '-o'. self htmlFileName .
'--toc' .
'--template=', self defaultPandocTemplate basenameWithoutExtension };
workingDirectory: self storage fullName;
runAndWaitOnExitDo: [ :process :outString | ^ self storage / self htmlFileName].
]
{ #category : #'*MiniDocs' }
LePage >> asMarkdeep [
| bodyStream markdeep |
bodyStream := '' writeStream.
self preorderTraversal
do: [ :snippet | bodyStream nextPutAll: snippet asMarkdeep ].
markdeep := Markdeep new
title: self title;
body: bodyStream contents;
metadata: self metadata;
file: self storage / self markdeepFileName;
navTop: self navTop.
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 head: nil.
^ markdeep
]
{ #category : #'*MiniDocs' }
LePage >> asMarkdeepFile [
^ self asMarkdeep notifyExportAsFileOn: self storage / self markdeepFileName
]
{ #category : #'*MiniDocs' }
LePage >> asMarkdown [
| bodyStream markdown |
bodyStream := '' writeStream.
bodyStream
nextPutAll: '# ', self title; cr; cr.
self preorderTraversal
do: [ :snippet | bodyStream nextPutAll: snippet asMarkdown ].
markdown := Markdown new
contents: bodyStream contents demoteMarkdownHeaders;
metadata: (self metadata at: 'original' ifAbsentPut: Dictionary new).
^ markdown
]
{ #category : #'*MiniDocs' }
LePage >> asMarkdownFile [
| folder |
folder := self storage.
^ MarkupFile exportAsFileOn: folder / self markdownFileName containing: self asMarkdownWithMetadataWrappers contents
]
{ #category : #'*MiniDocs' }
LePage >> asMarkdownWithMetadataWrappers [
| bodyStream markdown |
bodyStream := '' writeStream.
bodyStream
nextPutAll: '# ', self title; cr; cr.
self preorderTraversal
do: [ :snippet | bodyStream nextPutAll: snippet asMarkdownWithMetadataWrappers ].
markdown := Markdown new
contents: bodyStream contents demoteMarkdownHeaders;
metadata: (self metadata at: 'original' ifAbsentPut: Dictionary new).
^ markdown
]
{ #category : #'*MiniDocs' }
LePage >> config [
| configFile |
configFile := self storage / 'config.ston'.
configFile exists
ifTrue: [^ STON fromString: configFile contents ]
ifFalse: [ ^ nil ]
]
{ #category : #'*MiniDocs' }
LePage >> defaultPandocTemplate [
^ FileLocator home / '.pandoc' / 'templates' / 'clean-menu-mod.html'
]
{ #category : #'*MiniDocs' }
LePage >> detectMarkdeepTitleFrom: xmlSubtree [
| titleLine |
titleLine := (xmlSubtree nodesCollect: [:node | node contentString ]) first lines
detect: [:line | line includesSubstring: ' **'] ifNone: ['Untitled'].
^ titleLine trimmed trimBoth: [:char | char = $* ]
]
{ #category : #'*MiniDocs' }
LePage >> detectParentSnippetWithUid: uidString [
uidString = self uid asString36 ifTrue: [ ^ self ].
^ self preorderTraversal detect: [ :snippet | snippet uidString = uidString ]
]
{ #category : #'*MiniDocs' }
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' }
LePage >> exportedFileName [
| sanitized |
sanitized := self title asDashedLowercase romanizeAccents copyWithoutAll: #($/ $: $🢒).
^ sanitized , '--' , (self uidString copyFrom: 1 to: 5)
]
{ #category : #'*MiniDocs' }
LePage >> fromMarkdeepUrl: aString [
| docTree pageMetadata |
docTree := GrafoscopioUtils xmlFromUrl: aString.
pageMetadata := Markdeep new metadataFromXML: docTree.
self
basicUid: (pageMetadata at: 'id');
title: (pageMetadata at: 'title');
createTime: (pageMetadata at: 'created') asDateAndTime;
editTime: (pageMetadata at: 'modified') asDateAndTime;
createEmail: (pageMetadata at: 'creator');
editEmail: (pageMetadata at: 'modifier');
optionAt: 'metadata' put: pageMetadata.
self populateChildrenFrom: (docTree xpath: '//div')
]
{ #category : #'*MiniDocs' }
LePage >> htmlFileName [
^ self exportedFileName, '.html'
]
{ #category : #'*MiniDocs' }
LePage >> latestEditTime: aLeTime [
"Used for adding a LePage to database from a shared markdeep LePage version."
latestEditTime := aLeTime
]
{ #category : #'*MiniDocs' }
LePage >> localHostAddress [
| localUrl route |
MiniDocsServer teapot server isRunning ifFalse: [ MiniDocsServer restart ].
route := MiniDocsServer teapot staticRouter prefix joinUsing: '/'.
localUrl := MiniDocsServer teapot server localUrl asString.
^ localUrl, route, '/', self markdeepFileName
]
{ #category : #'*MiniDocs' }
LePage >> markdeepFileName [
^ self markdownFileName , '.html'
]
{ #category : #'*MiniDocs' }
LePage >> markdownFileName [
^ self exportedFileName, '.md'
]
{ #category : #'*MiniDocs' }
LePage >> metadata [
^ self metadataUpdate
]
{ #category : #'*MiniDocs' }
LePage >> metadataUpdate [
^ OrderedDictionary new
at: 'id' put: self uidString;
at: 'title' put: self contentAsString;
at: 'created' put: self createTime greaseString;
at: 'modified' put: self getLatestEditTime greaseString;
at: 'creator' put: self createEmail greaseString;
at: 'modifier' put: self editEmail greaseString;
yourself
]
{ #category : #'*MiniDocs' }
LePage >> navTop [
| topNavFile |
topNavFile := self storage / '_navtop.html'.
topNavFile exists
ifFalse: [ ^ '' ]
ifTrue: [ ^ topNavFile contents ]
]
{ #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' }
LePage >> options [
^ options
]
{ #category : #'*MiniDocs' }
LePage >> preorderTraversal [
^ self allChildrenDepthFirst
]
{ #category : #'*MiniDocs' }
LePage >> removeSnippetsMetadata [
self preorderTraversal do: [ :snippet |
(snippet options isNotNil and: [ snippet options includesKey: 'metadata' ])
ifTrue: [ snippet options removeKey: 'metadata' ] ]
]
{ #category : #'*MiniDocs' }
LePage >> sanitizeMetadata [
self allChildrenDepthFirst do: [:snippet | snippet sanitizeMetadata ]
]
{ #category : #'*MiniDocs' }
LePage >> sharedVariablesBindings [
| codeSnippets shared |
codeSnippets := self preorderTraversal select: [:snippet |
snippet class = LePharoSnippet and: [ snippet code includesSubstring: ':=']
].
codeSnippets first in: [:snippet | | context |
context := snippet coder evaluationContext.
snippet coder doItInContext: context.
shared := context bindingStrategy bindings detect: [:each |
each isKindOf: GtSharedVariablesBindings
]
].
codeSnippets asArray allButFirstDo: [:snippet| | context|
context := snippet coder evaluationContext.
context addBindings: shared.
snippet coder doItInContext: context
].
^ shared asDictionary
]
{ #category : #'*MiniDocs' }
LePage >> storage [
| current |
current := self database attachmentsDirectory parent.
self optionAt: 'storage' ifAbsent: [ ^ current ].
(self optionAt: 'storage') ifNil: [ ^ current ].
^ 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' }
LePage >> uiDefineFolderFor: anAction [
<lePageAction>
| folderButton |
folderButton := anAction dropdown
icon: BrGlamorousIcons savetodisk;
tooltip: 'Export folder'"";
content: [:aButton | BlElement new
background: (Color gray alpha: 0.2);
size: 100 @ 100;
margin: (BlInsets all: 10) ].
^ folderButton
]
{ #category : #'*MiniDocs' }
LePage >> uiExportButtonFor: anAction [
<lePageAction>
^ anAction button
tooltip: 'Export Page';
icon: BrGlamorousVectorIcons down;
action: [:aButton | aButton phlow spawnObject: self page asMarkdeepFile ]
]
{ #category : #'*MiniDocs' }
LePage >> uiRefreshWebPreviewButtonFor: anAction [
<lePageAction>
^ anAction button
tooltip: 'Refresh web view';
icon: BrGlamorousVectorIcons refresh;
action: [
self page asMarkdeep exportAsFileOn: (self page storage / self page markdeepFileName).
GoogleChrome openWindowOn: self page localHostAddress.
"TODO: If Chrome/Chromium are not installed, I should execute:"
"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
]