2022-09-21 18:57:52 +00:00
Extension { #name : # LeDatabase }
2023-10-26 17:42:32 +00:00
{ #category : # ' * MiniDocs ' }
LeDatabase >> addPage2FromMarkdeep: markdeepDocTree withRemote: externalDocLocation [
2023-10-31 20:48:51 +00:00
| newPage |
2023-10-28 18:28:50 +00:00
"^ { snippets . page }"
"Rebulding partial subtrees"
"Adding unrooted subtrees to the page"
"^ newPage"
2023-10-31 20:48:51 +00:00
newPage := self
rebuildPageFromMarkdeep: markdeepDocTree
withRemote: externalDocLocation .
newPage
c h i l d r e n D o : [ : snippet |
(self hasBlockUID: snippet uid )
i f T r u e : [ | existingPage |
existingPage := self pages
d e t e c t : [ : pageTemp | pageTemp includesSnippetUid: snippet uid ].
2023-10-26 17:42:32 +00:00
self importErrorForLocal: existingPage withRemote: externalDocLocation .
^ self ]
i f F a l s e : [ snippet database: self .
self registerSnippet: snippet ] ].
2023-10-28 18:28:50 +00:00
self addPage: newPage .
^ newPage
2023-10-26 17:42:32 +00:00
]
2023-10-12 22:01:26 +00:00
{ #category : # ' * MiniDocs ' }
LeDatabase >> addPageCopy: aLePage [
2023-10-25 11:50:15 +00:00
| 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 ).
2023-10-12 22:01:26 +00:00
^ page
]
2022-09-21 18:57:52 +00:00
{ #category : # ' * MiniDocs ' }
2022-10-09 21:26:33 +00:00
LeDatabase >> addPageFromMarkdeep: markdeepDocTree withRemote: externalDocLocation [
2023-10-20 17:59:17 +00:00
| remoteMetadata divSnippets dataSnippets snippets page |
2022-10-09 23:12:15 +00:00
divSnippets := (markdeepDocTree xpath: '//div[@st-class]' ) asOrderedCollection
c o l l e c t : [ : xmlElement | xmlElement postCopy ].
2023-10-20 17:59:17 +00:00
remoteMetadata := Markdeep new metadataFromXML: markdeepDocTree .
remoteMetadata at: 'origin' put: externalDocLocation .
dataSnippets := self sanitizeMarkdeepSnippets: divSnippets withMetadata: remoteMetadata .
snippets := dataSnippets collect: [ : each | each asLepiterSnippet ].
2024-04-11 18:06:21 +00:00
page := LePage new .
page
t i t l e : (remoteMetadata at: 'title' ifAbsent: [ page detectMarkdeepTitleFrom: markdeepDocTree ]);
b a s i c U i d : (UUID fromString36: (remoteMetadata at: 'id' ifAbsent: [UUID new asString36 ]));
c r e a t e T i m e : (LeTime new
t i m e : (remoteMetadata at: 'created' ifAbsent: [ DateAndTime now ]) asDateAndTime );
e d i t T i m e : (LeTime new
t i m e : (remoteMetadata at: 'modified' ifAbsent: [ DateAndTime now ]) asDateAndTime );
l a t e s t E d i t T i m e : (LeTime new
t i m e : (remoteMetadata at: 'modified' ifAbsent: [ DateAndTime now ]) asDateAndTime );
c r e a t e E m a i l : (remoteMetadata at: 'creator' ifAbsent: [ 'unknown' ]);
e d i t E m a i l : (remoteMetadata at: 'modifier' ifAbsent: [ 'unknown' ]).
2023-10-20 23:37:51 +00:00
snippets do: [ : snippet | "| currentParent |"
2023-10-20 18:54:43 +00:00
page addSnippet: snippet .
2023-10-20 23:37:51 +00:00
" currentParent := page detectParentSnippetWithUid: (snippet metadata at: 'parent' ).
snippet parent: currentParent . "
2023-10-20 18:54:43 +00:00
].
2022-10-09 23:12:15 +00:00
page children
d o : [ : snippet |
(self hasBlockUID: snippet uid )
i f T r u e : [ | existingPage |
existingPage := self pages
d e t e c t : [ : pageTemp | pageTemp includesSnippetUid: snippet uid ].
self importErrorForLocal: existingPage withRemote: externalDocLocation .
^ self ]
i f F a l s e : [ snippet database: self .
self registerSnippet: snippet ] ].
2022-10-03 22:50:44 +00:00
self addPage: page .
2022-10-09 23:12:15 +00:00
^ page
2022-09-21 18:57:52 +00:00
]
2022-09-29 13:20:56 +00:00
{ #category : # ' * MiniDocs ' }
LeDatabase >> addPageFromMarkdeepUrl: aString [
| page |
page := self detectLocalPageForRemote: aString .
2022-10-09 21:26:33 +00:00
page
i f N o t N i l : [ : arg |
2022-10-09 23:12:15 +00:00
self importErrorForLocal: page withRemote: aString .
2023-12-28 00:55:26 +00:00
^ self errorCardFor: page uidString ].
2023-10-28 18:28:50 +00:00
^ self addPageFromMarkdeep: (self docTreeForLink: aString ) withRemote: aString
2022-09-29 13:20:56 +00:00
]
2022-09-21 18:57:52 +00:00
{ #category : # ' * MiniDocs ' }
LeDatabase >> detectLocalPageForRemote: markdeepDocUrl [
| markdeepHelper id remoteMetadata docTree |
markdeepHelper := Markdeep new .
2022-09-21 21:15:13 +00:00
docTree := self docTreeForLink: markdeepDocUrl .
2022-09-21 18:57:52 +00:00
remoteMetadata := markdeepHelper metadataFromXML: docTree .
2022-09-21 21:15:13 +00:00
id := remoteMetadata at: 'id' ifAbsent: [ nil ].
^ self pageWithID: id ifAbsent: [ ^ nil ].
]
{ #category : # ' * MiniDocs ' }
LeDatabase >> docTreeForLink: aString [
2022-09-22 02:15:11 +00:00
^ (XMLHTMLParser on: aString asUrl retrieveContents ) parseDocument
2022-09-21 18:57:52 +00:00
]
2022-10-07 22:46:47 +00:00
{ #category : # ' * MiniDocs ' }
2023-12-28 00:55:26 +00:00
LeDatabase >> errorCardFor: errorKey [
2022-10-07 22:46:47 +00:00
2023-12-28 00:55:26 +00:00
| keepButton overwriteButton loadCopyButton errorMessageUI localPage |
2023-10-29 00:13:02 +00:00
2022-10-10 12:27:15 +00:00
localPage := self pageWithID: errorKey .
2022-10-07 22:46:47 +00:00
keepButton := BrButton new
aptitude: BrGlamorousButtonWithIconAndLabelAptitude ;
2022-10-09 01:59:57 +00:00
l a b e l : 'Keep existing local page' ;
2022-10-07 22:46:47 +00:00
icon: BrGlamorousVectorIcons cancel ;
2022-10-10 02:26:12 +00:00
m a r g i n : (BlInsets left: 10 );
a c t i o n : [ : aButton |
2022-10-10 14:17:08 +00:00
aButton phlow spawnObject: localPage .
self errors removeKey: errorKey
2022-10-10 02:26:12 +00:00
].
2022-10-07 22:46:47 +00:00
overwriteButton := BrButton new
aptitude: BrGlamorousButtonWithIconAndLabelAptitude ;
2022-10-09 01:59:57 +00:00
l a b e l : 'Overwrite with remote page' ;
2022-10-07 22:46:47 +00:00
icon: BrGlamorousVectorIcons edit ;
2022-10-10 02:26:12 +00:00
a c t i o n : [ : aButton |
self removePage: localPage .
2023-10-29 00:13:02 +00:00
aButton phlow spawnObject: (self addPageFromMarkdeepUrl: (self errors at: errorKey at: 'remote' )).
2022-10-10 14:17:08 +00:00
self errors removeKey: errorKey
2022-10-10 02:26:12 +00:00
];
2022-10-07 22:46:47 +00:00
m a r g i n : (BlInsets left: 10 ).
2023-10-29 00:13:02 +00:00
loadCopyButton := BrButton new
2022-10-07 22:46:47 +00:00
aptitude: BrGlamorousButtonWithIconAndLabelAptitude ;
2023-10-29 00:49:22 +00:00
l a b e l : 'Load remote page as a copy' ;
2022-10-07 22:46:47 +00:00
icon: BrGlamorousVectorIcons changes ;
2023-10-29 00:49:22 +00:00
a c t i o n : [ : aButton | self ];
2022-10-07 22:46:47 +00:00
m a r g i n : (BlInsets left: 10 ).
errorMessageUI := BrEditor new
2022-10-09 01:59:57 +00:00
aptitude: BrGlamorousRegularEditorAptitude new ;
2023-10-29 00:13:02 +00:00
t e x t : (self errors at: errorKey at: 'message' );
2022-10-07 22:46:47 +00:00
vFitContent .
2023-12-28 00:55:26 +00:00
^ BrHorizontalPane new
matchParent ;
alignCenter ;
addChild: errorMessageUI ;
addChild: keepButton ;
addChild: overwriteButton ;
addChild: loadCopyButton
2022-10-07 22:46:47 +00:00
]
2022-10-07 22:34:04 +00:00
{ #category : # ' * MiniDocs ' }
LeDatabase >> errors [
2022-10-10 12:27:15 +00:00
^ self optionAt: 'errors' ifAbsentPut: [ Dictionary new ]
2022-10-07 22:34:04 +00:00
]
2023-10-29 00:49:22 +00:00
{ #category : # ' * MiniDocs ' }
LeDatabase >> gtViewErrorDetailsOn: aView [
< gtView >
^ aView explicit
t i t l e : 'Errors' translated ;
priority: 5 ;
s t e n c i l : [ | container |
container := BlElement new
layout: BlFlowLayout new ;
c o n s t r a i n t s D o : [ : c |
c vertical fitContent .
c horizontal matchParent ];
p a d d i n g : (BlInsets all: 10 ).
container
a d d C h i l d r e n : (self errorCardFor: self errors )
].
]
2022-10-07 20:48:54 +00:00
{ #category : # ' * MiniDocs ' }
2023-10-29 00:13:02 +00:00
LeDatabase >> gtViewErrorDetailsOn: aView withKey: erroKey [
2022-10-07 20:48:54 +00:00
< gtView >
^ aView explicit
2023-10-31 18:04:47 +00:00
t i t l e : 'Errors beta' translated ;
2022-10-07 20:48:54 +00:00
priority: 5 ;
2022-10-10 02:26:12 +00:00
s t e n c i l : [ | container |
container := BlElement new
layout: BlFlowLayout new ;
c o n s t r a i n t s D o : [ : c |
c vertical fitContent .
c horizontal matchParent ];
p a d d i n g : (BlInsets all: 10 ).
container
2023-10-29 00:13:02 +00:00
a d d C h i l d r e n : (self errorCardFor: erroKey )
2022-10-10 02:26:12 +00:00
].
2022-10-07 20:48:54 +00:00
]
2024-04-08 17:46:42 +00:00
{ #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
]
2022-09-21 18:57:52 +00:00
{ #category : # ' * MiniDocs ' }
2022-10-09 23:12:15 +00:00
LeDatabase >> importErrorForLocal: page withRemote: externalDocLocation [
2022-09-21 18:57:52 +00:00
2022-10-10 01:30:40 +00:00
| message id error |
2022-10-07 22:34:04 +00:00
id := page uidString .
message := String streamContents: [ : stream |
2022-09-21 18:57:52 +00:00
stream
2022-10-09 01:59:57 +00:00
n e x t P u t A l l : ' IMPORTATION ERROR: A page with
' ;
2022-09-21 18:57:52 +00:00
nextPut: Character lf ;
2022-10-07 22:34:04 +00:00
n e x t P u t A l l : ' id: ' , id ;
2022-09-21 18:57:52 +00:00
nextPut: Character lf ;
n e x t P u t A l l : ' title: ' , page contentAsString ;
nextPut: Character lf ;
nextPut: Character lf ;
2022-10-09 01:59:57 +00:00
n e x t P u t A l l : 'already exists in this database and includes overlapping contents' ;
nextPut: Character lf ;
2022-10-09 23:12:15 +00:00
n e x t P u t A l l : ' with the page you are trying to import from:
' ;
nextPut: Character lf ;
nextPutAll: externalDocLocation ;
2022-09-21 18:57:52 +00:00
nextPut: Character lf ;
nextPut: Character lf ;
n e x t P u t A l l :
2022-10-09 01:59:57 +00:00
' Please choose one of the following options to addres the issue:
' ].
2022-10-10 01:30:40 +00:00
error := Dictionary new
2022-10-10 12:27:15 +00:00
a t : 'remote' put: externalDocLocation ;
a t : 'message' put: message ;
2022-10-10 01:30:40 +00:00
yourself .
2023-10-29 00:13:02 +00:00
self errors at: id put: error .
2023-12-28 00:55:26 +00:00
^ self errors at: id .
2022-10-07 22:34:04 +00:00
]
{ #category : # ' * MiniDocs ' }
LeDatabase >> options [
^ options
2022-09-21 18:57:52 +00:00
]
2023-10-20 14:22:06 +00:00
{ #category : # ' * MiniDocs ' }
LeDatabase >> previewSanitizedPageFromMarkdeep: markdeepDocTree withRemote: externalDocLocation [
| remoteMetadata divSnippets divSnippetsSanitized |
divSnippets := (markdeepDocTree xpath: '//div[@st-class]' ) asOrderedCollection
c o l l e c t : [ : xmlElement | xmlElement postCopy ].
2023-10-20 17:59:17 +00:00
remoteMetadata := Markdeep new metadataFromXML: markdeepDocTree .
remoteMetadata at: 'origin' put: externalDocLocation .
2023-10-20 14:22:06 +00:00
divSnippetsSanitized := self sanitizeMarkdeepSnippets: divSnippets withMetadata: remoteMetadata .
^ { divSnippets . divSnippetsSanitized . remoteMetadata }
]
2023-10-31 20:48:51 +00:00
{ #category : # ' * MiniDocs ' }
LeDatabase >> rebuildPageFromMarkdeep: markdeepDocTree withRemote: externalDocLocation [
| newPage snippets divSnippets remoteMetadata dataSnippets |
divSnippets := (markdeepDocTree xpath: '//div[@st-class]' ) asOrderedCollection
c o l l e c t : [ : 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
t i t l e : (remoteMetadata at: 'title' );
b a s i c U i d : (UUID fromString36: (remoteMetadata at: 'id' ));
c r e a t e T i m e : (LeTime new time: (remoteMetadata at: 'created' ) asDateAndTime );
e d i t T i m e : (LeTime new time: (remoteMetadata at: 'modified' ) asDateAndTime );
l a t e s t E d i t T i m e : (LeTime new time: (remoteMetadata at: 'modified' ) asDateAndTime );
c r e a t e E m a i l : (remoteMetadata at: 'creator' );
e d i t E m a i l : (remoteMetadata at: 'modifier' ). "^ { snippets . page }" "Rebulding partial subtrees"
snippets
d o : [ : currentSnippet |
| parentSnippet |
parentSnippet := snippets
d e t e c t : [ : item | item uid asString = currentSnippet parent ]
i f N o n e : [ parentSnippet := 'unrooted' ].
currentSnippet parent: parentSnippet .
parentSnippet class = ByteString
i f F a l s e : [ parentSnippet children addChild: currentSnippet ] ]. "Adding unrooted subtrees to the page"
"^ { unrooted . newPage }."
snippets
s e l e c t : [ : each | each parent = 'unrooted' ]
t h e n D o : [ : unrooted | newPage addSnippet: unrooted ].
^ newPage
]
2023-10-20 14:22:06 +00:00
{ #category : # ' * MiniDocs ' }
LeDatabase >> sanitizeMarkdeepSnippets: divSnippets withMetadata: remoteMetadata [
2023-10-20 17:59:17 +00:00
^ divSnippets collectWithIndex: [: markdeepDiv : i | | snippetData creationTime modificationTime timestampWarning |
2023-10-20 14:22:06 +00:00
snippetData := markdeepDiv asSnippetDictionary .
creationTime := snippetData at: 'created' .
modificationTime := snippetData at: 'modified' .
2023-10-31 19:03:39 +00:00
timestampWarning := [: timestamp |
'Modified timestamps: ' , timestamp , ' date and time was replaced instead of nil value. See "origin" metadata for more historical traceability information.'
].
2023-10-20 14:22:06 +00:00
(creationTime = 'nil' and: [ modificationTime ~= 'nil' ])
2023-10-20 17:59:17 +00:00
i f T r u e : [
snippetData redefineTimestampsBefore: modificationTime .
snippetData addErrata: (timestampWarning value: 'creation' ).
snippetData at: 'origin' put: (remoteMetadata at: 'origin' ).
].
2023-10-20 14:22:06 +00:00
(creationTime = 'nil' and: [ modificationTime = 'nil' ])
i f T r u e : [ | 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 .
2023-10-20 17:59:17 +00:00
snippetData addErrata: (timestampWarning value: 'creation' ).
snippetData addErrata: (timestampWarning value: 'modification' ).
snippetData at: 'origin' put: (remoteMetadata at: 'origin' ).
2023-10-20 14:22:06 +00:00
].
snippetData .
]
]