diff --git a/src/Microdown-BookTester-Tests/MiCheckerEngineTest.class.st b/src/Microdown-BookTester-Tests/MiCheckerEngineTest.class.st new file mode 100644 index 00000000..1022a104 --- /dev/null +++ b/src/Microdown-BookTester-Tests/MiCheckerEngineTest.class.st @@ -0,0 +1,78 @@ +Class { + #name : 'MiCheckerEngineTest', + #superclass : 'TestCase', + #instVars : [ + 'fileSystem', + 'engine', + 'file' + ], + #category : 'Microdown-BookTester-Tests', + #package : 'Microdown-BookTester-Tests' +} + +{ #category : 'running' } +MiCheckerEngineTest >> generateFilesystemExample [ + file := fileSystem workingDirectory / 'test.md'. + file writeStreamDo: [ :stream | + stream nextPutAll: 'The colour of the sky is blue. +## writing books in pharo' + ]. +] + +{ #category : 'running' } +MiCheckerEngineTest >> setUp [ + super setUp. + + fileSystem := FileSystem memory. + engine := MicCheckerEngine new. + self generateFilesystemExample. +] + +{ #category : 'running' } +MiCheckerEngineTest >> testEngineDetectsHeaderMistake [ + | config results | + config := OrderedDictionary new. + config at: 'HeaderCapitalization' put: 'uppercase'. + results := engine runOn: file withConfiguration: config. + self deny: results isEmpty. + self assert: results size equals: 3. +] + +{ #category : 'running' } +MiCheckerEngineTest >> testEngineDetectsVocabularyMistake [ + | config results | + config := OrderedDictionary new. + config at: 'Vocabulary' put: { ('colour' -> 'color') }. + results := engine runOn: file withConfiguration: config. + self deny: results isEmpty. + self assert: results size equals: 1. + self assert: (results first explanation includesSubstring: 'colour'). +] + +{ #category : 'running' } +MiCheckerEngineTest >> testEngineRunsMultipleCheckers [ + | config results | + config := OrderedDictionary new. + config at: 'Vocabulary' put: { ('colour' -> 'color') }. + config at: 'HeaderCapitalization' put: 'uppercase'. + results := engine runOn: file withConfiguration: config. + self deny: results isEmpty. + self assert: results size > 1. +] + +{ #category : 'running' } +MiCheckerEngineTest >> testEngineWithEmptyConfiguration [ + | config results | + config := OrderedDictionary new. + results := engine runOn: file withConfiguration: config. + self assert: results isEmpty. +] + +{ #category : 'running' } +MiCheckerEngineTest >> testEngineWithUnknownChecker [ + | config results | + config := OrderedDictionary new. + config at: 'UnknownChecker' put: nil. + results := engine runOn: file withConfiguration: config. + self assert: results isEmpty. +] diff --git a/src/Microdown-BookTester/MicChecker.class.st b/src/Microdown-BookTester/MicChecker.class.st index bab25928..3d1595a1 100644 --- a/src/Microdown-BookTester/MicChecker.class.st +++ b/src/Microdown-BookTester/MicChecker.class.st @@ -18,6 +18,11 @@ Class { #tag : 'Core' } +{ #category : 'as yet unclassified' } +MicChecker class >> checkerName [ + ^ 'UnnamedChecker' +] + { #category : 'visiting' } MicChecker >> addResult: aResult [ diff --git a/src/Microdown-BookTester/MicCheckerEngine.class.st b/src/Microdown-BookTester/MicCheckerEngine.class.st new file mode 100644 index 00000000..fd770e3a --- /dev/null +++ b/src/Microdown-BookTester/MicCheckerEngine.class.st @@ -0,0 +1,52 @@ +" +I am a generic engine that reads a configuration dictionary and instantiates, configures and runs the appropriate checkers. +I discover all available checkers by looking at all subclasses of MicChecker that respond to #checkerName. + +Usage example: + | engine config reslts | + config := OrderedDictionary new. + config at: 'Vocabulary' put: { ('colour' -> 'color') }. + config at: 'HeaderCapitalization' put: 'uppercase'. + config at: 'EnglishTypographic' put:nil. + engine := MicCheckerEngine new. + results := engine runOn: 'myFile.md' asFileReference withConfiguration: config. + results do: [ :r | Transcript showCr: r explanation ]. +" +Class { + #name : 'MicCheckerEngine', + #superclass : 'Object', + #category : 'Microdown-BookTester-Core', + #package : 'Microdown-BookTester', + #tag : 'Core' +} + +{ #category : 'as yet unclassified' } +MicCheckerEngine >> checkersFromConfiguration: aConfiguration [ + | availableCheckers activeCheckers | + availableCheckers := Dictionary new. + MicChecker allSubclasses do: [ :aClass | + availableCheckers at: aClass checkerName put: aClass ]. + activeCheckers := OrderedCollection new. + aConfiguration keysAndValuesDo: [ :key :value | + | checkerClass checker | + checkerClass := availableCheckers at: key ifAbsent: [ nil ]. + checkerClass ifNotNil: [ + checker := checkerClass new. + checker configureFrom: value. + activeCheckers add: checker + ] + ]. + ^ activeCheckers +] + +{ #category : 'as yet unclassified' } +MicCheckerEngine >> runOn: aFileReference withConfiguration: aConfiguration [ + | activeCheckers results | + activeCheckers := self checkersFromConfiguration: aConfiguration. + results := OrderedCollection new. + activeCheckers do: [ :checker | + checker checkProject: aFileReference. + results addAll: checker results + ]. + ^ results +] diff --git a/src/Microdown-Rules/MicElementAfterColonIsNotCapitalizedResult.class.st b/src/Microdown-Rules/MicElementAfterColonIsNotCapitalizedResult.class.st index 4b245ceb..915d1c95 100644 --- a/src/Microdown-Rules/MicElementAfterColonIsNotCapitalizedResult.class.st +++ b/src/Microdown-Rules/MicElementAfterColonIsNotCapitalizedResult.class.st @@ -4,9 +4,9 @@ Class { #instVars : [ 'detail' ], - #category : 'Microdown-Rules-EnglishTypographic', + #category : 'Microdown-Rules-Capitalization', #package : 'Microdown-Rules', - #tag : 'EnglishTypographic' + #tag : 'Capitalization' } { #category : 'accessing' } diff --git a/src/Microdown-Rules/MicElementOfHeaderIsNotCapitalizedResult.class.st b/src/Microdown-Rules/MicElementOfHeaderIsNotCapitalizedResult.class.st index b28ada41..a813aa21 100644 --- a/src/Microdown-Rules/MicElementOfHeaderIsNotCapitalizedResult.class.st +++ b/src/Microdown-Rules/MicElementOfHeaderIsNotCapitalizedResult.class.st @@ -1,12 +1,12 @@ Class { #name : 'MicElementOfHeaderIsNotCapitalizedResult', - #superclass : 'MicReport', + #superclass : 'MicAbstractResult', #instVars : [ 'detail' ], - #category : 'Microdown-Rules-EnglishTypographic', + #category : 'Microdown-Rules-Capitalization', #package : 'Microdown-Rules', - #tag : 'EnglishTypographic' + #tag : 'Capitalization' } { #category : 'accessing' } @@ -18,3 +18,8 @@ MicElementOfHeaderIsNotCapitalizedResult >> detail [ MicElementOfHeaderIsNotCapitalizedResult >> detail: aString [ detail := aString ] + +{ #category : 'accessing' } +MicElementOfHeaderIsNotCapitalizedResult >> explanation [ + ^ 'Header: "' , micElement text , '" in file' , fileReference fullName , ' contains a mistake: ' , detail , ' should be capitalized.' +] diff --git a/src/Microdown-Rules/MicEnglishTypoChecker.class.st b/src/Microdown-Rules/MicEnglishTypoChecker.class.st index e4c38766..43a90d69 100644 --- a/src/Microdown-Rules/MicEnglishTypoChecker.class.st +++ b/src/Microdown-Rules/MicEnglishTypoChecker.class.st @@ -6,6 +6,11 @@ Class { #tag : 'EnglishTypographic' } +{ #category : 'as yet unclassified' } +MicEnglishTypoChecker class >> checkerName [ + ^ 'EnglishTypographic' +] + { #category : 'adding' } MicEnglishTypoChecker >> addResultFor: anElement message: aMessage [ results add: (MicSpaceBeforeDiacriticsResult new @@ -45,6 +50,11 @@ checks := { ]. ] +{ #category : 'as yet unclassified' } +MicEnglishTypoChecker >> configureFrom: aConfiguration [ + ^ self +] + { #category : 'adding' } MicEnglishTypoChecker >> visitCode: aCodeBlock [ diff --git a/src/Microdown-Rules/MicFirstElementOfHeaderIsNotCapitalizedResult.class.st b/src/Microdown-Rules/MicFirstElementOfHeaderIsNotCapitalizedResult.class.st index 4713f94a..2b23ff82 100644 --- a/src/Microdown-Rules/MicFirstElementOfHeaderIsNotCapitalizedResult.class.st +++ b/src/Microdown-Rules/MicFirstElementOfHeaderIsNotCapitalizedResult.class.st @@ -9,6 +9,12 @@ Class { #tag : 'Capitalization' } +{ #category : 'accessing' } +MicFirstElementOfHeaderIsNotCapitalizedResult >> detail [ + + ^ detail +] + { #category : 'accessing' } MicFirstElementOfHeaderIsNotCapitalizedResult >> detail: aString [ diff --git a/src/Microdown-Rules/MicLastPeriodChecker.class.st b/src/Microdown-Rules/MicLastPeriodChecker.class.st index 6bcfd611..12066de7 100644 --- a/src/Microdown-Rules/MicLastPeriodChecker.class.st +++ b/src/Microdown-Rules/MicLastPeriodChecker.class.st @@ -9,6 +9,11 @@ Class { #tag : 'CodeLastPeriod' } +{ #category : 'as yet unclassified' } +MicLastPeriodChecker class >> checkerName [ + ^ 'CodeLastPeriod' +] + { #category : 'visiting' } MicLastPeriodChecker >> checkExtraPeriodIn: aMicCodeBlock [ diff --git a/src/Microdown-Rules/MicRuleHeaderChecker.class.st b/src/Microdown-Rules/MicRuleHeaderChecker.class.st index b83f4342..3b8fe970 100644 --- a/src/Microdown-Rules/MicRuleHeaderChecker.class.st +++ b/src/Microdown-Rules/MicRuleHeaderChecker.class.st @@ -11,6 +11,11 @@ Class { #tag : 'Capitalization' } +{ #category : 'as yet unclassified' } +MicRuleHeaderChecker class >> checkerName [ + ^ 'HeaderCapitalization' +] + { #category : 'initialization' } MicRuleHeaderChecker >> addUncapitalized: aString [ "Make sure that aString will not be capitalized" @@ -39,6 +44,14 @@ MicRuleHeaderChecker >> checkRest: words of: aMicHeader [ strategy checkRest: words of: aMicHeader ] +{ #category : 'as yet unclassified' } +MicRuleHeaderChecker >> configureFrom: aConfiguration [ + aConfiguration isNil ifTrue: [ ^ self ]. + aConfiguration = 'uppercase' + ifTrue: [ self verifyUppercase ] + ifFalse: [ self verifyLowercase ] +] + { #category : 'initialization' } MicRuleHeaderChecker >> initialize [ diff --git a/src/Microdown-Rules/MicVocabularyChecker.class.st b/src/Microdown-Rules/MicVocabularyChecker.class.st index fa0343ca..6e72dc43 100644 --- a/src/Microdown-Rules/MicVocabularyChecker.class.st +++ b/src/Microdown-Rules/MicVocabularyChecker.class.st @@ -9,6 +9,11 @@ Class { #tag : 'Vocabulary' } +{ #category : 'as yet unclassified' } +MicVocabularyChecker class >> checkerName [ + ^ 'Vocabulary' +] + { #category : 'visiting - inline elements' } MicVocabularyChecker >> checkText: aMicText [ @@ -21,6 +26,16 @@ MicVocabularyChecker >> checkText: aMicText [ patternPair: patternPair) ] ] ] +{ #category : 'as yet unclassified' } +MicVocabularyChecker >> configureFrom: aConfiguration [ + aConfiguration isCollection ifTrue: [ self pairs: aConfiguration ] +] + +{ #category : 'visiting - inline elements' } +MicVocabularyChecker >> pairs [ + ^ patternPairs +] + { #category : 'visiting - inline elements' } MicVocabularyChecker >> pairs: aCollectionOfPairs [