From 7e4b6453fa8e5decd9bbd536fd5b0740cc92a798 Mon Sep 17 00:00:00 2001 From: inatus Date: Sat, 15 Feb 2014 11:59:09 +0900 Subject: [PATCH] Add language tag retrieval function for non-alphabetical script support #15 --- src/pkg/go/doc/comment.go | 51 ++- src/pkg/go/doc/comment_ja_test.go | 328 ++++++++++++++++++ src/pkg/go/doc/comment_japanese_test.go | 81 ----- src/pkg/go/doc/ja.go | 35 ++ src/pkg/go/doc/japanese.go | 40 --- .../go/doc/nonalphabeticalscriptsupport.go | 23 ++ src/pkg/go/doc/nonlatincharactersupport.go | 36 -- 7 files changed, 425 insertions(+), 169 deletions(-) create mode 100644 src/pkg/go/doc/comment_ja_test.go delete mode 100644 src/pkg/go/doc/comment_japanese_test.go create mode 100644 src/pkg/go/doc/ja.go delete mode 100644 src/pkg/go/doc/japanese.go create mode 100644 src/pkg/go/doc/nonalphabeticalscriptsupport.go delete mode 100644 src/pkg/go/doc/nonlatincharactersupport.go diff --git a/src/pkg/go/doc/comment.go b/src/pkg/go/doc/comment.go index 167382b..096111f 100644 --- a/src/pkg/go/doc/comment.go +++ b/src/pkg/go/doc/comment.go @@ -7,6 +7,7 @@ package doc import ( + "encoding/json" "io" "regexp" "strings" @@ -181,21 +182,30 @@ func heading(line string) string { return "" } - // a heading must start with an uppercase letter - r, _ := utf8.DecodeRuneInString(line) - if (!unicode.IsLetter(r) || !unicode.IsUpper(r)) && !isValidNonLatinHeadCharacter(r) { - return "" + // check for non-alphabetical languages if a specific language is set + isValid := false + if commentLang != "" { + isValid = isValidNonAlphabeticalScriptHeader(line) } - // it must end in a letter or digit: - r, _ = utf8.DecodeLastRuneInString(line) - if !unicode.IsLetter(r) && !unicode.IsDigit(r) && !isValidNonLatinEndCharacter(r) { - return "" - } + // if the check of non-alphabetical languages is skipped or the result of the check is false, then check for alphabetical characters + if !isValid { + // a heading must start with an uppercase letter + r, _ := utf8.DecodeRuneInString(line) + if !unicode.IsLetter(r) || !unicode.IsUpper(r) { + return "" + } - // exclude lines with illegal characters - if strings.IndexAny(line, ",.;:!?+*/=()[]{}_^°&§~%#@<\">\\") >= 0 || hasInvalidNonLatinCharacters(line) { - return "" + // it must end in a letter or digit: + r, _ = utf8.DecodeLastRuneInString(line) + if !unicode.IsLetter(r) && !unicode.IsDigit(r) { + return "" + } + + // exclude lines with illegal characters + if strings.IndexAny(line, ",.;:!?+*/=()[]{}_^°&§~%#@<\">\\") >= 0 { + return "" + } } // allow "'" for possessive "'s" only @@ -226,6 +236,8 @@ type block struct { lines []string } +var commentLang string + var nonAlphaNumRx = regexp.MustCompile(`[^a-zA-Z0-9]`) func anchorID(line string) string { @@ -287,6 +299,7 @@ func ToHTML(w io.Writer, text string, words map[string]string) { w.Write(html_endpre) } } + commentLang = "" } func blocks(text string) []block { @@ -309,6 +322,20 @@ func blocks(text string) []block { unindent(lines) for i := 0; i < len(lines); { line := lines[i] + if i == 0 { + var langMap map[string]string + err := json.Unmarshal([]byte(line), &langMap) + if err != nil { + // go ahead + } else { + if langMap["language"] != "" { + // set language and go to the next line + commentLang = langMap["language"] + i++ + continue + } + } + } if isBlank(line) { // close paragraph close() diff --git a/src/pkg/go/doc/comment_ja_test.go b/src/pkg/go/doc/comment_ja_test.go new file mode 100644 index 0000000..82ac6e9 --- /dev/null +++ b/src/pkg/go/doc/comment_ja_test.go @@ -0,0 +1,328 @@ +package doc + +import ( + "bytes" + "testing" +) + +// Test case that has valid custom language setting. +func TestToHTMLWithValidSetting(t *testing.T) { + input := `{"language": "ja"} +これは導入部です。 + +これはヘッダです + +これはヘッダではありません。 + +コレも、ヘッダではないです + +ヘッダです + +此れもヘッダでないです。 + + インデントです。 + +此れはヘッダで須 + +これはヘッダでない! + +Header + +This is not a header. + +This is also not a header! + +This is also not a header! + +Not, a header + +not header` + + expected := `

+これは導入部です。 +

+

これはヘッダです

+

+これはヘッダではありません。 +

+

+コレも、ヘッダではないです +

+

ヘッダです

+

+此れもヘッダでないです。 +

+
インデントです。
+
+

此れはヘッダで須

+

+これはヘッダでない! +

+

Header

+

+This is not a header. +

+

+This is also not a header! +

+

+This is also not a header! +

+

+Not, a header +

+

+not header

+` + + executeTest(t, input, expected) +} + +// Test case that has no custom language setting. +// Only alphabetical script check should be done. +func TestToHTMLWithNoSetting(t *testing.T) { + input := ` +これは導入部です。 + +これはヘッダです + +これはヘッダではありません。 + +コレも、ヘッダではないです + +ヘッダです + +此れもヘッダでないです。 + + インデントです。 + +此れはヘッダで須 + +これはヘッダでない! + +Header + +This is not a header. + +This is also not a header! + +This is also not a header! + +Not, a header + +not header` + + expected := `

+これは導入部です。 +

+

+これはヘッダです +

+

+これはヘッダではありません。 +

+

+コレも、ヘッダではないです +

+

+ヘッダです +

+

+此れもヘッダでないです。 +

+
インデントです。
+
+

+此れはヘッダで須 +

+

+これはヘッダでない! +

+

Header

+

+This is not a header. +

+

+This is also not a header! +

+

+This is also not a header! +

+

+Not, a header +

+

+not header

+` + + executeTest(t, input, expected) +} + +// Test case that has custom language setting whose language is not supported. +// Only alphabetical script check should be done. +func TestToHTMLWithUnexistingLanguage(t *testing.T) { + input := `{"language": "not_existing"} +これは導入部です。 + +これはヘッダです + +これはヘッダではありません。 + +コレも、ヘッダではないです + +ヘッダです + +此れもヘッダでないです。 + + インデントです。 + +此れはヘッダで須 + +これはヘッダでない! + +Header + +This is not a header. + +This is also not a header! + +This is also not a header! + +Not, a header + +not header` + + expected := `

+これは導入部です。 +

+

+これはヘッダです +

+

+これはヘッダではありません。 +

+

+コレも、ヘッダではないです +

+

+ヘッダです +

+

+此れもヘッダでないです。 +

+
インデントです。
+
+

+此れはヘッダで須 +

+

+これはヘッダでない! +

+

Header

+

+This is not a header. +

+

+This is also not a header! +

+

+This is also not a header! +

+

+Not, a header +

+

+not header

+` + + executeTest(t, input, expected) +} + +// Test case that has invalid tag other than "language". +// Only alphabetical script check should be done. +func TestToHTMLWithInvalidTag(t *testing.T) { + input := `{"tongue": "ja"} +これは導入部です。 + +これはヘッダです + +これはヘッダではありません。 + +コレも、ヘッダではないです + +ヘッダです + +此れもヘッダでないです。 + + インデントです。 + +此れはヘッダで須 + +これはヘッダでない! + +Header + +This is not a header. + +This is also not a header! + +This is also not a header! + +Not, a header + +not header` + + expected := `

+{"tongue": "ja"} +これは導入部です。 +

+

+これはヘッダです +

+

+これはヘッダではありません。 +

+

+コレも、ヘッダではないです +

+

+ヘッダです +

+

+此れもヘッダでないです。 +

+
インデントです。
+
+

+此れはヘッダで須 +

+

+これはヘッダでない! +

+

Header

+

+This is not a header. +

+

+This is also not a header! +

+

+This is also not a header! +

+

+Not, a header +

+

+not header

+` + + executeTest(t, input, expected) +} + +func executeTest(t *testing.T, input string, expected string) { + var actual bytes.Buffer + ToHTML(&actual, input, nil) + if actual.String() != expected { + t.Errorf("expected: %v\nbut was: %v", expected, actual.String()) + } +} diff --git a/src/pkg/go/doc/comment_japanese_test.go b/src/pkg/go/doc/comment_japanese_test.go deleted file mode 100644 index 5594247..0000000 --- a/src/pkg/go/doc/comment_japanese_test.go +++ /dev/null @@ -1,81 +0,0 @@ -package doc - -import ( - "bytes" - "testing" -) - -func TestToHTML(t *testing.T) { - input := `これは導入部です。 - -これはヘッダです - -これはヘッダではありません。 - -コレも、ヘッダではないです - -ヘッダです - -此れもヘッダでないです。 - - インデントです。 - -此れはヘッダで須 - -これはヘッダでない! - -Header - -This is not a header. - -This is also not a header! - -This is also not a header! - -Not, a header - -not header` - - expected := `

-これは導入部です。 -

-

これはヘッダです

-

-これはヘッダではありません。 -

-

-コレも、ヘッダではないです -

-

ヘッダです

-

-此れもヘッダでないです。 -

-
インデントです。
-
-

此れはヘッダで須

-

-これはヘッダでない! -

-

Header

-

-This is not a header. -

-

-This is also not a header! -

-

-This is also not a header! -

-

-Not, a header -

-

-not header

-` - - var actual bytes.Buffer - ToHTML(&actual, input, nil) - if actual.String() != expected { - t.Errorf("expected: %v\nbut: %v", expected, actual.String()) - } -} diff --git a/src/pkg/go/doc/ja.go b/src/pkg/go/doc/ja.go new file mode 100644 index 0000000..8bd7c73 --- /dev/null +++ b/src/pkg/go/doc/ja.go @@ -0,0 +1,35 @@ +package doc + +import ( + "strings" + "unicode" + "unicode/utf8" +) + +type ja struct { +} + +func (f ja) isValidHeader(line string) bool { + // a heading must start with a letter of Hiragana, Katakana, or Chinese characters + r, _ := utf8.DecodeRuneInString(line) + hiragana := unicode.Range16{0x3041, 0x3093, 1} + katakana := unicode.Range16{0x30A1, 0x30F6, 1} + chineseCharactors := unicode.Range16{0x4E00, 0x9FA0, 1} + rt := unicode.RangeTable{R16: []unicode.Range16{hiragana, katakana, chineseCharactors}} + if !unicode.Is(&rt, r) { + return false + } + + // it must end in a letter of Hiragana, Katakana, or Chinese characters + r, _ = utf8.DecodeLastRuneInString(line) + if !unicode.Is(&rt, r) { + return false + } + + // exclude lines with illegal characters + if strings.IndexAny(line, "、。;:!?+*/=()「」{}_^&〜%#@<”>¥") >= 0 { + return false + } + + return true +} diff --git a/src/pkg/go/doc/japanese.go b/src/pkg/go/doc/japanese.go deleted file mode 100644 index c313b9a..0000000 --- a/src/pkg/go/doc/japanese.go +++ /dev/null @@ -1,40 +0,0 @@ -package doc - -import ( - "strings" - "unicode" -) - -type japanese struct { -} - -func (f japanese) isValidHead(r rune) bool { - hiragana := unicode.Range16{0x3041, 0x3093, 1} - katakana := unicode.Range16{0x30A1, 0x30F6, 1} - chineseCharactors := unicode.Range16{0x4E00, 0x9FA0, 1} - rt := unicode.RangeTable{R16: []unicode.Range16{hiragana, katakana, chineseCharactors}} - if unicode.Is(&rt, r) { - return true - } - return false - -} - -func (f japanese) isValidEnd(r rune) bool { - hiragana := unicode.Range16{0x3041, 0x3093, 1} - katakana := unicode.Range16{0x30A1, 0x30F6, 1} - chineseCharactors := unicode.Range16{0x4E00, 0x9FA0, 1} - rt := unicode.RangeTable{R16: []unicode.Range16{hiragana, katakana, chineseCharactors}} - if unicode.Is(&rt, r) { - return true - } - return false - -} - -func (f japanese) hasInvalidCharacters(line string) bool { - if strings.IndexAny(line, "、。;:!?+*/=()「」{}_^&〜%#@<”>¥") >= 0 { - return true - } - return false -} diff --git a/src/pkg/go/doc/nonalphabeticalscriptsupport.go b/src/pkg/go/doc/nonalphabeticalscriptsupport.go new file mode 100644 index 0000000..e639056 --- /dev/null +++ b/src/pkg/go/doc/nonalphabeticalscriptsupport.go @@ -0,0 +1,23 @@ +package doc + +import ( + "fmt" +) + +type language interface { + isValidHeader(line string) bool +} + +var languages = []language{ja{}} + +func isValidNonAlphabeticalScriptHeader(line string) bool { + for _, v := range languages { + if fmt.Sprintf("%T", v) == "doc."+commentLang { + if v.isValidHeader(line) { + return true + } + return false + } + } + return false +} diff --git a/src/pkg/go/doc/nonlatincharactersupport.go b/src/pkg/go/doc/nonlatincharactersupport.go deleted file mode 100644 index 1ff39d9..0000000 --- a/src/pkg/go/doc/nonlatincharactersupport.go +++ /dev/null @@ -1,36 +0,0 @@ -package doc - -type language interface { - isValidHead(r rune) bool - isValidEnd(r rune) bool - hasInvalidCharacters(line string) bool -} - -var languages = []language{japanese{}} - -func isValidNonLatinHeadCharacter(r rune) bool { - for _, v := range languages { - if v.isValidHead(r) { - return true - } - } - return false -} - -func isValidNonLatinEndCharacter(r rune) bool { - for _, v := range languages { - if v.isValidEnd(r) { - return true - } - } - return false -} - -func hasInvalidNonLatinCharacters(line string) bool { - for _, v := range languages { - if v.hasInvalidCharacters(line) { - return true - } - } - return false -}