" I model a Mardeep file as described in https://casual-effects.com/markdeep/ " Class { #name : #Markdeep, #superclass : #Markdown, #instVars : [ 'title', 'comments', 'tail', 'language', 'config', 'head', 'navTop', 'options' ], #category : #'MiniDocs-Core' } { #category : #'as yet unclassified' } Markdeep class >> fromMarkdownFile: aFileReference [ ^ self new fromMarkdownFile: aFileReference. ] { #category : #accessing } Markdeep class >> fromPubPubTOC: orderedDictionary folder: folder index: ordinalPossitive [ | contentSection testFile | contentSection := orderedDictionary associations at: ordinalPossitive. testFile := folder / (contentSection key,'--', contentSection value),'md'. ^ self new fromMarkdownFile: testFile. ] { #category : #'instance creation' } Markdeep >> authors [ self metadata at: 'authors' ifPresent: [:k | ^ '**', k, '**' ]. ^ ''. ] { #category : #'instance creation' } Markdeep >> authorsString [ self authors ifNil: [ ^ '' ] ifNotNil: [ ^ ' ', self authors ] ] { #category : #accessing } Markdeep >> body [ ^ body ifNil: [^ '' ] ] { #category : #accessing } Markdeep >> body: anObject [ body := anObject ] { #category : #accessing } Markdeep >> bodyReplaceAll: original with: replacement [ self body: (self body copyReplaceAll: original with: replacement) ] { #category : #accessing } Markdeep >> commentPubPubDelimiters [ | commented openners | openners := #('::: {.pub-body-component}' '::: pub-body-component' '::: {.editor .Prosemirror}' '::: {.pub-notes}'). commented := self body. openners do: [:openner | commented := commented copyReplaceAll: openner with: '' ]. commented := commented copyReplaceAll: '::: ' with: ' '. self body: commented ] { #category : #accessing } Markdeep >> comments [ ^ comments ifNil: [ ^ comments := true ] ] { #category : #accessing } Markdeep >> comments: aBoolean [ "I tell if comments are enabled by default or not." comments := aBoolean ] { #category : #utilities } Markdeep >> commentsProvider [ "I return the url of the default service that provides annotation support. I am used to add such support in the contents of the Markdeep page." ^ 'https://hypothes.is' ] { #category : #utilities } Markdeep >> commentsProviderStrings [ "I associate a comments service provider with the string that is required to be added to the document to enable such provider." | providers | providers := Dictionary new. providers at: 'https://hypothes.is' put: ' '. ^ providers ] { #category : #utilities } Markdeep >> commentsSupport [ "I enable comments of the page." self comments ifFalse: [ ^ self ]. ^ self commentsProviderStrings at: self commentsProvider ] { #category : #accessing } Markdeep >> config [ ^ config ifNil: [ config := Dictionary new] ] { #category : #accessing } Markdeep >> config: aDictionary [ config := aDictionary ] { #category : #'instance creation' } Markdeep >> contents [ | output | self title ifNil: [ ^ self body ]. output := '' writeStream. output nextPutAll: self headContents; lf; lf; nextPutAll: ' **', self title trimmed accentedCharactersCorrection, '**'; lf; nextPutAll: self authorsString ; lf; nextPutAll: '', self version; lf; nextPutAll: self navTop; lf; lf; nextPutAll: self body; lf; lf; nextPutAll: self tail; lf; lf; lf; lf; nextPutAll: self commentsSupport. ^ output contents. ] { #category : #accessing } Markdeep >> converPubPubFootnoteBetween: footnote and: nextFootnote in: footnotesArray [ | currentNoteIndex nextNoteIndex response noteLines | currentNoteIndex := footnotesArray indexOf: '[^',footnote, ']: '. nextNoteIndex := footnotesArray indexOf: '[^',nextFootnote, ']: '. noteLines := footnotesArray copyFrom: currentNoteIndex to: nextNoteIndex - 1. response := '' writeStream. noteLines do: [:line | line ifNotEmpty: [ response nextPutAll: line, String lf ] "ifEmpty: [ response nextPutAll: ' ' ]?" ]. response nextPutAll: String lf. ^ response contents ] { #category : #utilities } Markdeep >> fontAwesomeHeader [ "I enable the font awesome support in the document header" ^ '' ] { #category : #'instance creation' } Markdeep >> fromMarkdownFile: aFileReference [ "I create a Markdeep document from a given Markdown file." self processMarkdownFor: aFileReference. ^ self. ] { #category : #accessing } Markdeep >> fromPubPubToMarkdeep [ self removeAutoGeneratedFileNotice; removeCCByLicenseDiv; commentPubPubDelimiters; replaceEscapedCharacters; renamePubPubFootnotes; removeAlternativeImagesArray ] { #category : #accessing } Markdeep >> gtTextFor: aView [ ^ aView textEditor title: 'Text'; text: [ self contents ] ] { #category : #accessing } Markdeep >> head [ ^ head ifNil: [ head := OrderedCollection new. head add: self fontAwesomeHeader; yourself ] ] { #category : #accessing } Markdeep >> head: anOrderedCollection [ head := anOrderedCollection ] { #category : #'instance creation' } Markdeep >> headContents [ ^ String streamContents: [ :stream | stream nextPutAll: ''; nextPut: Character lf. self head do: [ :line | stream nextPutAll: ' '; nextPutAll: line; nextPut: Character lf ]. stream nextPutAll: ''; nextPut: Character lf. ]. ] { #category : #accessing } Markdeep >> language [ ^ language ] { #category : #accessing } Markdeep >> language: anObject [ language := anObject ] { #category : #accessing } Markdeep >> markdeepScriptTag [ ^ ' ' ] { #category : #accessing } Markdeep >> markdownFile [ self file ifNil: [ self file: FileLocator temp / ('untitled--', NanoID generate, '.md.html') ]. ^ (self file fullName withoutSuffix: '.html') asFileReference. ] { #category : #accessing } Markdeep >> markdownFile: aFileReference [ "Where the Mardown file associated with me is stored. Used for sync. and import/export purposes." self config at: 'markdownFile' put: aFileReference ] { #category : #'instance creation' } Markdeep >> metadata [ ^ metadata ifNil: [ metadata := OrderedDictionary new ] ] { #category : #accessing } Markdeep >> metadata: anOrderedDictionary [ metadata := anOrderedDictionary ] { #category : #utilities } Markdeep >> metadataFromXML: aXMLDocument [ | metaDict | metaDict := OrderedDictionary new. (aXMLDocument xpath: '//meta') do: [ :each | metaDict at: (each @ 'name') stringValue put: (each @ 'content') stringValue ]. ^ metaDict ] { #category : #'instance creation' } Markdeep >> navTop [ ^ navTop ifNil: [ navTop := '' ] ] { #category : #'as yet unclassified' } Markdeep >> navTop: aString [ navTop:= aString. ] { #category : #accessing } Markdeep >> options [ ^ options ifNil: [ "Setting defaults accoding to: https://casual-effects.com/markdeep/#api" options := Dictionary new at: 'mode' put: nil; at: 'lang' put: nil; at: 'tocStyle' put: 'auto'; at: 'autoLinkImages' put: true; yourself ] ] { #category : #printing } Markdeep >> printOn: aStream [ super printOn: aStream. aStream nextPutAll: '( ', self title accentedCharactersCorrection, ' )' ] { #category : #'instance creation' } Markdeep >> processMarkdownFor: aFileReference [ "comment stating purpose of message" | markdownContent | self file: aFileReference, 'html'. markdownContent := Markdown fromFile: aFileReference. self metadata: markdownContent yamlMetadata. self body: (markdownContent commentYAMLMetadata contents). ] { #category : #accessing } Markdeep >> pubPubFootnoteMetadataFromString: string [ | sanitized footnoteData altLine altString id | (string lines size <= 1) ifTrue: [ ^ nil ]. sanitized := '' writeStream. altString := string copyReplaceAll: '.footnote' with: ''. altString := altString copyReplaceAll: ' node-type=' with: ' node-type= '. altString := altString copyReplaceAll: ' data-value=' with: ' data-value='. altString := altString copyReplaceAll: ' date-structured-value=' with: ' date-structured-value= '. altString lines allButFirstDo: [:line | (line beginsWith: '>') ifTrue: [ altLine := line allButFirst ] ifFalse: [ altLine := line ]. sanitized nextPutAll: altLine trimBoth; nextPutAll: String lf ]. sanitized := sanitized contents. sanitized := sanitized copyReplaceAll: 'type=' with: 'type: '. sanitized := sanitized copyReplaceAll: 'value=' with: 'value: '. id := (altString lines first) allButFirst trimmed. footnoteData := { 'id' -> id } asDictionary. footnoteData addAll: (MiniDocs yamlToJson: sanitized trimmed). ^ footnoteData ] { #category : #accessing } Markdeep >> pubPubFootnoteRawLinks [ ^ self selectPubPubLinksWithSize: 2 ] { #category : #accessing } Markdeep >> pubPubFootnotesLinesRangeFor: contentSection [ | beginningLine endingLine | beginningLine := contentSection lines size + 1. contentSection lines doWithIndex: [:line :i | ((line includesSubstring: '::: {.pub-notes}') or: [line includesSubstring: '::: pub-notes']) ifTrue: [ beginningLine := i ]. (i > beginningLine and: [ line beginsWith: ':::' ]) ifTrue: [ endingLine := i. ^ {beginningLine . endingLine} ] ] ] { #category : #accessing } Markdeep >> pubPubFootnotesLinesRangeForBody [ ^ self pubPubFootnotesLinesRangeFor: self body ] { #category : #accessing } Markdeep >> pubPubFootnotesLinesRangeForContents [ ^ self pubPubFootnotesLinesRangeFor: self contents ] { #category : #accessing } Markdeep >> pubPubFootnotesText [ | footnotesLines output | footnotesLines := self contents lines copyFrom: self pubPubFootnotesLinesRangeForContents first + 3 to: self pubPubFootnotesLinesRangeForContents second - 1. output := '' writeStream. footnotesLines do: [:line | output nextPutAll: line; nextPutAll: String crlf. ]. ^ output contents allButLast ] { #category : #accessing } Markdeep >> pubPubImageLinks [ ^ self selectPubPubLinksWithSize: 3 ] { #category : #accessing } Markdeep >> pubPubImagesToMarkdeep [ | sanitized parsedLinks | parsedLinks := self pubPubImageLinks. parsedLinks ifEmpty: [ ^self ]. sanitized := self body. parsedLinks do: [:link | sanitized := sanitized copyReplaceAll: '{', link third, '}' with: '' ]. self body: sanitized ] { #category : #accessing } Markdeep >> pubPubRawLinks [ | parser | parser := PubPubGrammar2 new document. ^ (parser parse: self body) ] { #category : #accessing } Markdeep >> reformatPubPubFootnotes [ | footnotesLines footnotesIDs toReplace response | (self = self pubPubFootnotesLinesRangeForContents) ifTrue: [^self]. footnotesLines := self contents lines copyFrom: self pubPubFootnotesLinesRangeForContents first to: self pubPubFootnotesLinesRangeForContents second. footnotesIDs := self replacePubPubFootnotesIdentifiers. toReplace := footnotesLines select: [:line | (line includesSubstring: ' [[]{.pub-note-content-component}]{#fn-') ]. toReplace doWithIndex: [:replacement :i | | index | index := footnotesLines indexOf: replacement. footnotesLines at: index put: '[^', (footnotesIDs at: i),']: ' ]. response := '' writeStream. footnotesIDs allButLast doWithIndex: [:footnote :i | response nextPutAll: (self converPubPubFootnoteBetween: footnote and: (footnotesIDs at: i + 1) in: footnotesLines) ]. ^ response contents ] { #category : #accessing } Markdeep >> removeAlternativeImagesArray [ | replacements | self body ifNil: [^ self]. replacements := self selectPubPubLinksWithSize: 3. replacements ifEmpty: [^self]. replacements do: [:replacement | self body: (self body copyReplaceAll: replacement third with: '' ) ]. self body: (self body copyReplaceAll: '{srcset=}' with: ''). ] { #category : #accessing } Markdeep >> removeAutoGeneratedFileNotice [ | autoGeneratedNotice | autoGeneratedNotice := '**Notice:** This file is an auto-generated download and, as such, might include minor display or rendering errors. For the version of record, please visit the HTML version or download the PDF. ------------------------------------------------------------------------'. self body: (self body copyReplaceAll: autoGeneratedNotice with: '') ] { #category : #accessing } Markdeep >> removeCCByLicenseDiv [ | licenseDiv| licenseDiv := '
**License:** [Creative Commons Attribution 4.0 International License (CC-BY 4.0)](https://creativecommons.org/licenses/by/4.0/)
'. self body: (self body copyReplaceAll: licenseDiv with: '') ] { #category : #accessing } Markdeep >> renamePubPubFootnotes [ | reformated bodyLines beforeFootnotes afterFootnotesRaw afterFootnotes newBodyLines response | reformated := self reformatPubPubFootnotes. (self pubPubFootnotesLinesRangeForBody class = Markdeep) ifTrue: [ ^self ]. bodyLines := self body lines. beforeFootnotes := bodyLines copyFrom: 1 to: self pubPubFootnotesLinesRangeForBody first . afterFootnotesRaw := bodyLines copyFrom: self pubPubFootnotesLinesRangeForBody second to: bodyLines size. afterFootnotes := OrderedCollection new. afterFootnotesRaw do:[:line | (line beginsWith: ':::') ifTrue: [ afterFootnotes add: (line copyReplaceAll: ':::' with: ''). ] ]. newBodyLines := (beforeFootnotes copyWithAll: (#('# Footnotes' '') copyWithAll:(reformated lines copyWithAll: afterFootnotes))). response := '' writeStream. newBodyLines do: [:line | response nextPutAll: line, String lf ]. self body: response contents. ] { #category : #accessing } Markdeep >> replaceBackslashBreaklines [ self bodyReplaceAll: '\ ' with: '
' ] { #category : #accessing } Markdeep >> replaceEscapedCharacters [ self title: (self title copyReplaceAll: '\#' with: '#'); body: (self body copyReplaceAll: '\#' with: '#'); body: (self body copyReplaceAll: '\[' with: '['); body: (self body copyReplaceAll: '\]' with: ']'); body: (self body copyReplaceAll: '\*' with: '*') ] { #category : #accessing } Markdeep >> replacePubPubFootnotesIdentifiers [ | footnotes sanitized parsedLinks linkIdentifiers | footnotes := OrderedDictionary new. parsedLinks := self pubPubFootnoteRawLinks. parsedLinks ifEmpty: [ ^self ]. sanitized := self body. linkIdentifiers := OrderedCollection new. parsedLinks do: [:link | | id currentLinkText | id := (link second splitOn: '.footnote') first trimmed. linkIdentifiers add: id. currentLinkText := '[', link first, ']{#',link second,'}'. sanitized := sanitized copyReplaceAll: currentLinkText with: '[^', id, ']' ]. self body: sanitized. ^ linkIdentifiers ] { #category : #accessing } Markdeep >> selectPubPubLinksWithSize: naturalNumber [ ^ self pubPubRawLinks select: [ :each | each size = naturalNumber ] ] { #category : #accessing } Markdeep >> tail [ "I enable the document tail, which, in turn, enables a Markdeep document" | output | output := '' writeStream. output nextPutAll: ''; lf; lf; nextPutAll: ''; lf; nextPutAll: ''; lf; nextPutAll: self markdeepScriptTag; lf; nextPutAll: ''. ^ output contents ] { #category : #accessing } Markdeep >> tail: anObject [ tail := anObject ] { #category : #accessing } Markdeep >> title [ ^ title ifNil: [ title := self metadata at: 'title' ifAbsent: [ '' ] ] ] { #category : #accessing } Markdeep >> title: anObject [ title := anObject ] { #category : #accessing } Markdeep >> tocStyle [ ^ self options at: 'tocStyle' ifAbsent: [ 'short' ] ] { #category : #accessing } Markdeep >> tocStyle: aString [ "A string can be: 'auto' 'none' 'short' 'medium' or 'long'" self options at: 'tocStyle' put: aString ] { #category : #'instance creation' } Markdeep >> version [ self metadata at: 'version' ifPresent: [:value | ^ 'v',value ]. ^ '' ]