334 lines
9.2 KiB
Smalltalk
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
|
|
]
|