From 10502673ade5abc763c24354008a7e29c570c879 Mon Sep 17 00:00:00 2001 From: "Vyacheslav N. Boyko" Date: Sat, 9 Dec 2017 22:57:41 +0300 Subject: [PATCH] initial commit with existing sources --- .gitignore | 41 +- build.gradle | 132 + gradle/wrapper/gradle-wrapper.jar | Bin 0 -> 54711 bytes gradle/wrapper/gradle-wrapper.properties | 5 + gradlew | 172 + gradlew.bat | 84 + .../java/ru/bvn13/voidforum/Application.java | 54 + .../java/ru/bvn13/voidforum/Constants.java | 21 + .../java/ru/bvn13/voidforum/JpaConfig.java | 104 + .../java/ru/bvn13/voidforum/RedisConfig.java | 59 + .../ru/bvn13/voidforum/SecurityConfig.java | 67 + .../java/ru/bvn13/voidforum/WebConfig.java | 66 + .../voidforum/controllers/HomeController.java | 87 + .../voidforum/controllers/PostController.java | 84 + .../controllers/StoredFileController.java | 61 + .../controllers/SympathyController.java | 69 + .../voidforum/controllers/TagController.java | 58 + .../voidforum/controllers/TestController.java | 22 + .../voidforum/controllers/UserController.java | 90 + .../account/AccountController.java | 23 + .../account/CommentController.java | 23 + .../controllers/account/PostController.java | 193 + .../account/StoredFileController.java | 135 + .../controllers/account/UserController.java | 71 + .../controllers/admin/AdminController.java | 60 + .../controllers/admin/PostController.java | 184 + .../admin/SeoRobotAgentController.java | 70 + .../admin/StoredFileController.java | 135 + .../controllers/admin/UserController.java | 66 + .../controllers/seo/SitemapController.java | 32 + .../voidforum/error/EmailExistsException.java | 14 + .../error/ExceptionHandlerController.java | 53 + .../error/NicknameExistsException.java | 15 + .../voidforum/error/NotFoundException.java | 25 + .../ru/bvn13/voidforum/forms/CommentForm.java | 29 + .../ru/bvn13/voidforum/forms/LikeForm.java | 13 + .../ru/bvn13/voidforum/forms/PostForm.java | 117 + .../voidforum/forms/RegistrationForm.java | 30 + .../voidforum/forms/SeoRobotAgentForm.java | 18 + .../bvn13/voidforum/forms/SettingsForm.java | 30 + .../bvn13/voidforum/forms/StoredFileForm.java | 22 + .../ru/bvn13/voidforum/forms/UserForm.java | 22 + .../ru/bvn13/voidforum/models/BaseModel.java | 80 + .../ru/bvn13/voidforum/models/Comment.java | 49 + .../java/ru/bvn13/voidforum/models/Like.java | 32 + .../java/ru/bvn13/voidforum/models/Post.java | 101 + .../ru/bvn13/voidforum/models/Privilege.java | 26 + .../java/ru/bvn13/voidforum/models/Role.java | 34 + .../bvn13/voidforum/models/SeoPostData.java | 42 + .../bvn13/voidforum/models/SeoRobotAgent.java | 30 + .../ru/bvn13/voidforum/models/Setting.java | 30 + .../ru/bvn13/voidforum/models/StoredFile.java | 64 + .../java/ru/bvn13/voidforum/models/Tag.java | 32 + .../java/ru/bvn13/voidforum/models/User.java | 70 + .../java/ru/bvn13/voidforum/models/Visit.java | 32 + .../models/support/CommentFormat.java | 27 + .../support/HttpContentTypeSerializer.java | 40 + .../voidforum/models/support/OgLocale.java | 31 + .../voidforum/models/support/OgType.java | 27 + .../voidforum/models/support/PostFormat.java | 28 + .../voidforum/models/support/PostStatus.java | 32 + .../voidforum/models/support/PostType.java | 32 + .../voidforum/models/support/WebError.java | 21 + .../repositories/CommentRepository.java | 18 + .../repositories/LikeRepository.java | 22 + .../repositories/PostRepository.java | 49 + .../repositories/PrivilegeRepository.java | 22 + .../repositories/RoleRepository.java | 17 + .../repositories/SeoPostDataRepository.java | 9 + .../repositories/SeoRobotAgentRepository.java | 8 + .../repositories/SettingRepository.java | 15 + .../repositories/StoredFileRepository.java | 15 + .../voidforum/repositories/TagRepository.java | 11 + .../repositories/UserRepository.java | 29 + .../repositories/VisitRepository.java | 29 + .../bvn13/voidforum/services/AppSetting.java | 93 + .../services/CacheSettingService.java | 71 + .../voidforum/services/CommentService.java | 88 + .../services/FileStorageService.java | 116 + .../bvn13/voidforum/services/LikeService.java | 68 + .../bvn13/voidforum/services/PostService.java | 359 ++ .../voidforum/services/PrivilegeService.java | 13 + .../services/RequestProcessorService.java | 23 + .../bvn13/voidforum/services/RoleService.java | 15 + .../services/SeoRobotAgentService.java | 10 + .../bvn13/voidforum/services/SeoService.java | 81 + .../voidforum/services/SettingService.java | 12 + .../bvn13/voidforum/services/TagService.java | 63 + .../bvn13/voidforum/services/UserService.java | 233 + .../voidforum/services/VisitService.java | 103 + .../voidforum/support/InitialDataLoader.java | 133 + .../support/web/FlexmarkMarkdownService.java | 48 + .../support/web/MarkdownService.java | 8 + .../bvn13/voidforum/support/web/Message.java | 46 + .../voidforum/support/web/MessageHelper.java | 53 + .../support/web/SyntaxHighlightService.java | 8 + .../voidforum/support/web/ViewHelperVF.java | 133 + .../ru/bvn13/voidforum/utils/DTOUtil.java | 55 + src/main/resources/application.yml | 46 + src/main/resources/i18n/messages.properties | 7 + src/main/resources/logback.xml | 37 + .../resources/css/account/account.css | 45 + .../resources/resources/css/admin/admin.css | 45 + src/main/resources/resources/css/modal.css | 90 + src/main/resources/resources/css/mystyle.css | 177 + .../resources/resources/css/theme-light.css | 275 + src/main/resources/resources/css/theme.css | 190 + .../resources/resources/images/dislike.png | Bin 0 -> 673 bytes .../resources/images/dislike_min.png | Bin 0 -> 537 bytes src/main/resources/resources/images/like.png | Bin 0 -> 679 bytes .../resources/resources/images/like_min.png | Bin 0 -> 532 bytes .../images/open-eye-with-blank-pupil.png | Bin 0 -> 809 bytes .../images/open-eye-with-blank-pupil_min.png | Bin 0 -> 519 bytes .../vendors/bootstrap-paginator-1.0.2/LICENSE | 13 + .../bootstrap-paginator-1.0.2/README.md | 36 + .../js/bootstrap-paginator.min.js | 1 + .../resources/vendors/marked-0.3.6/.gitignore | 1 + .../resources/vendors/marked-0.3.6/.npmignore | 2 + .../vendors/marked-0.3.6/.travis.yml | 5 + .../vendors/marked-0.3.6/Gulpfile.js | 22 + .../resources/vendors/marked-0.3.6/LICENSE | 19 + .../resources/vendors/marked-0.3.6/Makefile | 12 + .../resources/vendors/marked-0.3.6/README.md | 406 ++ .../resources/vendors/marked-0.3.6/bin/marked | 187 + .../resources/vendors/marked-0.3.6/bower.json | 24 + .../vendors/marked-0.3.6/component.json | 10 + .../vendors/marked-0.3.6/doc/broken.md | 426 ++ .../vendors/marked-0.3.6/doc/todo.md | 2 + .../resources/vendors/marked-0.3.6/index.js | 1 + .../vendors/marked-0.3.6/lib/marked.js | 1286 ++++ .../vendors/marked-0.3.6/man/marked.1 | 91 + .../vendors/marked-0.3.6/marked.min.js | 6 + .../vendors/marked-0.3.6/package.json | 24 + .../vendors/marked-0.3.6/test/README | 10 + .../marked-0.3.6/test/browser/index.html | 5 + .../marked-0.3.6/test/browser/index.js | 41 + .../vendors/marked-0.3.6/test/browser/test.js | 62 + .../vendors/marked-0.3.6/test/index.js | 541 ++ .../marked-0.3.6/test/new/autolink_lines.html | 3 + .../marked-0.3.6/test/new/autolink_lines.text | 2 + .../test/new/blockquote_list_item.html | 3 + .../test/new/blockquote_list_item.text | 4 + .../test/new/case_insensitive_refs.html | 1 + .../test/new/case_insensitive_refs.text | 3 + .../marked-0.3.6/test/new/def_blocks.html | 28 + .../marked-0.3.6/test/new/def_blocks.text | 21 + .../marked-0.3.6/test/new/double_link.html | 5 + .../marked-0.3.6/test/new/double_link.text | 5 + .../marked-0.3.6/test/new/escaped_angles.html | 1 + .../marked-0.3.6/test/new/escaped_angles.text | 1 + .../test/new/gfm_break.breaks.html | 1 + .../test/new/gfm_break.breaks.text | 3 + .../marked-0.3.6/test/new/gfm_code.html | 10 + .../marked-0.3.6/test/new/gfm_code.text | 27 + .../test/new/gfm_code_hr_list.html | 52 + .../test/new/gfm_code_hr_list.text | 53 + .../marked-0.3.6/test/new/gfm_del.html | 1 + .../marked-0.3.6/test/new/gfm_del.text | 1 + .../vendors/marked-0.3.6/test/new/gfm_em.html | 1 + .../vendors/marked-0.3.6/test/new/gfm_em.text | 1 + .../test/new/gfm_hashtag.gfm.html | 5 + .../test/new/gfm_hashtag.gfm.text | 5 + .../test/new/gfm_hashtag.nogfm.html | 5 + .../test/new/gfm_hashtag.nogfm.text | 5 + .../marked-0.3.6/test/new/gfm_links.html | 2 + .../marked-0.3.6/test/new/gfm_links.text | 1 + .../marked-0.3.6/test/new/gfm_tables.html | 37 + .../marked-0.3.6/test/new/gfm_tables.text | 21 + .../marked-0.3.6/test/new/hr_list_break.html | 10 + .../marked-0.3.6/test/new/hr_list_break.text | 6 + .../test/new/lazy_blockquotes.html | 4 + .../test/new/lazy_blockquotes.text | 2 + .../marked-0.3.6/test/new/list_item_text.html | 1 + .../marked-0.3.6/test/new/list_item_text.text | 5 + .../marked-0.3.6/test/new/loose_lists.html | 62 + .../marked-0.3.6/test/new/loose_lists.text | 59 + .../vendors/marked-0.3.6/test/new/main.html | 4 + .../vendors/marked-0.3.6/test/new/main.text | 55 + .../marked-0.3.6/test/new/nested_code.html | 1 + .../marked-0.3.6/test/new/nested_code.text | 1 + .../marked-0.3.6/test/new/nested_em.html | 3 + .../marked-0.3.6/test/new/nested_em.text | 3 + .../test/new/nested_square_link.html | 1 + .../test/new/nested_square_link.text | 1 + .../marked-0.3.6/test/new/not_a_link.html | 1 + .../marked-0.3.6/test/new/not_a_link.text | 1 + .../marked-0.3.6/test/new/ref_paren.html | 1 + .../marked-0.3.6/test/new/ref_paren.text | 3 + .../marked-0.3.6/test/new/same_bullet.html | 5 + .../marked-0.3.6/test/new/same_bullet.text | 3 + .../test/new/text.smartypants.html | 6 + .../test/new/text.smartypants.text | 6 + .../test/new/toplevel_paragraphs.gfm.html | 34 + .../test/new/toplevel_paragraphs.gfm.text | 37 + .../marked-0.3.6/test/new/tricky_list.html | 23 + .../marked-0.3.6/test/new/tricky_list.text | 15 + .../original/amps_and_angles_encoding.html | 17 + .../original/amps_and_angles_encoding.text | 21 + .../test/original/auto_links.html | 18 + .../test/original/auto_links.text | 13 + .../test/original/backslash_escapes.html | 118 + .../test/original/backslash_escapes.text | 120 + .../blockquotes_with_code_blocks.html | 15 + .../blockquotes_with_code_blocks.text | 11 + .../test/original/code_blocks.html | 18 + .../test/original/code_blocks.text | 14 + .../test/original/code_spans.html | 6 + .../test/original/code_spans.text | 6 + ...apped_paragraphs_with_list_like_lines.html | 8 + ...apped_paragraphs_with_list_like_lines.text | 8 + .../test/original/horizontal_rules.html | 71 + .../test/original/horizontal_rules.text | 67 + .../test/original/inline_html_advanced.html | 15 + .../test/original/inline_html_advanced.text | 15 + .../test/original/inline_html_comments.html | 13 + .../test/original/inline_html_comments.text | 13 + .../test/original/inline_html_simple.html | 72 + .../test/original/inline_html_simple.text | 69 + .../test/original/links_inline_style.html | 15 + .../test/original/links_inline_style.text | 15 + .../test/original/links_reference_style.html | 52 + .../test/original/links_reference_style.text | 71 + .../original/links_shortcut_references.html | 9 + .../original/links_shortcut_references.text | 20 + .../original/literal_quotes_in_titles.html | 3 + .../original/literal_quotes_in_titles.text | 7 + .../markdown_documentation_basics.html | 314 + .../markdown_documentation_basics.text | 306 + .../markdown_documentation_syntax.html | 942 +++ .../markdown_documentation_syntax.text | 888 +++ .../test/original/nested_blockquotes.html | 9 + .../test/original/nested_blockquotes.text | 5 + .../original/ordered_and_unordered_lists.html | 148 + .../original/ordered_and_unordered_lists.text | 131 + .../test/original/strong_and_em_together.html | 7 + .../test/original/strong_and_em_together.text | 7 + .../marked-0.3.6/test/original/tabs.html | 25 + .../marked-0.3.6/test/original/tabs.text | 21 + .../marked-0.3.6/test/original/tidyness.html | 8 + .../marked-0.3.6/test/original/tidyness.text | 5 + .../test/tests/amps_and_angles_encoding.html | 17 + .../test/tests/amps_and_angles_encoding.text | 21 + .../marked-0.3.6/test/tests/auto_links.html | 18 + .../marked-0.3.6/test/tests/auto_links.text | 13 + .../test/tests/autolink_lines.html | 3 + .../test/tests/autolink_lines.text | 2 + .../test/tests/backslash_escapes.html | 118 + .../test/tests/backslash_escapes.text | 120 + .../test/tests/blockquote_list_item.html | 3 + .../test/tests/blockquote_list_item.text | 4 + .../tests/blockquotes_with_code_blocks.html | 15 + .../tests/blockquotes_with_code_blocks.text | 11 + .../test/tests/case_insensitive_refs.html | 1 + .../test/tests/case_insensitive_refs.text | 3 + .../marked-0.3.6/test/tests/code_blocks.html | 18 + .../marked-0.3.6/test/tests/code_blocks.text | 14 + .../marked-0.3.6/test/tests/code_spans.html | 6 + .../marked-0.3.6/test/tests/code_spans.text | 6 + .../marked-0.3.6/test/tests/def_blocks.html | 28 + .../marked-0.3.6/test/tests/def_blocks.text | 21 + .../marked-0.3.6/test/tests/double_link.html | 5 + .../marked-0.3.6/test/tests/double_link.text | 5 + .../test/tests/escaped_angles.html | 1 + .../test/tests/escaped_angles.text | 1 + .../test/tests/gfm_break.breaks.html | 1 + .../test/tests/gfm_break.breaks.text | 3 + .../marked-0.3.6/test/tests/gfm_code.html | 10 + .../marked-0.3.6/test/tests/gfm_code.text | 27 + .../test/tests/gfm_code_hr_list.html | 52 + .../test/tests/gfm_code_hr_list.text | 53 + .../marked-0.3.6/test/tests/gfm_del.html | 1 + .../marked-0.3.6/test/tests/gfm_del.text | 1 + .../marked-0.3.6/test/tests/gfm_em.html | 1 + .../marked-0.3.6/test/tests/gfm_em.text | 1 + .../test/tests/gfm_hashtag.gfm.html | 5 + .../test/tests/gfm_hashtag.gfm.text | 5 + .../test/tests/gfm_hashtag.nogfm.html | 5 + .../test/tests/gfm_hashtag.nogfm.text | 5 + .../marked-0.3.6/test/tests/gfm_links.html | 2 + .../marked-0.3.6/test/tests/gfm_links.text | 1 + .../marked-0.3.6/test/tests/gfm_tables.html | 37 + .../marked-0.3.6/test/tests/gfm_tables.text | 21 + ...paragraphs_with_list_like_lines.nogfm.html | 8 + ...paragraphs_with_list_like_lines.nogfm.text | 8 + .../test/tests/horizontal_rules.html | 71 + .../test/tests/horizontal_rules.text | 67 + .../test/tests/hr_list_break.html | 10 + .../test/tests/hr_list_break.text | 6 + .../test/tests/inline_html_advanced.html | 15 + .../test/tests/inline_html_advanced.text | 15 + .../test/tests/inline_html_comments.html | 13 + .../test/tests/inline_html_comments.text | 13 + .../test/tests/inline_html_simple.html | 72 + .../test/tests/inline_html_simple.text | 69 + .../test/tests/lazy_blockquotes.html | 4 + .../test/tests/lazy_blockquotes.text | 2 + .../test/tests/links.sanitize.html | 4 + .../test/tests/links.sanitize.text | 7 + .../test/tests/links_inline_style.html | 15 + .../test/tests/links_inline_style.text | 15 + .../test/tests/links_reference_style.html | 52 + .../test/tests/links_reference_style.text | 71 + .../test/tests/links_shortcut_references.html | 9 + .../test/tests/links_shortcut_references.text | 20 + .../test/tests/list_item_text.html | 1 + .../test/tests/list_item_text.text | 5 + .../test/tests/literal_quotes_in_titles.html | 3 + .../test/tests/literal_quotes_in_titles.text | 7 + .../marked-0.3.6/test/tests/loose_lists.html | 62 + .../marked-0.3.6/test/tests/loose_lists.text | 59 + .../vendors/marked-0.3.6/test/tests/main.html | 4 + .../vendors/marked-0.3.6/test/tests/main.text | 55 + .../tests/markdown_documentation_basics.html | 314 + .../tests/markdown_documentation_basics.text | 306 + .../tests/markdown_documentation_syntax.html | 942 +++ .../tests/markdown_documentation_syntax.text | 888 +++ .../test/tests/nested_blockquotes.html | 9 + .../test/tests/nested_blockquotes.text | 5 + .../marked-0.3.6/test/tests/nested_code.html | 1 + .../marked-0.3.6/test/tests/nested_code.text | 1 + .../marked-0.3.6/test/tests/nested_em.html | 3 + .../marked-0.3.6/test/tests/nested_em.text | 3 + .../test/tests/nested_square_link.html | 1 + .../test/tests/nested_square_link.text | 1 + .../marked-0.3.6/test/tests/not_a_link.html | 1 + .../marked-0.3.6/test/tests/not_a_link.text | 1 + .../tests/ordered_and_unordered_lists.html | 148 + .../tests/ordered_and_unordered_lists.text | 131 + .../marked-0.3.6/test/tests/ref_paren.html | 1 + .../marked-0.3.6/test/tests/ref_paren.text | 3 + .../marked-0.3.6/test/tests/same_bullet.html | 5 + .../marked-0.3.6/test/tests/same_bullet.text | 3 + .../test/tests/strong_and_em_together.html | 7 + .../test/tests/strong_and_em_together.text | 7 + .../vendors/marked-0.3.6/test/tests/tabs.html | 25 + .../vendors/marked-0.3.6/test/tests/tabs.text | 21 + .../test/tests/text.smartypants.html | 6 + .../test/tests/text.smartypants.text | 6 + .../marked-0.3.6/test/tests/tidyness.html | 8 + .../marked-0.3.6/test/tests/tidyness.text | 5 + .../test/tests/toplevel_paragraphs.gfm.html | 34 + .../test/tests/toplevel_paragraphs.gfm.text | 37 + .../marked-0.3.6/test/tests/tricky_list.html | 23 + .../marked-0.3.6/test/tests/tricky_list.text | 15 + .../resources/vendors/prism/prism.css | 327 + .../resources/vendors/prism/prism.js | 29 + .../resources/vendors/pygments/github.css | 61 + .../resources/vendors/pygments/monokai.css | 64 + .../vendors/simditor-2.3.6/images/image.png | Bin 0 -> 10706 bytes .../vendors/simditor-2.3.6/scripts/hotkeys.js | 241 + .../simditor-2.3.6/scripts/hotkeys.min.js | 7 + .../simditor-2.3.6/scripts/jquery.min.js | 5 + .../vendors/simditor-2.3.6/scripts/module.js | 172 + .../simditor-2.3.6/scripts/module.min.js | 3 + .../simditor-2.3.6/scripts/simditor.js | 5585 +++++++++++++++++ .../simditor-2.3.6/scripts/simditor.min.js | 11 + .../simditor-2.3.6/scripts/uploader.js | 261 + .../simditor-2.3.6/scripts/uploader.min.js | 7 + .../vendors/simditor-2.3.6/styles/editor.scss | 696 ++ .../simditor-2.3.6/styles/fonticon.scss | 1 + .../simditor-2.3.6/styles/simditor.css | 746 +++ .../simditor-2.3.6/styles/simditor.scss | 4 + .../lib/simditor-markdown.js | 146 + .../styles/simditor-markdown.css | 28 + .../vendors/to-markdown-3.1.0/.bowerrc | 3 + .../vendors/to-markdown-3.1.0/.editorconfig | 16 + .../vendors/to-markdown-3.1.0/.gitignore | 4 + .../vendors/to-markdown-3.1.0/.travis.yml | 17 + .../vendors/to-markdown-3.1.0/LICENSE | 20 + .../vendors/to-markdown-3.1.0/README.md | 164 + .../vendors/to-markdown-3.1.0/bower.json | 26 + .../vendors/to-markdown-3.1.0/index.js | 233 + .../to-markdown-3.1.0/lib/gfm-converters.js | 110 + .../to-markdown-3.1.0/lib/html-parser.js | 76 + .../to-markdown-3.1.0/lib/md-converters.js | 154 + .../vendors/to-markdown-3.1.0/package.json | 37 + .../to-markdown-3.1.0/test/gfm-test.js | 216 + .../vendors/to-markdown-3.1.0/test/index.html | 16 + .../test/to-markdown-test.js | 458 ++ .../vendors/to-markdown-3.1.0/testem.yml | 39 + .../vendors/typo.css-2.1.2/.gitignore | 1 + .../vendors/typo.css-2.1.2/README.md | 43 + .../vendors/typo.css-2.1.2/license.txt | 22 + .../resources/vendors/typo.css-2.1.2/typo.css | 345 + .../vendors/typo.css-2.1.2/typo.html | 430 ++ .../vendors/typo.css-2.1.2/typo.min.css | 1 + src/main/resources/static/favicon-16x16.png | Bin 0 -> 1065 bytes src/main/resources/static/favicon-32x32.png | Bin 0 -> 1834 bytes src/main/resources/static/favicon.ico | Bin 0 -> 15086 bytes src/main/resources/static/robots.txt | 5 + .../templates/account/files/edit.jade | 32 + .../files/fragments/fileUploadForm.jade | 7 + .../account/files/fragments/list.jade | 43 + .../templates/account/files/index.jade | 11 + .../templates/account/files/status.jade | 12 + .../templates/account/home/index.jade | 5 + .../templates/account/layout/account.jade | 11 + .../templates/account/layout/footer.jade | 0 .../templates/account/layout/head.jade | 32 + .../templates/account/layout/message.jade | 4 + .../templates/account/layout/navbar.jade | 26 + .../templates/account/posts/edit.jade | 87 + .../templates/account/posts/index.jade | 75 + .../templates/account/posts/new.jade | 114 + .../templates/account/users/profile.jade | 43 + .../resources/templates/admin/files/edit.jade | 32 + .../admin/files/fragments/fileUploadForm.jade | 7 + .../templates/admin/files/fragments/list.jade | 45 + .../templates/admin/files/index.jade | 11 + .../templates/admin/files/status.jade | 12 + .../resources/templates/admin/home/index.jade | 5 + .../templates/admin/home/settings.jade | 37 + .../templates/admin/layout/admin.jade | 11 + .../templates/admin/layout/footer.jade | 0 .../templates/admin/layout/head.jade | 32 + .../templates/admin/layout/message.jade | 4 + .../templates/admin/layout/navbar.jade | 28 + .../resources/templates/admin/posts/edit.jade | 167 + .../templates/admin/posts/index.jade | 74 + .../resources/templates/admin/posts/new.jade | 118 + .../templates/admin/robotsAgents/edit.jade | 7 + .../fragments/seoRobotAgentForm.jade | 33 + .../templates/admin/robotsAgents/index.jade | 45 + .../templates/admin/users/profile.jade | 43 + .../resources/templates/comments/deleted.jade | 12 + .../fragments/commentCreationForm.jade | 8 + .../resources/templates/comments/list.jade | 10 + .../resources/templates/comments/one.jade | 21 + src/main/resources/templates/error.jade | 1 + .../resources/templates/error/general.jade | 12 + .../resources/templates/fragments/disqus.jade | 0 .../resources/templates/fragments/ga.jade | 1 + .../templates/fragments/ya-metrics.jade | 36 + src/main/resources/templates/home/about.jade | 16 + src/main/resources/templates/home/index.jade | 14 + src/main/resources/templates/layout/app.jade | 19 + .../resources/templates/layout/footer.jade | 12 + src/main/resources/templates/layout/head.jade | 66 + .../resources/templates/layout/navbar.jade | 30 + src/main/resources/templates/layout/top.jade | 5 + .../resources/templates/posts/archive.jade | 24 + .../templates/posts/fragments/social.jade | 49 + .../posts/fragments/socialReadonly.jade | 7 + src/main/resources/templates/posts/list.jade | 97 + .../resources/templates/posts/projects.jade | 4 + src/main/resources/templates/posts/show.jade | 68 + src/main/resources/templates/tags/index.jade | 14 + src/main/resources/templates/tags/show.jade | 10 + src/main/resources/templates/tests/1.html | 12 + src/main/resources/templates/tests/2.jade | 2 + src/main/resources/templates/tests/3.html | 12 + .../resources/templates/users/register.jade | 24 + .../resources/templates/users/signin.jade | 20 + .../voidforum/VoidForumApplicationTests.java | 16 + 454 files changed, 31188 insertions(+), 19 deletions(-) create mode 100644 build.gradle create mode 100644 gradle/wrapper/gradle-wrapper.jar create mode 100644 gradle/wrapper/gradle-wrapper.properties create mode 100644 gradlew create mode 100644 gradlew.bat create mode 100644 src/main/java/ru/bvn13/voidforum/Application.java create mode 100644 src/main/java/ru/bvn13/voidforum/Constants.java create mode 100644 src/main/java/ru/bvn13/voidforum/JpaConfig.java create mode 100644 src/main/java/ru/bvn13/voidforum/RedisConfig.java create mode 100644 src/main/java/ru/bvn13/voidforum/SecurityConfig.java create mode 100644 src/main/java/ru/bvn13/voidforum/WebConfig.java create mode 100644 src/main/java/ru/bvn13/voidforum/controllers/HomeController.java create mode 100644 src/main/java/ru/bvn13/voidforum/controllers/PostController.java create mode 100644 src/main/java/ru/bvn13/voidforum/controllers/StoredFileController.java create mode 100644 src/main/java/ru/bvn13/voidforum/controllers/SympathyController.java create mode 100644 src/main/java/ru/bvn13/voidforum/controllers/TagController.java create mode 100644 src/main/java/ru/bvn13/voidforum/controllers/TestController.java create mode 100644 src/main/java/ru/bvn13/voidforum/controllers/UserController.java create mode 100644 src/main/java/ru/bvn13/voidforum/controllers/account/AccountController.java create mode 100644 src/main/java/ru/bvn13/voidforum/controllers/account/CommentController.java create mode 100644 src/main/java/ru/bvn13/voidforum/controllers/account/PostController.java create mode 100644 src/main/java/ru/bvn13/voidforum/controllers/account/StoredFileController.java create mode 100644 src/main/java/ru/bvn13/voidforum/controllers/account/UserController.java create mode 100644 src/main/java/ru/bvn13/voidforum/controllers/admin/AdminController.java create mode 100644 src/main/java/ru/bvn13/voidforum/controllers/admin/PostController.java create mode 100644 src/main/java/ru/bvn13/voidforum/controllers/admin/SeoRobotAgentController.java create mode 100644 src/main/java/ru/bvn13/voidforum/controllers/admin/StoredFileController.java create mode 100644 src/main/java/ru/bvn13/voidforum/controllers/admin/UserController.java create mode 100644 src/main/java/ru/bvn13/voidforum/controllers/seo/SitemapController.java create mode 100644 src/main/java/ru/bvn13/voidforum/error/EmailExistsException.java create mode 100644 src/main/java/ru/bvn13/voidforum/error/ExceptionHandlerController.java create mode 100644 src/main/java/ru/bvn13/voidforum/error/NicknameExistsException.java create mode 100644 src/main/java/ru/bvn13/voidforum/error/NotFoundException.java create mode 100644 src/main/java/ru/bvn13/voidforum/forms/CommentForm.java create mode 100644 src/main/java/ru/bvn13/voidforum/forms/LikeForm.java create mode 100644 src/main/java/ru/bvn13/voidforum/forms/PostForm.java create mode 100644 src/main/java/ru/bvn13/voidforum/forms/RegistrationForm.java create mode 100644 src/main/java/ru/bvn13/voidforum/forms/SeoRobotAgentForm.java create mode 100644 src/main/java/ru/bvn13/voidforum/forms/SettingsForm.java create mode 100644 src/main/java/ru/bvn13/voidforum/forms/StoredFileForm.java create mode 100644 src/main/java/ru/bvn13/voidforum/forms/UserForm.java create mode 100644 src/main/java/ru/bvn13/voidforum/models/BaseModel.java create mode 100644 src/main/java/ru/bvn13/voidforum/models/Comment.java create mode 100644 src/main/java/ru/bvn13/voidforum/models/Like.java create mode 100644 src/main/java/ru/bvn13/voidforum/models/Post.java create mode 100644 src/main/java/ru/bvn13/voidforum/models/Privilege.java create mode 100644 src/main/java/ru/bvn13/voidforum/models/Role.java create mode 100644 src/main/java/ru/bvn13/voidforum/models/SeoPostData.java create mode 100644 src/main/java/ru/bvn13/voidforum/models/SeoRobotAgent.java create mode 100644 src/main/java/ru/bvn13/voidforum/models/Setting.java create mode 100644 src/main/java/ru/bvn13/voidforum/models/StoredFile.java create mode 100644 src/main/java/ru/bvn13/voidforum/models/Tag.java create mode 100644 src/main/java/ru/bvn13/voidforum/models/User.java create mode 100644 src/main/java/ru/bvn13/voidforum/models/Visit.java create mode 100644 src/main/java/ru/bvn13/voidforum/models/support/CommentFormat.java create mode 100644 src/main/java/ru/bvn13/voidforum/models/support/HttpContentTypeSerializer.java create mode 100644 src/main/java/ru/bvn13/voidforum/models/support/OgLocale.java create mode 100644 src/main/java/ru/bvn13/voidforum/models/support/OgType.java create mode 100644 src/main/java/ru/bvn13/voidforum/models/support/PostFormat.java create mode 100644 src/main/java/ru/bvn13/voidforum/models/support/PostStatus.java create mode 100644 src/main/java/ru/bvn13/voidforum/models/support/PostType.java create mode 100644 src/main/java/ru/bvn13/voidforum/models/support/WebError.java create mode 100644 src/main/java/ru/bvn13/voidforum/repositories/CommentRepository.java create mode 100644 src/main/java/ru/bvn13/voidforum/repositories/LikeRepository.java create mode 100644 src/main/java/ru/bvn13/voidforum/repositories/PostRepository.java create mode 100644 src/main/java/ru/bvn13/voidforum/repositories/PrivilegeRepository.java create mode 100644 src/main/java/ru/bvn13/voidforum/repositories/RoleRepository.java create mode 100644 src/main/java/ru/bvn13/voidforum/repositories/SeoPostDataRepository.java create mode 100644 src/main/java/ru/bvn13/voidforum/repositories/SeoRobotAgentRepository.java create mode 100644 src/main/java/ru/bvn13/voidforum/repositories/SettingRepository.java create mode 100644 src/main/java/ru/bvn13/voidforum/repositories/StoredFileRepository.java create mode 100644 src/main/java/ru/bvn13/voidforum/repositories/TagRepository.java create mode 100644 src/main/java/ru/bvn13/voidforum/repositories/UserRepository.java create mode 100644 src/main/java/ru/bvn13/voidforum/repositories/VisitRepository.java create mode 100644 src/main/java/ru/bvn13/voidforum/services/AppSetting.java create mode 100644 src/main/java/ru/bvn13/voidforum/services/CacheSettingService.java create mode 100644 src/main/java/ru/bvn13/voidforum/services/CommentService.java create mode 100644 src/main/java/ru/bvn13/voidforum/services/FileStorageService.java create mode 100644 src/main/java/ru/bvn13/voidforum/services/LikeService.java create mode 100644 src/main/java/ru/bvn13/voidforum/services/PostService.java create mode 100644 src/main/java/ru/bvn13/voidforum/services/PrivilegeService.java create mode 100644 src/main/java/ru/bvn13/voidforum/services/RequestProcessorService.java create mode 100644 src/main/java/ru/bvn13/voidforum/services/RoleService.java create mode 100644 src/main/java/ru/bvn13/voidforum/services/SeoRobotAgentService.java create mode 100644 src/main/java/ru/bvn13/voidforum/services/SeoService.java create mode 100644 src/main/java/ru/bvn13/voidforum/services/SettingService.java create mode 100644 src/main/java/ru/bvn13/voidforum/services/TagService.java create mode 100644 src/main/java/ru/bvn13/voidforum/services/UserService.java create mode 100644 src/main/java/ru/bvn13/voidforum/services/VisitService.java create mode 100644 src/main/java/ru/bvn13/voidforum/support/InitialDataLoader.java create mode 100644 src/main/java/ru/bvn13/voidforum/support/web/FlexmarkMarkdownService.java create mode 100644 src/main/java/ru/bvn13/voidforum/support/web/MarkdownService.java create mode 100644 src/main/java/ru/bvn13/voidforum/support/web/Message.java create mode 100644 src/main/java/ru/bvn13/voidforum/support/web/MessageHelper.java create mode 100644 src/main/java/ru/bvn13/voidforum/support/web/SyntaxHighlightService.java create mode 100644 src/main/java/ru/bvn13/voidforum/support/web/ViewHelperVF.java create mode 100644 src/main/java/ru/bvn13/voidforum/utils/DTOUtil.java create mode 100644 src/main/resources/application.yml create mode 100644 src/main/resources/i18n/messages.properties create mode 100644 src/main/resources/logback.xml create mode 100644 src/main/resources/resources/css/account/account.css create mode 100644 src/main/resources/resources/css/admin/admin.css create mode 100644 src/main/resources/resources/css/modal.css create mode 100644 src/main/resources/resources/css/mystyle.css create mode 100644 src/main/resources/resources/css/theme-light.css create mode 100644 src/main/resources/resources/css/theme.css create mode 100644 src/main/resources/resources/images/dislike.png create mode 100644 src/main/resources/resources/images/dislike_min.png create mode 100644 src/main/resources/resources/images/like.png create mode 100644 src/main/resources/resources/images/like_min.png create mode 100644 src/main/resources/resources/images/open-eye-with-blank-pupil.png create mode 100644 src/main/resources/resources/images/open-eye-with-blank-pupil_min.png create mode 100644 src/main/resources/resources/vendors/bootstrap-paginator-1.0.2/LICENSE create mode 100644 src/main/resources/resources/vendors/bootstrap-paginator-1.0.2/README.md create mode 100644 src/main/resources/resources/vendors/bootstrap-paginator-1.0.2/js/bootstrap-paginator.min.js create mode 100644 src/main/resources/resources/vendors/marked-0.3.6/.gitignore create mode 100644 src/main/resources/resources/vendors/marked-0.3.6/.npmignore create mode 100644 src/main/resources/resources/vendors/marked-0.3.6/.travis.yml create mode 100644 src/main/resources/resources/vendors/marked-0.3.6/Gulpfile.js create mode 100644 src/main/resources/resources/vendors/marked-0.3.6/LICENSE create mode 100644 src/main/resources/resources/vendors/marked-0.3.6/Makefile create mode 100644 src/main/resources/resources/vendors/marked-0.3.6/README.md create mode 100644 src/main/resources/resources/vendors/marked-0.3.6/bin/marked create mode 100644 src/main/resources/resources/vendors/marked-0.3.6/bower.json create mode 100644 src/main/resources/resources/vendors/marked-0.3.6/component.json create mode 100644 src/main/resources/resources/vendors/marked-0.3.6/doc/broken.md create mode 100644 src/main/resources/resources/vendors/marked-0.3.6/doc/todo.md create mode 100644 src/main/resources/resources/vendors/marked-0.3.6/index.js create mode 100644 src/main/resources/resources/vendors/marked-0.3.6/lib/marked.js create mode 100644 src/main/resources/resources/vendors/marked-0.3.6/man/marked.1 create mode 100644 src/main/resources/resources/vendors/marked-0.3.6/marked.min.js create mode 100644 src/main/resources/resources/vendors/marked-0.3.6/package.json create mode 100644 src/main/resources/resources/vendors/marked-0.3.6/test/README create mode 100644 src/main/resources/resources/vendors/marked-0.3.6/test/browser/index.html create mode 100644 src/main/resources/resources/vendors/marked-0.3.6/test/browser/index.js create mode 100644 src/main/resources/resources/vendors/marked-0.3.6/test/browser/test.js create mode 100644 src/main/resources/resources/vendors/marked-0.3.6/test/index.js create mode 100644 src/main/resources/resources/vendors/marked-0.3.6/test/new/autolink_lines.html create mode 100644 src/main/resources/resources/vendors/marked-0.3.6/test/new/autolink_lines.text create mode 100644 src/main/resources/resources/vendors/marked-0.3.6/test/new/blockquote_list_item.html create mode 100644 src/main/resources/resources/vendors/marked-0.3.6/test/new/blockquote_list_item.text create mode 100644 src/main/resources/resources/vendors/marked-0.3.6/test/new/case_insensitive_refs.html create mode 100644 src/main/resources/resources/vendors/marked-0.3.6/test/new/case_insensitive_refs.text create mode 100644 src/main/resources/resources/vendors/marked-0.3.6/test/new/def_blocks.html create mode 100644 src/main/resources/resources/vendors/marked-0.3.6/test/new/def_blocks.text create mode 100644 src/main/resources/resources/vendors/marked-0.3.6/test/new/double_link.html create mode 100644 src/main/resources/resources/vendors/marked-0.3.6/test/new/double_link.text create mode 100644 src/main/resources/resources/vendors/marked-0.3.6/test/new/escaped_angles.html create mode 100644 src/main/resources/resources/vendors/marked-0.3.6/test/new/escaped_angles.text create mode 100644 src/main/resources/resources/vendors/marked-0.3.6/test/new/gfm_break.breaks.html create mode 100644 src/main/resources/resources/vendors/marked-0.3.6/test/new/gfm_break.breaks.text create mode 100644 src/main/resources/resources/vendors/marked-0.3.6/test/new/gfm_code.html create mode 100644 src/main/resources/resources/vendors/marked-0.3.6/test/new/gfm_code.text create mode 100644 src/main/resources/resources/vendors/marked-0.3.6/test/new/gfm_code_hr_list.html create mode 100644 src/main/resources/resources/vendors/marked-0.3.6/test/new/gfm_code_hr_list.text create mode 100644 src/main/resources/resources/vendors/marked-0.3.6/test/new/gfm_del.html create mode 100644 src/main/resources/resources/vendors/marked-0.3.6/test/new/gfm_del.text create mode 100644 src/main/resources/resources/vendors/marked-0.3.6/test/new/gfm_em.html create mode 100644 src/main/resources/resources/vendors/marked-0.3.6/test/new/gfm_em.text create mode 100644 src/main/resources/resources/vendors/marked-0.3.6/test/new/gfm_hashtag.gfm.html create mode 100644 src/main/resources/resources/vendors/marked-0.3.6/test/new/gfm_hashtag.gfm.text create mode 100644 src/main/resources/resources/vendors/marked-0.3.6/test/new/gfm_hashtag.nogfm.html create mode 100644 src/main/resources/resources/vendors/marked-0.3.6/test/new/gfm_hashtag.nogfm.text create mode 100644 src/main/resources/resources/vendors/marked-0.3.6/test/new/gfm_links.html create mode 100644 src/main/resources/resources/vendors/marked-0.3.6/test/new/gfm_links.text create mode 100644 src/main/resources/resources/vendors/marked-0.3.6/test/new/gfm_tables.html create mode 100644 src/main/resources/resources/vendors/marked-0.3.6/test/new/gfm_tables.text create mode 100644 src/main/resources/resources/vendors/marked-0.3.6/test/new/hr_list_break.html create mode 100644 src/main/resources/resources/vendors/marked-0.3.6/test/new/hr_list_break.text create mode 100644 src/main/resources/resources/vendors/marked-0.3.6/test/new/lazy_blockquotes.html create mode 100644 src/main/resources/resources/vendors/marked-0.3.6/test/new/lazy_blockquotes.text create mode 100644 src/main/resources/resources/vendors/marked-0.3.6/test/new/list_item_text.html create mode 100644 src/main/resources/resources/vendors/marked-0.3.6/test/new/list_item_text.text create mode 100644 src/main/resources/resources/vendors/marked-0.3.6/test/new/loose_lists.html create mode 100644 src/main/resources/resources/vendors/marked-0.3.6/test/new/loose_lists.text create mode 100644 src/main/resources/resources/vendors/marked-0.3.6/test/new/main.html create mode 100644 src/main/resources/resources/vendors/marked-0.3.6/test/new/main.text create mode 100644 src/main/resources/resources/vendors/marked-0.3.6/test/new/nested_code.html create mode 100644 src/main/resources/resources/vendors/marked-0.3.6/test/new/nested_code.text create mode 100644 src/main/resources/resources/vendors/marked-0.3.6/test/new/nested_em.html create mode 100644 src/main/resources/resources/vendors/marked-0.3.6/test/new/nested_em.text create mode 100644 src/main/resources/resources/vendors/marked-0.3.6/test/new/nested_square_link.html create mode 100644 src/main/resources/resources/vendors/marked-0.3.6/test/new/nested_square_link.text create mode 100644 src/main/resources/resources/vendors/marked-0.3.6/test/new/not_a_link.html create mode 100644 src/main/resources/resources/vendors/marked-0.3.6/test/new/not_a_link.text create mode 100644 src/main/resources/resources/vendors/marked-0.3.6/test/new/ref_paren.html create mode 100644 src/main/resources/resources/vendors/marked-0.3.6/test/new/ref_paren.text create mode 100644 src/main/resources/resources/vendors/marked-0.3.6/test/new/same_bullet.html create mode 100644 src/main/resources/resources/vendors/marked-0.3.6/test/new/same_bullet.text create mode 100644 src/main/resources/resources/vendors/marked-0.3.6/test/new/text.smartypants.html create mode 100644 src/main/resources/resources/vendors/marked-0.3.6/test/new/text.smartypants.text create mode 100644 src/main/resources/resources/vendors/marked-0.3.6/test/new/toplevel_paragraphs.gfm.html create mode 100644 src/main/resources/resources/vendors/marked-0.3.6/test/new/toplevel_paragraphs.gfm.text create mode 100644 src/main/resources/resources/vendors/marked-0.3.6/test/new/tricky_list.html create mode 100644 src/main/resources/resources/vendors/marked-0.3.6/test/new/tricky_list.text create mode 100644 src/main/resources/resources/vendors/marked-0.3.6/test/original/amps_and_angles_encoding.html create mode 100644 src/main/resources/resources/vendors/marked-0.3.6/test/original/amps_and_angles_encoding.text create mode 100644 src/main/resources/resources/vendors/marked-0.3.6/test/original/auto_links.html create mode 100644 src/main/resources/resources/vendors/marked-0.3.6/test/original/auto_links.text create mode 100644 src/main/resources/resources/vendors/marked-0.3.6/test/original/backslash_escapes.html create mode 100644 src/main/resources/resources/vendors/marked-0.3.6/test/original/backslash_escapes.text create mode 100644 src/main/resources/resources/vendors/marked-0.3.6/test/original/blockquotes_with_code_blocks.html create mode 100644 src/main/resources/resources/vendors/marked-0.3.6/test/original/blockquotes_with_code_blocks.text create mode 100644 src/main/resources/resources/vendors/marked-0.3.6/test/original/code_blocks.html create mode 100644 src/main/resources/resources/vendors/marked-0.3.6/test/original/code_blocks.text create mode 100644 src/main/resources/resources/vendors/marked-0.3.6/test/original/code_spans.html create mode 100644 src/main/resources/resources/vendors/marked-0.3.6/test/original/code_spans.text create mode 100644 src/main/resources/resources/vendors/marked-0.3.6/test/original/hard_wrapped_paragraphs_with_list_like_lines.html create mode 100644 src/main/resources/resources/vendors/marked-0.3.6/test/original/hard_wrapped_paragraphs_with_list_like_lines.text create mode 100644 src/main/resources/resources/vendors/marked-0.3.6/test/original/horizontal_rules.html create mode 100644 src/main/resources/resources/vendors/marked-0.3.6/test/original/horizontal_rules.text create mode 100644 src/main/resources/resources/vendors/marked-0.3.6/test/original/inline_html_advanced.html create mode 100644 src/main/resources/resources/vendors/marked-0.3.6/test/original/inline_html_advanced.text create mode 100644 src/main/resources/resources/vendors/marked-0.3.6/test/original/inline_html_comments.html create mode 100644 src/main/resources/resources/vendors/marked-0.3.6/test/original/inline_html_comments.text create mode 100644 src/main/resources/resources/vendors/marked-0.3.6/test/original/inline_html_simple.html create mode 100644 src/main/resources/resources/vendors/marked-0.3.6/test/original/inline_html_simple.text create mode 100644 src/main/resources/resources/vendors/marked-0.3.6/test/original/links_inline_style.html create mode 100644 src/main/resources/resources/vendors/marked-0.3.6/test/original/links_inline_style.text create mode 100644 src/main/resources/resources/vendors/marked-0.3.6/test/original/links_reference_style.html create mode 100644 src/main/resources/resources/vendors/marked-0.3.6/test/original/links_reference_style.text create mode 100644 src/main/resources/resources/vendors/marked-0.3.6/test/original/links_shortcut_references.html create mode 100644 src/main/resources/resources/vendors/marked-0.3.6/test/original/links_shortcut_references.text create mode 100644 src/main/resources/resources/vendors/marked-0.3.6/test/original/literal_quotes_in_titles.html create mode 100644 src/main/resources/resources/vendors/marked-0.3.6/test/original/literal_quotes_in_titles.text create mode 100644 src/main/resources/resources/vendors/marked-0.3.6/test/original/markdown_documentation_basics.html create mode 100644 src/main/resources/resources/vendors/marked-0.3.6/test/original/markdown_documentation_basics.text create mode 100644 src/main/resources/resources/vendors/marked-0.3.6/test/original/markdown_documentation_syntax.html create mode 100644 src/main/resources/resources/vendors/marked-0.3.6/test/original/markdown_documentation_syntax.text create mode 100644 src/main/resources/resources/vendors/marked-0.3.6/test/original/nested_blockquotes.html create mode 100644 src/main/resources/resources/vendors/marked-0.3.6/test/original/nested_blockquotes.text create mode 100644 src/main/resources/resources/vendors/marked-0.3.6/test/original/ordered_and_unordered_lists.html create mode 100644 src/main/resources/resources/vendors/marked-0.3.6/test/original/ordered_and_unordered_lists.text create mode 100644 src/main/resources/resources/vendors/marked-0.3.6/test/original/strong_and_em_together.html create mode 100644 src/main/resources/resources/vendors/marked-0.3.6/test/original/strong_and_em_together.text create mode 100644 src/main/resources/resources/vendors/marked-0.3.6/test/original/tabs.html create mode 100644 src/main/resources/resources/vendors/marked-0.3.6/test/original/tabs.text create mode 100644 src/main/resources/resources/vendors/marked-0.3.6/test/original/tidyness.html create mode 100644 src/main/resources/resources/vendors/marked-0.3.6/test/original/tidyness.text create mode 100644 src/main/resources/resources/vendors/marked-0.3.6/test/tests/amps_and_angles_encoding.html create mode 100644 src/main/resources/resources/vendors/marked-0.3.6/test/tests/amps_and_angles_encoding.text create mode 100644 src/main/resources/resources/vendors/marked-0.3.6/test/tests/auto_links.html create mode 100644 src/main/resources/resources/vendors/marked-0.3.6/test/tests/auto_links.text create mode 100644 src/main/resources/resources/vendors/marked-0.3.6/test/tests/autolink_lines.html create mode 100644 src/main/resources/resources/vendors/marked-0.3.6/test/tests/autolink_lines.text create mode 100644 src/main/resources/resources/vendors/marked-0.3.6/test/tests/backslash_escapes.html create mode 100644 src/main/resources/resources/vendors/marked-0.3.6/test/tests/backslash_escapes.text create mode 100644 src/main/resources/resources/vendors/marked-0.3.6/test/tests/blockquote_list_item.html create mode 100644 src/main/resources/resources/vendors/marked-0.3.6/test/tests/blockquote_list_item.text create mode 100644 src/main/resources/resources/vendors/marked-0.3.6/test/tests/blockquotes_with_code_blocks.html create mode 100644 src/main/resources/resources/vendors/marked-0.3.6/test/tests/blockquotes_with_code_blocks.text create mode 100644 src/main/resources/resources/vendors/marked-0.3.6/test/tests/case_insensitive_refs.html create mode 100644 src/main/resources/resources/vendors/marked-0.3.6/test/tests/case_insensitive_refs.text create mode 100644 src/main/resources/resources/vendors/marked-0.3.6/test/tests/code_blocks.html create mode 100644 src/main/resources/resources/vendors/marked-0.3.6/test/tests/code_blocks.text create mode 100644 src/main/resources/resources/vendors/marked-0.3.6/test/tests/code_spans.html create mode 100644 src/main/resources/resources/vendors/marked-0.3.6/test/tests/code_spans.text create mode 100644 src/main/resources/resources/vendors/marked-0.3.6/test/tests/def_blocks.html create mode 100644 src/main/resources/resources/vendors/marked-0.3.6/test/tests/def_blocks.text create mode 100644 src/main/resources/resources/vendors/marked-0.3.6/test/tests/double_link.html create mode 100644 src/main/resources/resources/vendors/marked-0.3.6/test/tests/double_link.text create mode 100644 src/main/resources/resources/vendors/marked-0.3.6/test/tests/escaped_angles.html create mode 100644 src/main/resources/resources/vendors/marked-0.3.6/test/tests/escaped_angles.text create mode 100644 src/main/resources/resources/vendors/marked-0.3.6/test/tests/gfm_break.breaks.html create mode 100644 src/main/resources/resources/vendors/marked-0.3.6/test/tests/gfm_break.breaks.text create mode 100644 src/main/resources/resources/vendors/marked-0.3.6/test/tests/gfm_code.html create mode 100644 src/main/resources/resources/vendors/marked-0.3.6/test/tests/gfm_code.text create mode 100644 src/main/resources/resources/vendors/marked-0.3.6/test/tests/gfm_code_hr_list.html create mode 100644 src/main/resources/resources/vendors/marked-0.3.6/test/tests/gfm_code_hr_list.text create mode 100644 src/main/resources/resources/vendors/marked-0.3.6/test/tests/gfm_del.html create mode 100644 src/main/resources/resources/vendors/marked-0.3.6/test/tests/gfm_del.text create mode 100644 src/main/resources/resources/vendors/marked-0.3.6/test/tests/gfm_em.html create mode 100644 src/main/resources/resources/vendors/marked-0.3.6/test/tests/gfm_em.text create mode 100644 src/main/resources/resources/vendors/marked-0.3.6/test/tests/gfm_hashtag.gfm.html create mode 100644 src/main/resources/resources/vendors/marked-0.3.6/test/tests/gfm_hashtag.gfm.text create mode 100644 src/main/resources/resources/vendors/marked-0.3.6/test/tests/gfm_hashtag.nogfm.html create mode 100644 src/main/resources/resources/vendors/marked-0.3.6/test/tests/gfm_hashtag.nogfm.text create mode 100644 src/main/resources/resources/vendors/marked-0.3.6/test/tests/gfm_links.html create mode 100644 src/main/resources/resources/vendors/marked-0.3.6/test/tests/gfm_links.text create mode 100644 src/main/resources/resources/vendors/marked-0.3.6/test/tests/gfm_tables.html create mode 100644 src/main/resources/resources/vendors/marked-0.3.6/test/tests/gfm_tables.text create mode 100644 src/main/resources/resources/vendors/marked-0.3.6/test/tests/hard_wrapped_paragraphs_with_list_like_lines.nogfm.html create mode 100644 src/main/resources/resources/vendors/marked-0.3.6/test/tests/hard_wrapped_paragraphs_with_list_like_lines.nogfm.text create mode 100644 src/main/resources/resources/vendors/marked-0.3.6/test/tests/horizontal_rules.html create mode 100644 src/main/resources/resources/vendors/marked-0.3.6/test/tests/horizontal_rules.text create mode 100644 src/main/resources/resources/vendors/marked-0.3.6/test/tests/hr_list_break.html create mode 100644 src/main/resources/resources/vendors/marked-0.3.6/test/tests/hr_list_break.text create mode 100644 src/main/resources/resources/vendors/marked-0.3.6/test/tests/inline_html_advanced.html create mode 100644 src/main/resources/resources/vendors/marked-0.3.6/test/tests/inline_html_advanced.text create mode 100644 src/main/resources/resources/vendors/marked-0.3.6/test/tests/inline_html_comments.html create mode 100644 src/main/resources/resources/vendors/marked-0.3.6/test/tests/inline_html_comments.text create mode 100644 src/main/resources/resources/vendors/marked-0.3.6/test/tests/inline_html_simple.html create mode 100644 src/main/resources/resources/vendors/marked-0.3.6/test/tests/inline_html_simple.text create mode 100644 src/main/resources/resources/vendors/marked-0.3.6/test/tests/lazy_blockquotes.html create mode 100644 src/main/resources/resources/vendors/marked-0.3.6/test/tests/lazy_blockquotes.text create mode 100644 src/main/resources/resources/vendors/marked-0.3.6/test/tests/links.sanitize.html create mode 100644 src/main/resources/resources/vendors/marked-0.3.6/test/tests/links.sanitize.text create mode 100644 src/main/resources/resources/vendors/marked-0.3.6/test/tests/links_inline_style.html create mode 100644 src/main/resources/resources/vendors/marked-0.3.6/test/tests/links_inline_style.text create mode 100644 src/main/resources/resources/vendors/marked-0.3.6/test/tests/links_reference_style.html create mode 100644 src/main/resources/resources/vendors/marked-0.3.6/test/tests/links_reference_style.text create mode 100644 src/main/resources/resources/vendors/marked-0.3.6/test/tests/links_shortcut_references.html create mode 100644 src/main/resources/resources/vendors/marked-0.3.6/test/tests/links_shortcut_references.text create mode 100644 src/main/resources/resources/vendors/marked-0.3.6/test/tests/list_item_text.html create mode 100644 src/main/resources/resources/vendors/marked-0.3.6/test/tests/list_item_text.text create mode 100644 src/main/resources/resources/vendors/marked-0.3.6/test/tests/literal_quotes_in_titles.html create mode 100644 src/main/resources/resources/vendors/marked-0.3.6/test/tests/literal_quotes_in_titles.text create mode 100644 src/main/resources/resources/vendors/marked-0.3.6/test/tests/loose_lists.html create mode 100644 src/main/resources/resources/vendors/marked-0.3.6/test/tests/loose_lists.text create mode 100644 src/main/resources/resources/vendors/marked-0.3.6/test/tests/main.html create mode 100644 src/main/resources/resources/vendors/marked-0.3.6/test/tests/main.text create mode 100644 src/main/resources/resources/vendors/marked-0.3.6/test/tests/markdown_documentation_basics.html create mode 100644 src/main/resources/resources/vendors/marked-0.3.6/test/tests/markdown_documentation_basics.text create mode 100644 src/main/resources/resources/vendors/marked-0.3.6/test/tests/markdown_documentation_syntax.html create mode 100644 src/main/resources/resources/vendors/marked-0.3.6/test/tests/markdown_documentation_syntax.text create mode 100644 src/main/resources/resources/vendors/marked-0.3.6/test/tests/nested_blockquotes.html create mode 100644 src/main/resources/resources/vendors/marked-0.3.6/test/tests/nested_blockquotes.text create mode 100644 src/main/resources/resources/vendors/marked-0.3.6/test/tests/nested_code.html create mode 100644 src/main/resources/resources/vendors/marked-0.3.6/test/tests/nested_code.text create mode 100644 src/main/resources/resources/vendors/marked-0.3.6/test/tests/nested_em.html create mode 100644 src/main/resources/resources/vendors/marked-0.3.6/test/tests/nested_em.text create mode 100644 src/main/resources/resources/vendors/marked-0.3.6/test/tests/nested_square_link.html create mode 100644 src/main/resources/resources/vendors/marked-0.3.6/test/tests/nested_square_link.text create mode 100644 src/main/resources/resources/vendors/marked-0.3.6/test/tests/not_a_link.html create mode 100644 src/main/resources/resources/vendors/marked-0.3.6/test/tests/not_a_link.text create mode 100644 src/main/resources/resources/vendors/marked-0.3.6/test/tests/ordered_and_unordered_lists.html create mode 100644 src/main/resources/resources/vendors/marked-0.3.6/test/tests/ordered_and_unordered_lists.text create mode 100644 src/main/resources/resources/vendors/marked-0.3.6/test/tests/ref_paren.html create mode 100644 src/main/resources/resources/vendors/marked-0.3.6/test/tests/ref_paren.text create mode 100644 src/main/resources/resources/vendors/marked-0.3.6/test/tests/same_bullet.html create mode 100644 src/main/resources/resources/vendors/marked-0.3.6/test/tests/same_bullet.text create mode 100644 src/main/resources/resources/vendors/marked-0.3.6/test/tests/strong_and_em_together.html create mode 100644 src/main/resources/resources/vendors/marked-0.3.6/test/tests/strong_and_em_together.text create mode 100644 src/main/resources/resources/vendors/marked-0.3.6/test/tests/tabs.html create mode 100644 src/main/resources/resources/vendors/marked-0.3.6/test/tests/tabs.text create mode 100644 src/main/resources/resources/vendors/marked-0.3.6/test/tests/text.smartypants.html create mode 100644 src/main/resources/resources/vendors/marked-0.3.6/test/tests/text.smartypants.text create mode 100644 src/main/resources/resources/vendors/marked-0.3.6/test/tests/tidyness.html create mode 100644 src/main/resources/resources/vendors/marked-0.3.6/test/tests/tidyness.text create mode 100644 src/main/resources/resources/vendors/marked-0.3.6/test/tests/toplevel_paragraphs.gfm.html create mode 100644 src/main/resources/resources/vendors/marked-0.3.6/test/tests/toplevel_paragraphs.gfm.text create mode 100644 src/main/resources/resources/vendors/marked-0.3.6/test/tests/tricky_list.html create mode 100644 src/main/resources/resources/vendors/marked-0.3.6/test/tests/tricky_list.text create mode 100644 src/main/resources/resources/vendors/prism/prism.css create mode 100644 src/main/resources/resources/vendors/prism/prism.js create mode 100644 src/main/resources/resources/vendors/pygments/github.css create mode 100644 src/main/resources/resources/vendors/pygments/monokai.css create mode 100644 src/main/resources/resources/vendors/simditor-2.3.6/images/image.png create mode 100644 src/main/resources/resources/vendors/simditor-2.3.6/scripts/hotkeys.js create mode 100644 src/main/resources/resources/vendors/simditor-2.3.6/scripts/hotkeys.min.js create mode 100644 src/main/resources/resources/vendors/simditor-2.3.6/scripts/jquery.min.js create mode 100644 src/main/resources/resources/vendors/simditor-2.3.6/scripts/module.js create mode 100644 src/main/resources/resources/vendors/simditor-2.3.6/scripts/module.min.js create mode 100644 src/main/resources/resources/vendors/simditor-2.3.6/scripts/simditor.js create mode 100644 src/main/resources/resources/vendors/simditor-2.3.6/scripts/simditor.min.js create mode 100644 src/main/resources/resources/vendors/simditor-2.3.6/scripts/uploader.js create mode 100644 src/main/resources/resources/vendors/simditor-2.3.6/scripts/uploader.min.js create mode 100644 src/main/resources/resources/vendors/simditor-2.3.6/styles/editor.scss create mode 100644 src/main/resources/resources/vendors/simditor-2.3.6/styles/fonticon.scss create mode 100644 src/main/resources/resources/vendors/simditor-2.3.6/styles/simditor.css create mode 100644 src/main/resources/resources/vendors/simditor-2.3.6/styles/simditor.scss create mode 100644 src/main/resources/resources/vendors/simditor-markdown/lib/simditor-markdown.js create mode 100644 src/main/resources/resources/vendors/simditor-markdown/styles/simditor-markdown.css create mode 100644 src/main/resources/resources/vendors/to-markdown-3.1.0/.bowerrc create mode 100644 src/main/resources/resources/vendors/to-markdown-3.1.0/.editorconfig create mode 100644 src/main/resources/resources/vendors/to-markdown-3.1.0/.gitignore create mode 100644 src/main/resources/resources/vendors/to-markdown-3.1.0/.travis.yml create mode 100644 src/main/resources/resources/vendors/to-markdown-3.1.0/LICENSE create mode 100644 src/main/resources/resources/vendors/to-markdown-3.1.0/README.md create mode 100644 src/main/resources/resources/vendors/to-markdown-3.1.0/bower.json create mode 100644 src/main/resources/resources/vendors/to-markdown-3.1.0/index.js create mode 100644 src/main/resources/resources/vendors/to-markdown-3.1.0/lib/gfm-converters.js create mode 100644 src/main/resources/resources/vendors/to-markdown-3.1.0/lib/html-parser.js create mode 100644 src/main/resources/resources/vendors/to-markdown-3.1.0/lib/md-converters.js create mode 100644 src/main/resources/resources/vendors/to-markdown-3.1.0/package.json create mode 100644 src/main/resources/resources/vendors/to-markdown-3.1.0/test/gfm-test.js create mode 100644 src/main/resources/resources/vendors/to-markdown-3.1.0/test/index.html create mode 100644 src/main/resources/resources/vendors/to-markdown-3.1.0/test/to-markdown-test.js create mode 100644 src/main/resources/resources/vendors/to-markdown-3.1.0/testem.yml create mode 100644 src/main/resources/resources/vendors/typo.css-2.1.2/.gitignore create mode 100644 src/main/resources/resources/vendors/typo.css-2.1.2/README.md create mode 100644 src/main/resources/resources/vendors/typo.css-2.1.2/license.txt create mode 100644 src/main/resources/resources/vendors/typo.css-2.1.2/typo.css create mode 100644 src/main/resources/resources/vendors/typo.css-2.1.2/typo.html create mode 100644 src/main/resources/resources/vendors/typo.css-2.1.2/typo.min.css create mode 100644 src/main/resources/static/favicon-16x16.png create mode 100644 src/main/resources/static/favicon-32x32.png create mode 100644 src/main/resources/static/favicon.ico create mode 100644 src/main/resources/static/robots.txt create mode 100644 src/main/resources/templates/account/files/edit.jade create mode 100644 src/main/resources/templates/account/files/fragments/fileUploadForm.jade create mode 100644 src/main/resources/templates/account/files/fragments/list.jade create mode 100644 src/main/resources/templates/account/files/index.jade create mode 100644 src/main/resources/templates/account/files/status.jade create mode 100644 src/main/resources/templates/account/home/index.jade create mode 100644 src/main/resources/templates/account/layout/account.jade create mode 100644 src/main/resources/templates/account/layout/footer.jade create mode 100644 src/main/resources/templates/account/layout/head.jade create mode 100644 src/main/resources/templates/account/layout/message.jade create mode 100644 src/main/resources/templates/account/layout/navbar.jade create mode 100644 src/main/resources/templates/account/posts/edit.jade create mode 100644 src/main/resources/templates/account/posts/index.jade create mode 100644 src/main/resources/templates/account/posts/new.jade create mode 100644 src/main/resources/templates/account/users/profile.jade create mode 100644 src/main/resources/templates/admin/files/edit.jade create mode 100644 src/main/resources/templates/admin/files/fragments/fileUploadForm.jade create mode 100644 src/main/resources/templates/admin/files/fragments/list.jade create mode 100644 src/main/resources/templates/admin/files/index.jade create mode 100644 src/main/resources/templates/admin/files/status.jade create mode 100644 src/main/resources/templates/admin/home/index.jade create mode 100644 src/main/resources/templates/admin/home/settings.jade create mode 100644 src/main/resources/templates/admin/layout/admin.jade create mode 100644 src/main/resources/templates/admin/layout/footer.jade create mode 100644 src/main/resources/templates/admin/layout/head.jade create mode 100644 src/main/resources/templates/admin/layout/message.jade create mode 100644 src/main/resources/templates/admin/layout/navbar.jade create mode 100644 src/main/resources/templates/admin/posts/edit.jade create mode 100644 src/main/resources/templates/admin/posts/index.jade create mode 100644 src/main/resources/templates/admin/posts/new.jade create mode 100644 src/main/resources/templates/admin/robotsAgents/edit.jade create mode 100644 src/main/resources/templates/admin/robotsAgents/fragments/seoRobotAgentForm.jade create mode 100644 src/main/resources/templates/admin/robotsAgents/index.jade create mode 100644 src/main/resources/templates/admin/users/profile.jade create mode 100644 src/main/resources/templates/comments/deleted.jade create mode 100644 src/main/resources/templates/comments/fragments/commentCreationForm.jade create mode 100644 src/main/resources/templates/comments/list.jade create mode 100644 src/main/resources/templates/comments/one.jade create mode 100644 src/main/resources/templates/error.jade create mode 100644 src/main/resources/templates/error/general.jade create mode 100644 src/main/resources/templates/fragments/disqus.jade create mode 100644 src/main/resources/templates/fragments/ga.jade create mode 100644 src/main/resources/templates/fragments/ya-metrics.jade create mode 100644 src/main/resources/templates/home/about.jade create mode 100644 src/main/resources/templates/home/index.jade create mode 100644 src/main/resources/templates/layout/app.jade create mode 100644 src/main/resources/templates/layout/footer.jade create mode 100644 src/main/resources/templates/layout/head.jade create mode 100644 src/main/resources/templates/layout/navbar.jade create mode 100644 src/main/resources/templates/layout/top.jade create mode 100644 src/main/resources/templates/posts/archive.jade create mode 100644 src/main/resources/templates/posts/fragments/social.jade create mode 100644 src/main/resources/templates/posts/fragments/socialReadonly.jade create mode 100644 src/main/resources/templates/posts/list.jade create mode 100644 src/main/resources/templates/posts/projects.jade create mode 100644 src/main/resources/templates/posts/show.jade create mode 100644 src/main/resources/templates/tags/index.jade create mode 100644 src/main/resources/templates/tags/show.jade create mode 100644 src/main/resources/templates/tests/1.html create mode 100644 src/main/resources/templates/tests/2.jade create mode 100644 src/main/resources/templates/tests/3.html create mode 100644 src/main/resources/templates/users/register.jade create mode 100644 src/main/resources/templates/users/signin.jade create mode 100644 src/test/java/ru/bvn13/voidforum/VoidForumApplicationTests.java diff --git a/.gitignore b/.gitignore index 6143e53..c9f7010 100644 --- a/.gitignore +++ b/.gitignore @@ -1,22 +1,25 @@ -# Compiled class file -*.class +.gradle +/build/ +!gradle/wrapper/gradle-wrapper.jar -# Log file -*.log +### STS ### +.apt_generated +.classpath +.factorypath +.project +.settings +.springBeans -# BlueJ files -*.ctxt +### IntelliJ IDEA ### +.idea +*.iws +*.iml +*.ipr -# Mobile Tools for Java (J2ME) -.mtj.tmp/ - -# Package Files # -*.jar -*.war -*.ear -*.zip -*.tar.gz -*.rar - -# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml -hs_err_pid* +### NetBeans ### +nbproject/private/ +build/ +nbbuild/ +dist/ +nbdist/ +.nb-gradle/ \ No newline at end of file diff --git a/build.gradle b/build.gradle new file mode 100644 index 0000000..0124347 --- /dev/null +++ b/build.gradle @@ -0,0 +1,132 @@ +buildscript { + ext { + springBootVersion = '1.5.10.BUILD-SNAPSHOT' + redisEmbeddedVersion = "0.6" + } + repositories { + mavenCentral() + jcenter() + maven { url "https://repo.spring.io/snapshot" } + maven { url "https://repo.spring.io/milestone" } + } + dependencies { + classpath("org.springframework.boot:spring-boot-gradle-plugin:1.5.10.BUILD-SNAPSHOT") + } +} + +apply plugin: 'java' +apply plugin: 'idea' +apply plugin: 'org.springframework.boot' + +group = 'ru.bvn13' +version = '0.0.1-SNAPSHOT' + +sourceCompatibility = 1.8 +targetCompatibility = 1.8 + +repositories { + mavenCentral() + jcenter() + maven { url "https://repo.spring.io/snapshot" } + maven { url "https://repo.spring.io/milestone" } + + maven { url 'https://repo.spring.io/libs-release' } + maven { url "https://repo.springsource.org/repo" } +} + + +bootRun { + systemProperties = System.properties +} + +configurations { + compile.exclude module: "spring-boot-starter-tomcat" + all*.exclude module: 'spring-boot-starter-logging' +} + + +dependencies { + + // --- spring boot --- + //compile('org.springframework.boot:spring-boot-starter-cache') + compile('org.springframework.boot:spring-boot-starter-data-jpa:1.5.10.BUILD-SNAPSHOT') + compile('org.springframework.boot:spring-boot-starter-security:1.5.10.BUILD-SNAPSHOT') + compile('org.springframework.session:spring-session:1.3.1.RELEASE') + compile('org.springframework.boot:spring-boot-starter-validation:1.5.10.BUILD-SNAPSHOT') + compile('org.springframework.boot:spring-boot-starter-web:1.5.10.BUILD-SNAPSHOT') + compile('org.springframework.boot:spring-boot-starter-jetty:1.5.10.BUILD-SNAPSHOT') + compile('org.springframework.boot:spring-boot-starter-thymeleaf:1.5.10.BUILD-SNAPSHOT') + compile('com.domingosuarez.boot:spring-boot-starter-jade4j:0.3.2') + compile "org.springframework.boot:spring-boot-starter-data-redis:1.5.10.BUILD-SNAPSHOT", + "com.github.kstyrc:embedded-redis:$redisEmbeddedVersion" + compile(group: 'org.springframework.boot', name: 'spring-boot-starter') { + exclude(module: 'spring-boot-starter-logging') + } + compile('org.springframework.boot:spring-boot-starter-log4j:1.3.7.RELEASE') + + // --- spring --- + compile('org.springframework:spring-context:4.3.13.RELEASE') + compile('org.springframework:spring-webmvc:4.3.13.RELEASE') + compile('org.springframework.security:spring-security-config:4.2.3.RELEASE') + compile('org.springframework.security:spring-security-web:4.2.3.RELEASE') + + // --- spring data --- + compile('org.springframework.data:spring-data-jpa:1.11.9.RELEASE') + + // --- persistence --- + compile('com.zaxxer:HikariCP:2.5.1') + compile('org.springframework:spring-orm:4.3.13.RELEASE') + compile('org.hibernate:hibernate-entitymanager:5.0.12.Final') + compile('javax.el:javax.el-api:+') + compile('org.hsqldb:hsqldb:2.3.5') + + // --- view --- + compile('de.neuland-bfi:spring-jade4j:1.2.7') + + //markdown processor + compile 'com.vladsch.flexmark:flexmark-all:0.28.8' + + // --- cache --- + compile('org.springframework.data:spring-data-redis:1.8.9.RELEASE') + compile('redis.clients:jedis:2.9.0') + + // --- PostgreSQL --- + runtime('org.postgresql:postgresql') + + // --- Validation --- + compile 'org.hibernate:hibernate-validator:6.0.5.Final' + //compile 'org.hibernate.validator:hibernate-validator:6.0.5.Final' + //compile 'org.hibernate.validator:hibernate-validator-annotation-processor:6.0.5.Final' + compile 'javax.validation:validation-api:2.0.0.Final' + + // Logging + compile('ch.qos.logback:logback-classic') + compile('org.slf4j:slf4j-api') + compile('org.apache.commons:commons-lang3') + + // @Inject + compile('javax.inject:javax.inject:+') + + // JSON + compile('com.fasterxml.jackson.core:jackson-databind') + compile('com.fasterxml.jackson.core:jackson-annotations') + + // Utilities + compile('com.google.guava:guava:23.0') + compile('org.modelmapper:modelmapper:1.1.1') + compile('org.projectlombok:lombok:1.16.18') + + + // static resources, ref. http://www.webjars.org/ + compile('org.webjars:jquery:3.2.1') + compile('org.webjars:bootstrap:3.3.7-1') + compile('org.webjars:font-awesome:4.7.0') + compile('org.webjars:ace:1.2.8') + + + // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + + testCompile('org.springframework.boot:spring-boot-starter-test') + testCompile('org.springframework.security:spring-security-test') +} + diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000000000000000000000000000000000000..1a958be6420a4dd04b588fe4b31eb5d7ff8748c2 GIT binary patch literal 54711 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 \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG=`dirname "$PRG"`"/$link" + fi +done +SAVED="`pwd`" +cd "`dirname \"$PRG\"`/" >/dev/null +APP_HOME="`pwd -P`" +cd "$SAVED" >/dev/null + +APP_NAME="Gradle" +APP_BASE_NAME=`basename "$0"` + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS="" + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD="maximum" + +warn ( ) { + echo "$*" +} + +die ( ) { + echo + echo "$*" + echo + exit 1 +} + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "`uname`" in + CYGWIN* ) + cygwin=true + ;; + Darwin* ) + darwin=true + ;; + MINGW* ) + msys=true + ;; + NONSTOP* ) + nonstop=true + ;; +esac + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD="java" + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +fi + +# Increase the maximum file descriptors if we can. +if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then + MAX_FD_LIMIT=`ulimit -H -n` + if [ $? -eq 0 ] ; then + if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then + MAX_FD="$MAX_FD_LIMIT" + fi + ulimit -n $MAX_FD + if [ $? -ne 0 ] ; then + warn "Could not set maximum file descriptor limit: $MAX_FD" + fi + else + warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" + fi +fi + +# For Darwin, add options to specify how the application appears in the dock +if $darwin; then + GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" +fi + +# For Cygwin, switch paths to Windows format before running java +if $cygwin ; then + APP_HOME=`cygpath --path --mixed "$APP_HOME"` + CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` + JAVACMD=`cygpath --unix "$JAVACMD"` + + # We build the pattern for arguments to be converted via cygpath + ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` + SEP="" + for dir in $ROOTDIRSRAW ; do + ROOTDIRS="$ROOTDIRS$SEP$dir" + SEP="|" + done + OURCYGPATTERN="(^($ROOTDIRS))" + # Add a user-defined pattern to the cygpath arguments + if [ "$GRADLE_CYGPATTERN" != "" ] ; then + OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" + fi + # Now convert the arguments - kludge to limit ourselves to /bin/sh + i=0 + for arg in "$@" ; do + CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` + CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option + + if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition + eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` + else + eval `echo args$i`="\"$arg\"" + fi + i=$((i+1)) + done + case $i in + (0) set -- ;; + (1) set -- "$args0" ;; + (2) set -- "$args0" "$args1" ;; + (3) set -- "$args0" "$args1" "$args2" ;; + (4) set -- "$args0" "$args1" "$args2" "$args3" ;; + (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; + (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; + (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; + (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; + (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; + esac +fi + +# Escape application args +save ( ) { + for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done + echo " " +} +APP_ARGS=$(save "$@") + +# Collect all arguments for the java command, following the shell quoting and substitution rules +eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" + +# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong +if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then + cd "$(dirname "$0")" +fi + +exec "$JAVACMD" "$@" diff --git a/gradlew.bat b/gradlew.bat new file mode 100644 index 0000000..f955316 --- /dev/null +++ b/gradlew.bat @@ -0,0 +1,84 @@ +@if "%DEBUG%" == "" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS= + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if "%ERRORLEVEL%" == "0" goto init + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto init + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:init +@rem Get command-line arguments, handling Windows variants + +if not "%OS%" == "Windows_NT" goto win9xME_args + +:win9xME_args +@rem Slurp the command line arguments. +set CMD_LINE_ARGS= +set _SKIP=2 + +:win9xME_args_slurp +if "x%~1" == "x" goto execute + +set CMD_LINE_ARGS=%* + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% + +:end +@rem End local scope for the variables with windows NT shell +if "%ERRORLEVEL%"=="0" goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 +exit /b 1 + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/src/main/java/ru/bvn13/voidforum/Application.java b/src/main/java/ru/bvn13/voidforum/Application.java new file mode 100644 index 0000000..51a6446 --- /dev/null +++ b/src/main/java/ru/bvn13/voidforum/Application.java @@ -0,0 +1,54 @@ +package ru.bvn13.voidforum; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import redis.embedded.Redis; +import redis.embedded.RedisServer; + +import javax.annotation.PostConstruct; +import javax.annotation.PreDestroy; + +import static java.util.stream.Collectors.joining; + +/** + * @author bvn13 + */ + +@SpringBootApplication +public class Application { + + private static final Logger logger = LoggerFactory.getLogger(Application.class); + + @Autowired + @Qualifier("RedisServer") + private Redis redisServer; + + + @PostConstruct + public void start() { + logger.info("starting redis..."); + if (!redisServer.isActive()) { + redisServer.start(); + } + if (redisServer.isActive()) { + logger.info("redis listen ports: {}", redisServer.ports().stream().map(Object::toString).collect(joining(","))); + } + } + + @PreDestroy + public void stop() { + + logger.info("shutting down redis..."); + redisServer.stop(); + logger.info("bye!"); + } + + + public static void main(String[] args) { + SpringApplication.run(Application.class, args); + } +} diff --git a/src/main/java/ru/bvn13/voidforum/Constants.java b/src/main/java/ru/bvn13/voidforum/Constants.java new file mode 100644 index 0000000..b39b9d0 --- /dev/null +++ b/src/main/java/ru/bvn13/voidforum/Constants.java @@ -0,0 +1,21 @@ +package ru.bvn13.voidforum; + +/** + * @author: bvn13 + */ +public final class Constants { + + public static final String ENV_PRODUCTION = "production"; + + public static final String ENV_DEVELOPMENT = "development"; + + public static final String DEFAULT_ADMIN_NICKNAME = "admin"; + + public static final String DEFAULT_ADMIN_EMAIL = "admin@admin.com"; + + public static final String DEFAULT_ADMIN_PASSWORD = "admin"; + + public static final String ABOUT_PAGE_PERMALINK = "about"; + + +} diff --git a/src/main/java/ru/bvn13/voidforum/JpaConfig.java b/src/main/java/ru/bvn13/voidforum/JpaConfig.java new file mode 100644 index 0000000..701a5ee --- /dev/null +++ b/src/main/java/ru/bvn13/voidforum/JpaConfig.java @@ -0,0 +1,104 @@ +package ru.bvn13.voidforum; + +import com.zaxxer.hikari.HikariConfig; +import com.zaxxer.hikari.HikariDataSource; +import org.hibernate.SessionFactory; +import org.hibernate.jpa.HibernateEntityManagerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.autoconfigure.domain.EntityScan; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.jpa.repository.config.EnableJpaRepositories; +import org.springframework.orm.jpa.JpaTransactionManager; +import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean; +import org.springframework.orm.jpa.vendor.HibernateJpaSessionFactoryBean; +import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter; +import org.springframework.transaction.PlatformTransactionManager; +import org.springframework.transaction.annotation.EnableTransactionManagement; +import org.springframework.transaction.annotation.TransactionManagementConfigurer; + +import javax.persistence.EntityManager; +import javax.persistence.EntityManagerFactory; +import javax.sql.DataSource; +import java.util.Properties; + +/** + * @author bvn13 + */ + +@Configuration +@EnableTransactionManagement +@EnableJpaRepositories(basePackageClasses = Application.class) +class JpaConfig implements TransactionManagementConfigurer { + + @Value("${spring.dataSource.driverClassName}") + private String driver; + @Value("${spring.dataSource.url}") + private String url; + @Value("${spring.dataSource.username}") + private String username; + @Value("${spring.dataSource.password}") + private String password; + @Value("${spring.hibernate.dialect}") + private String dialect; + @Value("${spring.hibernate.hbm2ddl.auto}") + private String hbm2ddlAuto; + @Value("${spring.hibernate.show_sql}") + private Boolean showSql; + + @Bean + public DataSource configureDataSource() { + HikariConfig config = new HikariConfig(); + config.setDriverClassName(driver); + config.setJdbcUrl(url); + config.setUsername(username); + config.setPassword(password); + + config.addDataSourceProperty("useUnicode", "true"); + config.addDataSourceProperty("characterEncoding", "utf8"); + config.addDataSourceProperty("cachePrepStmts", "true"); + config.addDataSourceProperty("prepStmtCacheSize", "250"); + config.addDataSourceProperty("prepStmtCacheSqlLimit", "2048"); + config.addDataSourceProperty("useServerPrepStmts", "true"); + + return new HikariDataSource(config); + } + + @Bean + public LocalContainerEntityManagerFactoryBean entityManagerFactory() { + LocalContainerEntityManagerFactoryBean entityManagerFactoryBean = new LocalContainerEntityManagerFactoryBean(); + entityManagerFactoryBean.setDataSource(configureDataSource()); + entityManagerFactoryBean.setPackagesToScan("ru.bvn13.voidforum"); + entityManagerFactoryBean.setJpaVendorAdapter(new HibernateJpaVendorAdapter()); + + Properties jpaProperties = new Properties(); + jpaProperties.put(org.hibernate.cfg.Environment.DIALECT, dialect); + jpaProperties.put(org.hibernate.cfg.Environment.HBM2DDL_AUTO, hbm2ddlAuto); + jpaProperties.put(org.hibernate.cfg.Environment.SHOW_SQL, showSql); + entityManagerFactoryBean.setJpaProperties(jpaProperties); + + return entityManagerFactoryBean; + } + + @Bean(name = "transactionManager") + public PlatformTransactionManager annotationDrivenTransactionManager() { + return new JpaTransactionManager(); + } + + /* + + @Autowired + private EntityManagerFactory entityManagerFactory; + + @Bean + public SessionFactory getSessionFactory() { + if (entityManagerFactory.unwrap(SessionFactory.class) == null) { + throw new NullPointerException("factory is not a hibernate factory"); + } + return entityManagerFactory.unwrap(SessionFactory.class); + }*/ + + +} diff --git a/src/main/java/ru/bvn13/voidforum/RedisConfig.java b/src/main/java/ru/bvn13/voidforum/RedisConfig.java new file mode 100644 index 0000000..0637acc --- /dev/null +++ b/src/main/java/ru/bvn13/voidforum/RedisConfig.java @@ -0,0 +1,59 @@ +package ru.bvn13.voidforum; + +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import redis.embedded.Redis; +import redis.embedded.RedisServer; +import redis.embedded.exceptions.EmbeddedRedisException; + +import java.util.List; + +@Configuration +public class RedisConfig { + + public static class RedisDummy implements Redis { + + @Override + public boolean isActive() { + return false; + } + + @Override + public void start() throws EmbeddedRedisException { + + } + + @Override + public void stop() throws EmbeddedRedisException { + + } + + @Override + public List ports() { + return null; + } + } + + @Value("${spring.redis.port}") + private int port; + + @Value("${spring.redis.embedded}") + private Boolean useEmbeddedRedis; + + + + + @Bean(name = "RedisServer") + public Redis redisServer() { + if (!this.useEmbeddedRedis) { + return new RedisDummy(); + } + RedisServer.builder().reset(); + + return RedisServer.builder() + .port(this.port) + .build(); + } + +} diff --git a/src/main/java/ru/bvn13/voidforum/SecurityConfig.java b/src/main/java/ru/bvn13/voidforum/SecurityConfig.java new file mode 100644 index 0000000..e3d3fb1 --- /dev/null +++ b/src/main/java/ru/bvn13/voidforum/SecurityConfig.java @@ -0,0 +1,67 @@ +package ru.bvn13.voidforum; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; +import org.springframework.security.crypto.password.PasswordEncoder; +import org.springframework.security.crypto.password.StandardPasswordEncoder; +import org.springframework.security.web.authentication.rememberme.TokenBasedRememberMeServices; +import ru.bvn13.voidforum.services.PrivilegeService; +import ru.bvn13.voidforum.services.UserService; + +/** + * @author bvn13 + */ + +@Configuration +public class SecurityConfig extends WebSecurityConfigurerAdapter { + + @Bean + public UserService userService() { + return new UserService(); + } + + @Bean + public TokenBasedRememberMeServices rememberMeServices() { + return new TokenBasedRememberMeServices("remember-me-key", userService()); + } + + @Bean + public PasswordEncoder passwordEncoder() { + return new StandardPasswordEncoder(); + } + + @Override + protected void configure(AuthenticationManagerBuilder auth) throws Exception { + auth + .eraseCredentials(true) + .userDetailsService(userService()) + .passwordEncoder(passwordEncoder()); + } + + @Override + protected void configure(HttpSecurity http) throws Exception { + http + .authorizeRequests() + .antMatchers("/admin/**").hasAnyAuthority(PrivilegeService.PRIVILEGE_ADMIN, PrivilegeService.PRIVILEGE_OWNER) + .antMatchers("/account/**").hasAnyAuthority(PrivilegeService.PRIVILEGE_WRITE, PrivilegeService.PRIVILEGE_ADMIN, PrivilegeService.PRIVILEGE_OWNER) + .anyRequest().permitAll() + .and() + .formLogin() + .loginPage("/signin") + .permitAll() + .failureUrl("/signin?error=1") + .loginProcessingUrl("/authenticate") + .and() + .logout() + .logoutUrl("/logout") + .permitAll() + .logoutSuccessUrl("/signin?logout") + .and() + .rememberMe() + .rememberMeServices(rememberMeServices()) + .key("remember-me-key"); + } +} diff --git a/src/main/java/ru/bvn13/voidforum/WebConfig.java b/src/main/java/ru/bvn13/voidforum/WebConfig.java new file mode 100644 index 0000000..be4df18 --- /dev/null +++ b/src/main/java/ru/bvn13/voidforum/WebConfig.java @@ -0,0 +1,66 @@ +package ru.bvn13.voidforum; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.core.env.Environment; +import org.springframework.security.web.csrf.CsrfToken; +import org.springframework.web.servlet.HandlerInterceptor; +import org.springframework.web.servlet.ModelAndView; +import org.springframework.web.servlet.config.annotation.InterceptorRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; +import org.springframework.web.servlet.handler.HandlerInterceptorAdapter; +import ru.bvn13.voidforum.support.web.ViewHelperVF; + +import javax.annotation.PostConstruct; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import static ru.bvn13.voidforum.Constants.*; + +/** + * @author bvn13 . + */ +@Configuration +public class WebConfig extends WebMvcConfigurerAdapter { + @Autowired + private ViewHelperVF viewHelper; + + @Autowired + private Environment env; + + @Override + public void addInterceptors(InterceptorRegistry registry) { + registry.addInterceptor(viewObjectAddingInterceptor()); + super.addInterceptors(registry); + } + + @PostConstruct + public void registerJadeViewHelpers(){ + viewHelper.setApplicationEnv(this.getApplicationEnv()); + } + + @Bean + public HandlerInterceptor viewObjectAddingInterceptor() { + return new HandlerInterceptorAdapter() { + @Override + public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { + viewHelper.setStartTime(System.currentTimeMillis()); + + return true; + } + + @Override + public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView view) { + CsrfToken token = (CsrfToken) request.getAttribute(CsrfToken.class.getName()); + if (token != null) { + view.addObject(token.getParameterName(), token); + } + } + }; + } + + public String getApplicationEnv(){ + return this.env.acceptsProfiles(ENV_PRODUCTION) ? ENV_PRODUCTION : ENV_DEVELOPMENT; + } +} diff --git a/src/main/java/ru/bvn13/voidforum/controllers/HomeController.java b/src/main/java/ru/bvn13/voidforum/controllers/HomeController.java new file mode 100644 index 0000000..3521677 --- /dev/null +++ b/src/main/java/ru/bvn13/voidforum/controllers/HomeController.java @@ -0,0 +1,87 @@ +package ru.bvn13.voidforum.controllers; + +import ru.bvn13.voidforum.Constants; +import ru.bvn13.voidforum.error.NotFoundException; +import ru.bvn13.voidforum.models.Post; +import ru.bvn13.voidforum.services.AppSetting; +import ru.bvn13.voidforum.services.PostService; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.domain.Page; +import org.springframework.stereotype.Controller; +import org.springframework.ui.Model; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import ru.bvn13.voidforum.services.PrivilegeService; +import ru.bvn13.voidforum.services.UserService; + +import javax.servlet.http.HttpServletRequest; + +import static org.springframework.web.bind.annotation.RequestMethod.GET; + +@Controller +public class HomeController { + + private static final Logger logger = LoggerFactory.getLogger(HomeController.class); + + @Autowired + private PostService postService; + + @Autowired + private UserService userService; + + @Autowired + private AppSetting appSetting; + + @RequestMapping(value = "", method = GET) + public String index(@RequestParam(defaultValue = "1") int page, Model model, HttpServletRequest request) { + //request.isUserInRole("READ_PRIVILEGE"); + page = page < 1 ? 0 : page - 1; + Page posts = null; + if (userService.currentUserHasPrivilege(PrivilegeService.PRIVILEGE_WRITE)) { + if (userService.currentUserHasPrivilege(PrivilegeService.PRIVILEGE_ADMIN)) { + posts = postService.getAllPublishedPostsByPage(page, appSetting.getPageSize()); + } else { + posts = postService.getAllPublishedNotDeletedPostsByPage(page, appSetting.getPageSize()); + } + } else { + posts = postService.getAllPublishedNotCensoredNotDeletedPostsByPage(page, appSetting.getPageSize()); + } + + model.addAttribute("totalPages", posts.getTotalPages()); + model.addAttribute("posts", posts); + model.addAttribute("page", page + 1); + + return "home/index"; + } + + @RequestMapping(value = "about", method = GET) + public String about(Model model) { + + /*Post post = null; + try { + post = postService.getPublishedPostByPermalink(Constants.ABOUT_PAGE_PERMALINK); + } catch (NotFoundException nfe) { + logger.debug("Get post with permalink " + Constants.ABOUT_PAGE_PERMALINK); + post = postService.createAboutPage(); + } + + if (post == null) { + throw new NotFoundException("Post with permalink " + Constants.ABOUT_PAGE_PERMALINK + " is not found"); + } + */ + + Post post = null; + try { + post = postService.getPublishedPostByPermalink(Constants.ABOUT_PAGE_PERMALINK); + } catch (NotFoundException nfe) { + logger.debug("Get post with permalink " + Constants.ABOUT_PAGE_PERMALINK); + throw new NotFoundException("Post with permalink " + Constants.ABOUT_PAGE_PERMALINK + " is not found"); + } + + model.addAttribute("about", post); + return "home/about"; + } + +} diff --git a/src/main/java/ru/bvn13/voidforum/controllers/PostController.java b/src/main/java/ru/bvn13/voidforum/controllers/PostController.java new file mode 100644 index 0000000..fa67bb9 --- /dev/null +++ b/src/main/java/ru/bvn13/voidforum/controllers/PostController.java @@ -0,0 +1,84 @@ +package ru.bvn13.voidforum.controllers; + +import ru.bvn13.voidforum.forms.CommentForm; +import ru.bvn13.voidforum.models.Post; +import ru.bvn13.voidforum.models.SeoPostData; +import ru.bvn13.voidforum.services.*; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Controller; +import org.springframework.ui.Model; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestMapping; + +import javax.servlet.http.HttpServletRequest; + +import static org.springframework.web.bind.annotation.RequestMethod.*; + + +/** + * bvn13 + */ +@Controller +@RequestMapping("posts") +public class PostController { + + Logger logger = LoggerFactory.getLogger(PostController.class); + + @Autowired + private PostService postService; + + @Autowired + private VisitService visitService; + + @Autowired + private LikeService likeService; + + @Autowired + private CommentService commentService; + + @Autowired + private RequestProcessorService requestProcessorService; + + + @RequestMapping(value = "archive", method = GET) + public String archive(Model model){ + model.addAttribute("posts", postService.getArchivePosts()); + + return "posts/archive"; + } + + @RequestMapping(value = "{permalink}", method = GET) + public String show(@PathVariable String permalink, Model model, HttpServletRequest request){ + Post post = this.postService.findPostByPermalink(permalink); + + logger.debug(String.format("ACCESS %s from IP: %s", permalink, this.requestProcessorService.getRealIp(request))); + + this.visitService.saveVisit(post, this.requestProcessorService.getRealIp(request), this.requestProcessorService.getUserAgent(request)); + post.setVisitsCount(this.visitService.getUniqueVisitsCount(post)); + post.setSympathyCount(this.likeService.getTotalLikesByPost(post)); + + SeoPostData seoData = null; + if (post.getSeoData() == null) { + seoData = new SeoPostData(); + seoData.setPost(post); + } else { + seoData = post.getSeoData(); + } + + model.addAttribute("post", post); + model.addAttribute("tags", this.postService.getPostTags(post)); + model.addAttribute("seoKeywords", this.postService.getSeoKeywordsAsString(post)); + model.addAttribute("seoDescription", post.getSeoDescription()); + model.addAttribute("seoData", seoData); + + model.addAttribute("comments", commentService.getCommentsForPost(post)); + model.addAttribute("commentForm", new CommentForm()); + model.addAttribute("commentFormats", commentService.getAvailableCommentFormats()); + + return "posts/show"; + } + + +} diff --git a/src/main/java/ru/bvn13/voidforum/controllers/StoredFileController.java b/src/main/java/ru/bvn13/voidforum/controllers/StoredFileController.java new file mode 100644 index 0000000..565fe9c --- /dev/null +++ b/src/main/java/ru/bvn13/voidforum/controllers/StoredFileController.java @@ -0,0 +1,61 @@ +package ru.bvn13.voidforum.controllers; + +import ru.bvn13.voidforum.models.StoredFile; +import ru.bvn13.voidforum.services.FileStorageService; +import ru.bvn13.voidforum.services.UserService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpEntity; +import org.springframework.http.HttpHeaders; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.*; + +import javax.servlet.http.HttpServletResponse; +import java.io.FileNotFoundException; +import java.io.IOException; + +import static org.springframework.http.MediaType.APPLICATION_OCTET_STREAM; +import static org.springframework.util.MimeTypeUtils.APPLICATION_OCTET_STREAM_VALUE; + + +@Controller +@RequestMapping("/files") +public class StoredFileController { + + @Autowired + private UserService userService; + + @Autowired + private FileStorageService storageService; + + @GetMapping(value = "/{fileName:.+}", produces = APPLICATION_OCTET_STREAM_VALUE) + @ExceptionHandler(value = FileNotFoundException.class) + public @ResponseBody + HttpEntity getFileById(@PathVariable String fileName, final HttpServletResponse response) throws IOException { + + StoredFile file = this.storageService.getFileByName(fileName); + if (file == null) { + response.sendError(404, String.format("File %s not found", fileName)); + return null; + } + byte[] content; + try { + content = this.storageService.getFileContent(file.getPath()); + } catch (IOException e) { + e.printStackTrace(); + if (this.userService.isCurrentUserAdmin()) { + response.sendError(404, String.format("File %s (%s) not found", file.getName(), file.getPath())); + } else { + response.sendError(404, String.format("File %s not found", file.getName())); + } + return null; + } + + HttpHeaders header = new HttpHeaders(); + header.setContentType(APPLICATION_OCTET_STREAM); + header.set("Content-Disposition", "inline; filename=" + file.getName()); + header.setContentLength(file.getSize()); + + return new HttpEntity(content, header); + } + +} diff --git a/src/main/java/ru/bvn13/voidforum/controllers/SympathyController.java b/src/main/java/ru/bvn13/voidforum/controllers/SympathyController.java new file mode 100644 index 0000000..55f7bd0 --- /dev/null +++ b/src/main/java/ru/bvn13/voidforum/controllers/SympathyController.java @@ -0,0 +1,69 @@ +package ru.bvn13.voidforum.controllers; + +import ru.bvn13.voidforum.forms.LikeForm; +import ru.bvn13.voidforum.models.Post; +import ru.bvn13.voidforum.services.*; +import ru.bvn13.voidforum.support.web.ViewHelperVF; +import lombok.Data; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.ResponseBody; + +import javax.servlet.http.HttpServletRequest; +import javax.validation.constraints.NotNull; + +@Controller +@RequestMapping(value = "/sympathy") +public class SympathyController { + + @Autowired + private AppSetting appSetting; + + @Autowired + private PostService postService; + + @Autowired + private LikeService likeService; + + @Autowired + private UserService userService; + + @Autowired + private RequestProcessorService requestProcessorService; + + + @Data + public static class SympathyRequestData { + @NotNull + private String postId; + } + + + @PostMapping(value = "/like") + public @ResponseBody + LikeForm likeIt(@RequestBody SympathyRequestData data, HttpServletRequest request) { + Post post = this.postService.findPostByPermalink(data.getPostId()); + this.likeService.likePost(post, this.requestProcessorService.getRealIp(request)); + ViewHelperVF viewHelper = new ViewHelperVF(this.appSetting); + LikeForm result = new LikeForm(); + result.setSympathy(viewHelper.formatNumberByThousands(this.likeService.getTotalLikesByPost(post))); + return result; + } + + @PostMapping(value = "/dislike") + public @ResponseBody + LikeForm dislikeIt(@RequestBody SympathyRequestData data, HttpServletRequest request) { + Post post = this.postService.findPostByPermalink(data.getPostId()); + this.likeService.dislikePost(post, this.requestProcessorService.getRealIp(request)); + ViewHelperVF viewHelper = new ViewHelperVF(this.appSetting); + LikeForm result = new LikeForm(); + result.setSympathy(viewHelper.formatNumberByThousands(this.likeService.getTotalLikesByPost(post))); + return result; + } + + + +} diff --git a/src/main/java/ru/bvn13/voidforum/controllers/TagController.java b/src/main/java/ru/bvn13/voidforum/controllers/TagController.java new file mode 100644 index 0000000..d338480 --- /dev/null +++ b/src/main/java/ru/bvn13/voidforum/controllers/TagController.java @@ -0,0 +1,58 @@ +package ru.bvn13.voidforum.controllers; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.domain.Page; +import org.springframework.stereotype.Controller; +import org.springframework.ui.Model; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import ru.bvn13.voidforum.error.NotFoundException; +import ru.bvn13.voidforum.models.Post; +import ru.bvn13.voidforum.models.Tag; +import ru.bvn13.voidforum.services.AppSetting; +import ru.bvn13.voidforum.services.PostService; +import ru.bvn13.voidforum.services.TagService; + +import static org.springframework.web.bind.annotation.RequestMethod.GET; + +/** + * bvn13 . + */ +@Controller +@RequestMapping("tags") +public class TagController { + @Autowired + private TagService tagService; + + @Autowired + private PostService postService; + + @Autowired + private AppSetting appSetting; + + @RequestMapping(value = "", method = GET) + public String index(Model model){ + model.addAttribute("tags", postService.countPostsByTags()); + return "tags/index"; + } + + @RequestMapping(value = "{tagName}", method = GET) + public String showTag(@PathVariable String tagName, @RequestParam(defaultValue = "1") int page, Model model) { + Tag tag = tagService.getTag(tagName); + + if (tag == null) { + throw new NotFoundException("Tag " + tagName + " is not found."); + } + + page = page < 1 ? 0 : page - 1; + Page posts = postService.findPostsByTag(tagName, page, appSetting.getPageSize()); + + model.addAttribute("tag", tag); + model.addAttribute("posts", posts); + model.addAttribute("page", page + 1); + model.addAttribute("totalPages", posts.getTotalPages()); + + return "tags/show"; + } +} diff --git a/src/main/java/ru/bvn13/voidforum/controllers/TestController.java b/src/main/java/ru/bvn13/voidforum/controllers/TestController.java new file mode 100644 index 0000000..4748ce7 --- /dev/null +++ b/src/main/java/ru/bvn13/voidforum/controllers/TestController.java @@ -0,0 +1,22 @@ +package ru.bvn13.voidforum.controllers; + +import org.springframework.stereotype.Controller; +import org.springframework.ui.Model; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; + +/** + * Created by bvn13 on 09.12.2017. + */ +@Controller +@RequestMapping("tests") +public class TestController { + + @GetMapping(value = "/1") + public String test1(Model model) { + + + return "tests/1"; + } + +} diff --git a/src/main/java/ru/bvn13/voidforum/controllers/UserController.java b/src/main/java/ru/bvn13/voidforum/controllers/UserController.java new file mode 100644 index 0000000..58f00de --- /dev/null +++ b/src/main/java/ru/bvn13/voidforum/controllers/UserController.java @@ -0,0 +1,90 @@ +package ru.bvn13.voidforum.controllers; + +import lombok.Getter; +import lombok.Setter; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.http.MediaType; +import org.springframework.security.authentication.AuthenticationManager; +import org.springframework.security.authentication.BadCredentialsException; +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.stereotype.Controller; +import org.springframework.ui.Model; +import org.springframework.validation.Errors; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.servlet.mvc.support.RedirectAttributes; +import ru.bvn13.voidforum.error.EmailExistsException; +import ru.bvn13.voidforum.error.NicknameExistsException; +import ru.bvn13.voidforum.forms.RegistrationForm; +import ru.bvn13.voidforum.models.User; +import ru.bvn13.voidforum.services.UserService; +import ru.bvn13.voidforum.utils.DTOUtil; + +import javax.servlet.http.HttpServletRequest; +import javax.validation.Valid; +import java.security.Principal; + +/** + * bvn13 + */ +@Controller(value = "/") +public class UserController { + + @Autowired + private UserService userService; + + + @RequestMapping(value = "signin", method = RequestMethod.GET) + public String signin(Principal principal, RedirectAttributes ra) { + return principal == null ? "users/signin" : "redirect:/"; + } + + + @GetMapping(value = "register") + public String registrationForm(Model model) { + model.addAttribute("form", new RegistrationForm()); + return "users/register"; + } + + + @PostMapping(value = "register") + public String register(@Valid RegistrationForm registrationForm, Errors errors, Model model, RedirectAttributes ra) { + if (!registrationForm.getPassword().equals(registrationForm.getPasswordCheck())) { + ra.addFlashAttribute("error", "Verify your password!"); + return "redirect:/register"; + } + + if (registrationForm.getUsername().isEmpty() + || registrationForm.getNickname().isEmpty() + || registrationForm.getPassword().isEmpty() + || registrationForm.getPasswordCheck().isEmpty()) { + ra.addFlashAttribute("error", "Not all necessary fields are specified"); + return "redirect:/register"; + } + + User user = new User(); + user.setEmail(registrationForm.getUsername()); + user.setNickname(registrationForm.getNickname()); + user.setPassword(registrationForm.getPassword()); + //DTOUtil.mapTo(registrationForm, user); + + try { + userService.registerNewUserAccount(user); + } catch (EmailExistsException e) { + e.printStackTrace(); + ra.addFlashAttribute("error", "There is an account with specified email and nickname"); + return "redirect:/register"; + } catch (NicknameExistsException e) { + e.printStackTrace(); + ra.addFlashAttribute("error", "There is an account with specified email and nickname"); + return "redirect:/register"; + } + + return "redirect:/signin"; + } +} \ No newline at end of file diff --git a/src/main/java/ru/bvn13/voidforum/controllers/account/AccountController.java b/src/main/java/ru/bvn13/voidforum/controllers/account/AccountController.java new file mode 100644 index 0000000..61a113d --- /dev/null +++ b/src/main/java/ru/bvn13/voidforum/controllers/account/AccountController.java @@ -0,0 +1,23 @@ +package ru.bvn13.voidforum.controllers.account; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Controller; +import org.springframework.ui.Model; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; + +/** + * Created by bvn13 on 08.12.2017. + */ +@Controller +@RequestMapping(value = "/account") +public class AccountController { + + @GetMapping(value = "") + public String getAccountIndex(Model model) { + + return "account/home/index"; + + } + +} diff --git a/src/main/java/ru/bvn13/voidforum/controllers/account/CommentController.java b/src/main/java/ru/bvn13/voidforum/controllers/account/CommentController.java new file mode 100644 index 0000000..bd16665 --- /dev/null +++ b/src/main/java/ru/bvn13/voidforum/controllers/account/CommentController.java @@ -0,0 +1,23 @@ +package ru.bvn13.voidforum.controllers.account; + +import org.springframework.stereotype.Controller; +import org.springframework.ui.Model; +import org.springframework.web.bind.annotation.RequestMapping; + +import static org.springframework.web.bind.annotation.RequestMethod.POST; + +/** + * Created by bvn13 on 08.12.2017. + */ +@Controller("accountCommentController") +@RequestMapping("/account/comments") +public class CommentController { + + + @RequestMapping(value = "", method = POST) + public String addComment(Model model) { + + return ""; + } + +} diff --git a/src/main/java/ru/bvn13/voidforum/controllers/account/PostController.java b/src/main/java/ru/bvn13/voidforum/controllers/account/PostController.java new file mode 100644 index 0000000..be6873d --- /dev/null +++ b/src/main/java/ru/bvn13/voidforum/controllers/account/PostController.java @@ -0,0 +1,193 @@ +package ru.bvn13.voidforum.controllers.account; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Sort; +import org.springframework.security.access.AccessDeniedException; +import org.springframework.stereotype.Controller; +import org.springframework.ui.Model; +import org.springframework.util.Assert; +import org.springframework.validation.Errors; +import org.springframework.validation.FieldError; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import ru.bvn13.voidforum.forms.PostForm; +import ru.bvn13.voidforum.models.Post; +import ru.bvn13.voidforum.models.User; +import ru.bvn13.voidforum.models.support.*; +import ru.bvn13.voidforum.repositories.PostRepository; +import ru.bvn13.voidforum.repositories.UserRepository; +import ru.bvn13.voidforum.services.PostService; +import ru.bvn13.voidforum.services.PrivilegeService; +import ru.bvn13.voidforum.services.UserService; +import ru.bvn13.voidforum.utils.DTOUtil; + +import javax.validation.Valid; +import java.security.Principal; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import static org.springframework.web.bind.annotation.RequestMethod.DELETE; +import static org.springframework.web.bind.annotation.RequestMethod.POST; +import static org.springframework.web.bind.annotation.RequestMethod.PUT; + +/** + * Created by bvn13 on 07.12.2017. + */ +@Controller("accountPostController") +@RequestMapping(value = "/account/posts") +public class PostController { + + @Autowired + private PostRepository postRepository; + + @Autowired + private PostService postService; + + @Autowired + private UserRepository userRepository; + + @Autowired + private UserService userService; + + private static final int PAGE_SIZE = 20; + + @GetMapping(name = "") + public String getOwnedPosts(@RequestParam(defaultValue = "0") int page, Model model) { + + Assert.notNull(userService.currentUser(), ""); + + Page posts = postRepository.findAllByUser(userService.currentUser(), new PageRequest(page, PAGE_SIZE, Sort.Direction.DESC, "id")); + + model.addAttribute("totalPages", posts.getTotalPages()); + model.addAttribute("page", page); + model.addAttribute("posts", posts); + + return "account/posts/index"; + } + + private String makeFormPostCreation(Model model) { + PostForm postForm = DTOUtil.map(new Post(), PostForm.class); + postForm.init(); + return this.makeFormPostCreation(model, postForm); + } + + private String makeFormPostCreation(Model model, PostForm postForm) { + + User user = userService.currentUser(); + List availableFormats = userService.getAvailablePostFormats(user); + + model.addAttribute("postForm", postForm); + model.addAttribute("postFormats", availableFormats); + model.addAttribute("postStatus", PostStatus.values()); + model.addAttribute("seoOgLocales", OgLocale.values()); + model.addAttribute("seoOgTypes", OgType.values()); + + return "account/posts/new"; + } + + private String makeFormPostEdition(Long postId, Model model) { + return this.makeFormPostEdition(postId, model, null); + } + + private String makeFormPostEdition(Long postId, Model model, PostForm postForm) { + Post post = postRepository.findOne(postId); + + if (postForm == null) { + postForm = DTOUtil.map(post, PostForm.class); + } + + postForm.init(); + DTOUtil.mapTo(post, postForm); + postForm.initFromPost(post, postService.getTagNames(post.getTags())); + + User user = userService.currentUser(); + List availableFormats = userService.getAvailablePostFormats(user); + + model.addAttribute("post", post); + model.addAttribute("postForm", postForm); + model.addAttribute("postFormats", availableFormats); + model.addAttribute("postStatus", PostStatus.values()); + model.addAttribute("seoOgLocales", OgLocale.values()); + model.addAttribute("seoOgTypes", OgType.values()); + + return "account/posts/edit"; + } + + private void checkAccess(Long postId) { + if (!postService.getPost(postId).getUser().getId().equals(userService.currentUser().getId())) { + throw new AccessDeniedException("You are not allowed to be here"); + } + } + + @RequestMapping(value = "{postId:[0-9]+}/edit") + public String editPost(@PathVariable Long postId, Model model) { + this.checkAccess(postId); + return this.makeFormPostEdition(postId, model); + } + + + @RequestMapping(value = "new") + public String newPost(Model model){ + return this.makeFormPostCreation(model); + } + + + @RequestMapping(value = "{postId:[0-9]+}/delete", method = {DELETE, POST}) + public String deletePost(@PathVariable Long postId){ + this.checkAccess(postId); + postService.deletePost(postRepository.findOne(postId)); + return "redirect:/account/posts"; + } + + @RequestMapping(value = "", method = POST) + public String create(Principal principal, @Valid PostForm postForm, Errors errors, Model model){ + if (errors.hasErrors()) { + Map webErrors = new HashMap<>(); + errors.getAllErrors().forEach(e -> { + String field = ((FieldError)e).getField(); + webErrors.put(field, new WebError(field, e.getDefaultMessage())); + }); + model.addAttribute("errors", webErrors); + return this.makeFormPostCreation(model, postForm); + } else { + Post post = DTOUtil.map(postForm, Post.class); + post.setUser(userRepository.findByEmail(principal.getName())); + post.setTags(postService.parseTagNames(postForm.getPostTags())); + postForm.fillOgFieldsInPost(post); + + postService.createPost(post); + + return "redirect:/account/posts"; + } + } + + @RequestMapping(value = "{postId:[0-9]+}", method = {PUT, POST}) + public String update(@PathVariable Long postId, @Valid PostForm postForm, Errors errors, Model model){ + this.checkAccess(postId); + if (errors.hasErrors()){ + Map webErrors = new HashMap<>(); + errors.getAllErrors().forEach(e -> { + String field = ((FieldError)e).getField(); + webErrors.put(field, new WebError(field, e.getDefaultMessage())); + }); + model.addAttribute("errors", webErrors); + return this.makeFormPostEdition(postId, model, postForm); + } else { + Post post = postRepository.findOne(postId); + DTOUtil.mapTo(postForm, post); + post.setTags(postService.parseTagNames(postForm.getPostTags())); + postForm.fillOgFieldsInPost(post); + + postService.updatePost(post); + + return "redirect:/account/posts"; + } + } + +} diff --git a/src/main/java/ru/bvn13/voidforum/controllers/account/StoredFileController.java b/src/main/java/ru/bvn13/voidforum/controllers/account/StoredFileController.java new file mode 100644 index 0000000..db7f2da --- /dev/null +++ b/src/main/java/ru/bvn13/voidforum/controllers/account/StoredFileController.java @@ -0,0 +1,135 @@ +package ru.bvn13.voidforum.controllers.account; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Sort; +import org.springframework.stereotype.Controller; +import org.springframework.ui.Model; +import org.springframework.util.Assert; +import org.springframework.validation.Errors; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.multipart.MultipartFile; +import org.springframework.web.servlet.mvc.support.RedirectAttributes; +import ru.bvn13.voidforum.error.NotFoundException; +import ru.bvn13.voidforum.forms.StoredFileForm; +import ru.bvn13.voidforum.models.StoredFile; +import ru.bvn13.voidforum.repositories.StoredFileRepository; +import ru.bvn13.voidforum.services.FileStorageService; +import ru.bvn13.voidforum.services.UserService; +import ru.bvn13.voidforum.utils.DTOUtil; + +import javax.validation.Valid; +import java.io.IOException; +import java.util.Date; + +import static org.springframework.web.bind.annotation.RequestMethod.DELETE; +import static org.springframework.web.bind.annotation.RequestMethod.POST; + +@Controller("accountUploadController") +@RequestMapping("account/files") +public class StoredFileController { + + private static final int PAGE_SIZE = 20; + + @Autowired + private FileStorageService storageService; + + @Autowired + private StoredFileRepository storedFileRepository; + + @Autowired + private UserService userService; + + @GetMapping("") + public String index(@RequestParam(defaultValue = "0") int page, Model model) { + Page files = storedFileRepository.findAllByUserOrderByIdDesc(userService.currentUser(), new PageRequest(page, PAGE_SIZE, Sort.Direction.DESC, "id")); + + model.addAttribute("totalPages", files.getTotalPages()); + model.addAttribute("page", page); + model.addAttribute("files", files); + + return "account/files/index"; + } + + @PostMapping("/upload") //new annotation since 4.3 + public String upload(@RequestParam("file") MultipartFile file, RedirectAttributes redirectAttributes) { + if (file.isEmpty()) { + redirectAttributes.addFlashAttribute("uploadStatus", "Please select a file to upload"); + return "redirect:/account/files/status"; + } + + String message = ""; + + try { + + // Get the file and save it somewhere + byte[] bytes = file.getBytes(); + + this.storageService.storeFile(userService.currentUser(), file.getOriginalFilename(), bytes); + + message = "You successfully uploaded '" + file.getOriginalFilename() + "'"; + redirectAttributes.addFlashAttribute("uploadStatus", message); + + } catch (Exception e) { + e.printStackTrace(); + message = "Internal server error occured"; + redirectAttributes.addFlashAttribute("uploadStatus", message); + } + + return "redirect:/account/files/status"; + } + + @GetMapping("/status") + public String uploadStatus() { + return "account/files/status"; + } + + + + @GetMapping(value = "/{fileId:[\\d]+}/edit") + public String editFileById(@PathVariable Long fileId, Model model) { + Assert.notNull(fileId); + StoredFile file = this.storageService.getFileById(fileId); + if (file == null) { + //response.sendError(404, String.format("File %s not found", fileId)); + throw new NotFoundException(String.format("File with id %s not found", fileId)); + } + + StoredFileForm fileForm = DTOUtil.map(file, StoredFileForm.class); + + model.addAttribute("file", file); + model.addAttribute("fileForm", fileForm); + + return "account/files/edit"; + } + + + @PostMapping(value = "/{fileId:[\\d]+}") + public String saveFile(@PathVariable Long fileId, @Valid StoredFileForm fileForm, Errors errors) { + Assert.notNull(fileId); + + if (errors.hasErrors()) { + return String.format("account/files/%d/edit", fileId); + } + + StoredFile storedFile = this.storedFileRepository.findById(fileId); + DTOUtil.mapTo(fileForm, storedFile); + storedFile.setUser(this.userService.currentUser()); + storedFile.setUpdatedAt(new Date()); + this.storedFileRepository.save(storedFile); + + return "redirect:/account/files"; + } + + @RequestMapping(value = "{fileId:[0-9]+}/delete", method = {DELETE, POST}) + public String deletePost(@PathVariable Long fileId){ + try { + this.storageService.deleteFileById(fileId); + } catch (IOException e) { + e.printStackTrace(); + } + return "redirect:/account/files"; + } + +} diff --git a/src/main/java/ru/bvn13/voidforum/controllers/account/UserController.java b/src/main/java/ru/bvn13/voidforum/controllers/account/UserController.java new file mode 100644 index 0000000..bf8eae4 --- /dev/null +++ b/src/main/java/ru/bvn13/voidforum/controllers/account/UserController.java @@ -0,0 +1,71 @@ +package ru.bvn13.voidforum.controllers.account; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.access.AccessDeniedException; +import org.springframework.stereotype.Controller; +import org.springframework.ui.Model; +import org.springframework.util.Assert; +import org.springframework.validation.Errors; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.servlet.mvc.support.RedirectAttributes; +import ru.bvn13.voidforum.forms.UserForm; +import ru.bvn13.voidforum.models.User; +import ru.bvn13.voidforum.repositories.UserRepository; +import ru.bvn13.voidforum.services.UserService; +import ru.bvn13.voidforum.support.web.MessageHelper; + +import javax.validation.Valid; + +import static org.springframework.web.bind.annotation.RequestMethod.POST; + +/** + * bvn13 . + */ +@Controller("accountUserController") +@RequestMapping("account/profile") +public class UserController { + + private UserService userService; + private UserRepository userRepository; + + @Autowired + public UserController(UserService userService, UserRepository userRepository){ + this.userService = userService; + this.userRepository = userRepository; + } + + @RequestMapping() + public String profile(Model model){ + model.addAttribute("user", userService.currentUser()); + + return "account/users/profile"; + } + + @RequestMapping(value = "{userId:[0-9]+}", method = POST) + public String update(@PathVariable Long userId, @Valid UserForm userForm, Errors errors, RedirectAttributes ra){ + User user = userRepository.findOne(userId); + Assert.notNull(user); + + if (!userService.currentUser().getId().equals(userId)) { + throw new AccessDeniedException("You are not allowed here"); + } + + if (errors.hasErrors()){ + // do something + + return "account/users/profile"; + } + + if (!userForm.getNewPassword().isEmpty()){ + + if (!userService.changePassword(user, userForm.getPassword(), userForm.getNewPassword())) + MessageHelper.addErrorAttribute(ra, "Change password failed."); + else + MessageHelper.addSuccessAttribute(ra, "Change password successfully."); + + } + + return "redirect:/account/profile"; + } +} diff --git a/src/main/java/ru/bvn13/voidforum/controllers/admin/AdminController.java b/src/main/java/ru/bvn13/voidforum/controllers/admin/AdminController.java new file mode 100644 index 0000000..05bd1d3 --- /dev/null +++ b/src/main/java/ru/bvn13/voidforum/controllers/admin/AdminController.java @@ -0,0 +1,60 @@ +package ru.bvn13.voidforum.controllers.admin; + +import ru.bvn13.voidforum.forms.SettingsForm; +import ru.bvn13.voidforum.services.AppSetting; +import ru.bvn13.voidforum.support.web.MessageHelper; +import ru.bvn13.voidforum.utils.DTOUtil; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Controller; +import org.springframework.ui.Model; +import org.springframework.validation.Errors; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.servlet.mvc.support.RedirectAttributes; + +import javax.validation.Valid; + +/** + * bvn13 + */ +@Controller +@RequestMapping("admin") +public class AdminController { + + private AppSetting appSetting; + + @Autowired + public AdminController( AppSetting appSetting){ + this.appSetting = appSetting; + } + + @RequestMapping("") + public String index(){ + return "admin/home/index"; + } + + @RequestMapping(value = "settings") + public String settings(Model model){ + SettingsForm settingsForm = DTOUtil.map(appSetting, SettingsForm.class); + + model.addAttribute("settings", settingsForm); + return "admin/home/settings"; + } + + @RequestMapping(value = "settings", method = RequestMethod.POST) + public String updateSettings(@Valid SettingsForm settingsForm, Errors errors, Model model, RedirectAttributes ra){ + if (errors.hasErrors()){ + return "admin/settings"; + } else { + appSetting.setSiteName(settingsForm.getSiteName()); + appSetting.setSiteSlogan(settingsForm.getSiteSlogan()); + appSetting.setPageSize(settingsForm.getPageSize()); + appSetting.setStoragePath(settingsForm.getStoragePath()); + appSetting.setMainUri(settingsForm.getMainUri()); + + MessageHelper.addSuccessAttribute(ra, "Update settings successfully."); + + return "redirect:settings"; + } + } +} diff --git a/src/main/java/ru/bvn13/voidforum/controllers/admin/PostController.java b/src/main/java/ru/bvn13/voidforum/controllers/admin/PostController.java new file mode 100644 index 0000000..54c527c --- /dev/null +++ b/src/main/java/ru/bvn13/voidforum/controllers/admin/PostController.java @@ -0,0 +1,184 @@ +package ru.bvn13.voidforum.controllers.admin; + +import ru.bvn13.voidforum.forms.PostForm; +import ru.bvn13.voidforum.models.Post; +import ru.bvn13.voidforum.models.User; +import ru.bvn13.voidforum.models.support.*; +import ru.bvn13.voidforum.repositories.PostRepository; +import ru.bvn13.voidforum.repositories.UserRepository; +import ru.bvn13.voidforum.services.PostService; +import ru.bvn13.voidforum.services.PrivilegeService; +import ru.bvn13.voidforum.services.UserService; +import ru.bvn13.voidforum.utils.DTOUtil; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Sort; +import org.springframework.stereotype.Controller; +import org.springframework.ui.Model; +import org.springframework.validation.Errors; +import org.springframework.validation.FieldError; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; + +import javax.validation.Valid; +import java.security.Principal; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import static org.springframework.web.bind.annotation.RequestMethod.*; + +/** + * bvn13 + */ +@Controller("adminPostController") +@RequestMapping("admin/posts") +public class PostController { + + @Autowired + private PostRepository postRepository; + + @Autowired + private PostService postService; + + @Autowired + private UserRepository userRepository; + + @Autowired + private UserService userService; + + + private static final int PAGE_SIZE = 20; + + @RequestMapping(value = "") + public String index(@RequestParam(defaultValue = "0") int page, Model model) { + Page posts = postRepository.findAll(new PageRequest(page, PAGE_SIZE, Sort.Direction.DESC, "id")); + + model.addAttribute("totalPages", posts.getTotalPages()); + model.addAttribute("page", page); + model.addAttribute("posts", posts); + + return "admin/posts/index"; + } + + private String makeFormPostCreation(Model model) { + PostForm postForm = DTOUtil.map(new Post(), PostForm.class); + postForm.init(); + return this.makeFormPostCreation(model, postForm); + } + + private String makeFormPostCreation(Model model, PostForm postForm) { + + User user = userService.currentUser(); + List availableFormats = userService.getAvailablePostFormats(user); + + model.addAttribute("postForm", postForm); + model.addAttribute("postFormats", availableFormats); + model.addAttribute("postStatus", PostStatus.values()); + model.addAttribute("seoOgLocales", OgLocale.values()); + model.addAttribute("seoOgTypes", OgType.values()); + + return "admin/posts/new"; + } + + @RequestMapping(value = "new") + public String newPost(Model model){ + return this.makeFormPostCreation(model); + } + + private String makeFormPostEdition(Long postId, Model model) { + return this.makeFormPostEdition(postId, model, null); + } + + private String makeFormPostEdition(Long postId, Model model, PostForm postForm) { + Post post = postRepository.findOne(postId); + + if (postForm == null) { + postForm = DTOUtil.map(post, PostForm.class); + } + + postForm.init(); + DTOUtil.mapTo(post, postForm); + postForm.initFromPost(post, postService.getTagNames(post.getTags())); + + User user = userService.currentUser(); + List availableFormats = userService.getAvailablePostFormats(user); + + model.addAttribute("post", post); + model.addAttribute("postForm", postForm); + model.addAttribute("postFormats", availableFormats); + model.addAttribute("postStatus", PostStatus.values()); + model.addAttribute("seoOgLocales", OgLocale.values()); + model.addAttribute("seoOgTypes", OgType.values()); + + return "admin/posts/edit"; + } + + @RequestMapping(value = "{postId:[0-9]+}/edit") + public String editPost(@PathVariable Long postId, Model model){ + return this.makeFormPostEdition(postId, model); + } + + @RequestMapping(value = "{postId:[0-9]+}/delete", method = {DELETE, POST}) + public String deletePost(@PathVariable Long postId){ + postService.deletePost(postRepository.findOne(postId)); + return "redirect:/admin/posts"; + } + + @RequestMapping(value = "{postId:[0-9]+}/censore", method = {PUT, POST}) + public String censorePost(@PathVariable Long postId){ + postService.censorePost(postRepository.findOne(postId)); + return "redirect:/admin/posts"; + } + + @RequestMapping(value = "", method = POST) + public String create(Principal principal, @Valid PostForm postForm, Errors errors, Model model){ + if (errors.hasErrors()) { + Map webErrors = new HashMap<>(); + errors.getAllErrors().forEach(e -> { + String field = ((FieldError)e).getField(); + webErrors.put(field, new WebError(field, e.getDefaultMessage())); + }); + model.addAttribute("errors", webErrors); + return this.makeFormPostCreation(model, postForm); + } else { + Post post = DTOUtil.map(postForm, Post.class); + post.setUser(userRepository.findByEmail(principal.getName())); + post.setTags(postService.parseTagNames(postForm.getPostTags())); + postForm.fillOgFieldsInPost(post); + + postService.createPost(post); + + return "redirect:/admin/posts"; + } + } + + @RequestMapping(value = "{postId:[0-9]+}", method = {PUT, POST}) + public String update(@PathVariable Long postId, @Valid PostForm postForm, Errors errors, Model model){ + if (errors.hasErrors()){ + Map webErrors = new HashMap<>(); + errors.getAllErrors().forEach(e -> { + String field = ((FieldError)e).getField(); + webErrors.put(field, new WebError(field, e.getDefaultMessage())); + }); + model.addAttribute("errors", webErrors); + return this.makeFormPostEdition(postId, model, postForm); + } else { + Post post = postRepository.findOne(postId); + DTOUtil.mapTo(postForm, post); + post.setTags(postService.parseTagNames(postForm.getPostTags())); + postForm.fillOgFieldsInPost(post); + + postService.updatePost(post); + + return "redirect:/admin/posts"; + } + } + + + + +} diff --git a/src/main/java/ru/bvn13/voidforum/controllers/admin/SeoRobotAgentController.java b/src/main/java/ru/bvn13/voidforum/controllers/admin/SeoRobotAgentController.java new file mode 100644 index 0000000..05bebfc --- /dev/null +++ b/src/main/java/ru/bvn13/voidforum/controllers/admin/SeoRobotAgentController.java @@ -0,0 +1,70 @@ +package ru.bvn13.voidforum.controllers.admin; + +import ru.bvn13.voidforum.forms.SeoRobotAgentForm; +import ru.bvn13.voidforum.models.SeoRobotAgent; +import ru.bvn13.voidforum.repositories.SeoRobotAgentRepository; +import ru.bvn13.voidforum.utils.DTOUtil; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Controller; +import org.springframework.ui.Model; +import org.springframework.util.Assert; +import org.springframework.validation.Errors; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestMapping; + +import javax.validation.Valid; + +@Controller +@RequestMapping(value = "/admin/robotsAgents") +public class SeoRobotAgentController { + + @Autowired + private SeoRobotAgentRepository seoRobotAgentRepository; + + @GetMapping() + public String getSeoRobotsAgents(Model model) { + model.addAttribute("records", this.seoRobotAgentRepository.findAll()); + model.addAttribute("form", new SeoRobotAgentForm()); + return "admin/robotsAgents/index"; + } + + + @GetMapping(value = "/{recordId:[\\d]+}/edit") + public String editSeoRobotAgent(@PathVariable Long recordId, Model model) { + + SeoRobotAgent ua = this.seoRobotAgentRepository.findOne(recordId); + + Assert.notNull(ua); + + model.addAttribute("form", DTOUtil.map(ua, SeoRobotAgentForm.class)); + + return "admin/robotsAgents/edit"; + } + + @PostMapping(value = "/{recordId:[\\d]+}/edit") + public String saveSeoRobotAgent(@PathVariable Long recordId, @Valid SeoRobotAgentForm form, Errors errors) { + SeoRobotAgent ua = null; + if (recordId.equals(0L)) { + ua = new SeoRobotAgent(); + } else { + ua = this.seoRobotAgentRepository.findOne(recordId); + } + Assert.notNull(ua); + + DTOUtil.mapTo(form, ua); + + this.seoRobotAgentRepository.save(ua); + + return "redirect:/admin/robotsAgents"; + } + + + @PostMapping(value = "/{recordId:[\\d]+}/delete") + public String deleteSeoRobotAgent(@PathVariable Long recordId) { + this.seoRobotAgentRepository.delete(recordId); + return "redirect:/admin/robotsAgents"; + } + +} diff --git a/src/main/java/ru/bvn13/voidforum/controllers/admin/StoredFileController.java b/src/main/java/ru/bvn13/voidforum/controllers/admin/StoredFileController.java new file mode 100644 index 0000000..4668339 --- /dev/null +++ b/src/main/java/ru/bvn13/voidforum/controllers/admin/StoredFileController.java @@ -0,0 +1,135 @@ +package ru.bvn13.voidforum.controllers.admin; + +import ru.bvn13.voidforum.error.NotFoundException; +import ru.bvn13.voidforum.forms.StoredFileForm; +import ru.bvn13.voidforum.models.StoredFile; +import ru.bvn13.voidforum.repositories.StoredFileRepository; +import ru.bvn13.voidforum.services.FileStorageService; +import ru.bvn13.voidforum.services.UserService; +import ru.bvn13.voidforum.utils.DTOUtil; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Sort; +import org.springframework.stereotype.Controller; +import org.springframework.ui.Model; +import org.springframework.util.Assert; +import org.springframework.validation.Errors; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.multipart.MultipartFile; +import org.springframework.web.servlet.mvc.support.RedirectAttributes; + +import javax.validation.Valid; +import java.io.IOException; +import java.util.Date; + +import static org.springframework.web.bind.annotation.RequestMethod.DELETE; +import static org.springframework.web.bind.annotation.RequestMethod.POST; + +@Controller("adminUploadController") +@RequestMapping("admin/files") +public class StoredFileController { + + private static final int PAGE_SIZE = 20; + + @Autowired + private FileStorageService storageService; + + @Autowired + private StoredFileRepository storedFileRepository; + + @Autowired + private UserService userService; + + @GetMapping("") + public String index(@RequestParam(defaultValue = "0") int page, Model model) { + Page files = storedFileRepository.findAll(new PageRequest(page, PAGE_SIZE, Sort.Direction.DESC, "id")); + + model.addAttribute("totalPages", files.getTotalPages()); + model.addAttribute("page", page); + model.addAttribute("files", files); + + return "admin/files/index"; + } + + @PostMapping("/upload") //new annotation since 4.3 + public String upload(@RequestParam("file") MultipartFile file, RedirectAttributes redirectAttributes) { + if (file.isEmpty()) { + redirectAttributes.addFlashAttribute("uploadStatus", "Please select a file to upload"); + return "redirect:/admin/files/status"; + } + + String message = ""; + + try { + + // Get the file and save it somewhere + byte[] bytes = file.getBytes(); + + this.storageService.storeFile(userService.currentUser(), file.getOriginalFilename(), bytes); + + message = "You successfully uploaded '" + file.getOriginalFilename() + "'"; + redirectAttributes.addFlashAttribute("uploadStatus", message); + + } catch (Exception e) { + e.printStackTrace(); + message = "Internal server error occured"; + redirectAttributes.addFlashAttribute("uploadStatus", message); + } + + return "redirect:/admin/files/status"; + } + + @GetMapping("/status") + public String uploadStatus() { + return "admin/files/status"; + } + + + + @GetMapping(value = "/{fileId:[\\d]+}/edit") + public String editFileById(@PathVariable Long fileId, Model model) { + Assert.notNull(fileId); + StoredFile file = this.storageService.getFileById(fileId); + if (file == null) { + //response.sendError(404, String.format("File %s not found", fileId)); + throw new NotFoundException(String.format("File with id %s not found", fileId)); + } + + StoredFileForm fileForm = DTOUtil.map(file, StoredFileForm.class); + + model.addAttribute("file", file); + model.addAttribute("fileForm", fileForm); + + return "admin/files/edit"; + } + + + @PostMapping(value = "/{fileId:[\\d]+}") + public String saveFile(@PathVariable Long fileId, @Valid StoredFileForm fileForm, Errors errors) { + Assert.notNull(fileId); + + if (errors.hasErrors()) { + return String.format("admin/files/%d/edit", fileId); + } + + StoredFile storedFile = this.storedFileRepository.findById(fileId); + DTOUtil.mapTo(fileForm, storedFile); + storedFile.setUser(this.userService.currentUser()); + storedFile.setUpdatedAt(new Date()); + this.storedFileRepository.save(storedFile); + + return "redirect:/admin/files"; + } + + @RequestMapping(value = "{fileId:[0-9]+}/delete", method = {DELETE, POST}) + public String deletePost(@PathVariable Long fileId){ + try { + this.storageService.deleteFileById(fileId); + } catch (IOException e) { + e.printStackTrace(); + } + return "redirect:/admin/files"; + } + +} diff --git a/src/main/java/ru/bvn13/voidforum/controllers/admin/UserController.java b/src/main/java/ru/bvn13/voidforum/controllers/admin/UserController.java new file mode 100644 index 0000000..009b039 --- /dev/null +++ b/src/main/java/ru/bvn13/voidforum/controllers/admin/UserController.java @@ -0,0 +1,66 @@ +package ru.bvn13.voidforum.controllers.admin; + +import ru.bvn13.voidforum.forms.UserForm; +import ru.bvn13.voidforum.models.User; +import ru.bvn13.voidforum.repositories.UserRepository; +import ru.bvn13.voidforum.services.UserService; +import ru.bvn13.voidforum.support.web.MessageHelper; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Controller; +import org.springframework.ui.Model; +import org.springframework.util.Assert; +import org.springframework.validation.Errors; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.servlet.mvc.support.RedirectAttributes; + +import javax.validation.Valid; + +import static org.springframework.web.bind.annotation.RequestMethod.POST; + +/** + * bvn13 . + */ +@Controller("adminUserController") +@RequestMapping("admin/users") +public class UserController { + + private UserService userService; + private UserRepository userRepository; + + @Autowired + public UserController(UserService userService, UserRepository userRepository){ + this.userService = userService; + this.userRepository = userRepository; + } + + @RequestMapping("profile") + public String profile(Model model){ + model.addAttribute("user", userService.currentUser()); + + return "admin/users/profile"; + } + + @RequestMapping(value = "{userId:[0-9]+}", method = POST) + public String update(@PathVariable Long userId, @Valid UserForm userForm, Errors errors, RedirectAttributes ra){ + User user = userRepository.findOne(userId); + Assert.notNull(user); + + if (errors.hasErrors()){ + // do something + + return "admin/users/profile"; + } + + if (!userForm.getNewPassword().isEmpty()){ + + if (!userService.changePassword(user, userForm.getPassword(), userForm.getNewPassword())) + MessageHelper.addErrorAttribute(ra, "Change password failed."); + else + MessageHelper.addSuccessAttribute(ra, "Change password successfully."); + + } + + return "redirect:profile"; + } +} diff --git a/src/main/java/ru/bvn13/voidforum/controllers/seo/SitemapController.java b/src/main/java/ru/bvn13/voidforum/controllers/seo/SitemapController.java new file mode 100644 index 0000000..fbff056 --- /dev/null +++ b/src/main/java/ru/bvn13/voidforum/controllers/seo/SitemapController.java @@ -0,0 +1,32 @@ +package ru.bvn13.voidforum.controllers.seo; + +import ru.bvn13.voidforum.models.Post; +import ru.bvn13.voidforum.services.PostService; +import ru.bvn13.voidforum.services.SeoService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.MediaType; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.ResponseBody; + +import java.util.List; + +@Controller +@RequestMapping(value = {"/seo", ""}) +public class SitemapController { + + @Autowired + private PostService postService; + + @Autowired + private SeoService seoService; + + @GetMapping(value = "/sitemap", produces = MediaType.APPLICATION_XML_VALUE) + public @ResponseBody + String getSiteMap() { + List posts = this.postService.getAllPublishedPosts(); + return this.seoService.createSitemap(posts); + } + +} diff --git a/src/main/java/ru/bvn13/voidforum/error/EmailExistsException.java b/src/main/java/ru/bvn13/voidforum/error/EmailExistsException.java new file mode 100644 index 0000000..209a03c --- /dev/null +++ b/src/main/java/ru/bvn13/voidforum/error/EmailExistsException.java @@ -0,0 +1,14 @@ +package ru.bvn13.voidforum.error; + +import lombok.Getter; + +public class EmailExistsException extends Exception { + @Getter + private String message; + + public EmailExistsException(){} + + public EmailExistsException(String message){ + this.message = message; + } +} diff --git a/src/main/java/ru/bvn13/voidforum/error/ExceptionHandlerController.java b/src/main/java/ru/bvn13/voidforum/error/ExceptionHandlerController.java new file mode 100644 index 0000000..872ce82 --- /dev/null +++ b/src/main/java/ru/bvn13/voidforum/error/ExceptionHandlerController.java @@ -0,0 +1,53 @@ +package ru.bvn13.voidforum.error; + +import com.google.common.base.Throwables; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.http.HttpStatus; +import org.springframework.web.bind.annotation.ControllerAdvice; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.bind.annotation.ResponseStatus; +import org.springframework.web.servlet.ModelAndView; + +import javax.servlet.http.HttpServletRequest; + +/** + * General error handler for the application. + */ +@ControllerAdvice +class ExceptionHandlerController { + private static final Logger logger = LoggerFactory.getLogger(ExceptionHandlerController.class); + + @ResponseStatus(HttpStatus.NOT_FOUND) + @ExceptionHandler(NotFoundException.class) + public ModelAndView notFound(HttpServletRequest request, NotFoundException exception){ + String uri = request.getRequestURI(); + logger.error("Request page: " + uri + " raised NotFoundException : " + exception); + + ModelAndView model = new ModelAndView("error/general"); + model.addObject("status", HttpStatus.NOT_FOUND.value()); + model.addObject("error", HttpStatus.NOT_FOUND.getReasonPhrase()); + model.addObject("path", uri); + model.addObject("customMessage", exception.getMessage()); + + return model; + } + + /** + * Handle all exceptions + */ +// @ResponseStatus(HttpStatus.SERVICE_UNAVAILABLE) + @ExceptionHandler(Exception.class) + public ModelAndView exception(HttpServletRequest request, Exception exception) { + String uri = request.getRequestURI(); + logger.error("Request page: " + uri + " raised exception : " + exception); + + ModelAndView model = new ModelAndView("error/general"); + model.addObject("error", Throwables.getRootCause(exception).getMessage()); + model.addObject("status", Throwables.getRootCause(exception).getCause()); + model.addObject("path", uri); + model.addObject("customMessage", exception.getMessage()); + + return model; + } +} \ No newline at end of file diff --git a/src/main/java/ru/bvn13/voidforum/error/NicknameExistsException.java b/src/main/java/ru/bvn13/voidforum/error/NicknameExistsException.java new file mode 100644 index 0000000..2b19770 --- /dev/null +++ b/src/main/java/ru/bvn13/voidforum/error/NicknameExistsException.java @@ -0,0 +1,15 @@ +package ru.bvn13.voidforum.error; + + +import lombok.Getter; + +public class NicknameExistsException extends Exception { + @Getter + private String message; + + public NicknameExistsException(){} + + public NicknameExistsException(String message){ + this.message = message; + } +} diff --git a/src/main/java/ru/bvn13/voidforum/error/NotFoundException.java b/src/main/java/ru/bvn13/voidforum/error/NotFoundException.java new file mode 100644 index 0000000..c443b31 --- /dev/null +++ b/src/main/java/ru/bvn13/voidforum/error/NotFoundException.java @@ -0,0 +1,25 @@ +package ru.bvn13.voidforum.error; + +import org.springframework.http.HttpStatus; +import org.springframework.web.bind.annotation.ResponseStatus; + +/** + * @author Raysmond + */ +@ResponseStatus(value = HttpStatus.NOT_FOUND) +public final class NotFoundException extends RuntimeException { + private String message; + + public NotFoundException(){ + + } + + public NotFoundException(String message){ + this.message = message; + } + + @Override + public String getMessage(){ + return message; + } +} \ No newline at end of file diff --git a/src/main/java/ru/bvn13/voidforum/forms/CommentForm.java b/src/main/java/ru/bvn13/voidforum/forms/CommentForm.java new file mode 100644 index 0000000..88365f9 --- /dev/null +++ b/src/main/java/ru/bvn13/voidforum/forms/CommentForm.java @@ -0,0 +1,29 @@ +package ru.bvn13.voidforum.forms; + +import lombok.Data; +import ru.bvn13.voidforum.models.Comment; +import ru.bvn13.voidforum.models.Post; +import ru.bvn13.voidforum.models.User; +import ru.bvn13.voidforum.models.support.CommentFormat; + +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; + +/** + * Created by bvn13 on 08.12.2017. + */ +@Data +public class CommentForm { + + @NotNull + private Integer postId; + + private Integer parentCommentId; + + @NotEmpty + private String content; + + @NotNull + private CommentFormat commentFormat; + +} diff --git a/src/main/java/ru/bvn13/voidforum/forms/LikeForm.java b/src/main/java/ru/bvn13/voidforum/forms/LikeForm.java new file mode 100644 index 0000000..9376d39 --- /dev/null +++ b/src/main/java/ru/bvn13/voidforum/forms/LikeForm.java @@ -0,0 +1,13 @@ +package ru.bvn13.voidforum.forms; + +import lombok.Data; + +import javax.validation.constraints.NotNull; + +@Data +public class LikeForm { + + @NotNull + private String sympathy = "0"; + +} diff --git a/src/main/java/ru/bvn13/voidforum/forms/PostForm.java b/src/main/java/ru/bvn13/voidforum/forms/PostForm.java new file mode 100644 index 0000000..ddc4551 --- /dev/null +++ b/src/main/java/ru/bvn13/voidforum/forms/PostForm.java @@ -0,0 +1,117 @@ +package ru.bvn13.voidforum.forms; + +import lombok.Data; +import javax.validation.constraints.NotEmpty; +import ru.bvn13.voidforum.models.Post; +import ru.bvn13.voidforum.models.SeoPostData; +import ru.bvn13.voidforum.models.support.OgLocale; +import ru.bvn13.voidforum.models.support.OgType; +import ru.bvn13.voidforum.models.support.PostFormat; +import ru.bvn13.voidforum.models.support.PostStatus; + +import javax.validation.constraints.NotNull; + +/** + * bvn13 + */ +@Data +public class PostForm { + @NotEmpty + private String title; + + @NotEmpty + private String content; + + @NotNull + private PostFormat postFormat; + + @NotNull + private PostStatus postStatus; + + @NotNull + private String permalink; + + @NotNull + private String postTags; + + @NotNull + private String seoKeywords; + + @NotNull + private String seoDescription; + + +// @NotNull +// private String seoOgTitle; + + @NotNull + private OgType seoOgType; + + @NotNull + private String seoOgImage; + + @NotNull + private String seoOgVideo; + + @NotNull + private OgLocale seoOgLocale; + + @NotNull + private Boolean deletedMark; + + @NotNull + private Boolean censored; + + public void init() { + this.setTitle(""); + this.setPermalink(""); + this.setContent(""); + this.setPostTags(""); + this.setPostStatus(PostStatus.DRAFT); + this.setPostFormat(PostFormat.MARKDOWN); + this.setSeoKeywords(""); + this.setSeoOgImage(""); + this.setSeoOgLocale(OgLocale.ru_RU); + //this.setSeoOgTitle(""); + this.setSeoOgType(OgType.WEBSITE); + this.setSeoOgVideo(""); + this.setDeletedMark(false); + this.setCensored(false); + } + + public void initFromPost(Post post) { + if (post.getSeoData() != null) { + this.setSeoOgImage(post.getSeoData().getOgImage()); + this.setSeoOgVideo(post.getSeoData().getOgVideo()); + this.setSeoOgLocale(post.getSeoData().getOgLocale()); + this.setSeoOgType(post.getSeoData().getOgType()); + } else { + this.setSeoOgImage(""); + this.setSeoOgLocale(OgLocale.ru_RU); + //this.setSeoOgTitle(""); + this.setSeoOgType(OgType.WEBSITE); + this.setSeoOgVideo(""); + } + } + + public void initFromPost(Post post, String postTags) { + this.initFromPost(post); + this.setPostTags(postTags); + } + + public void fillOgFieldsInPost(Post post) { + SeoPostData data = null; + if (post.getSeoData() == null) { + data = new SeoPostData(); + } else { + data = post.getSeoData(); + } + data.setOgImage(this.seoOgImage); + data.setOgLocale(this.seoOgLocale); + data.setOgTitle(this.title); + data.setOgType(this.seoOgType); + data.setOgVideo(this.seoOgVideo); + post.setSeoData(data); + } + +} diff --git a/src/main/java/ru/bvn13/voidforum/forms/RegistrationForm.java b/src/main/java/ru/bvn13/voidforum/forms/RegistrationForm.java new file mode 100644 index 0000000..766fecc --- /dev/null +++ b/src/main/java/ru/bvn13/voidforum/forms/RegistrationForm.java @@ -0,0 +1,30 @@ +package ru.bvn13.voidforum.forms; + +import lombok.Data; + + +import javax.validation.constraints.Email; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; + +/** + * bvn13 . + */ +@Data +public class RegistrationForm { + + @Email(message = "Email should be valid") + @NotBlank(message = "Specify your email") + private String username; + + @NotBlank(message = "Specify your nickname") + private String nickname; + + @NotBlank(message = "Specify your password") + private String password; + + @NotBlank(message = "Verify your password") + private String passwordCheck; + +} diff --git a/src/main/java/ru/bvn13/voidforum/forms/SeoRobotAgentForm.java b/src/main/java/ru/bvn13/voidforum/forms/SeoRobotAgentForm.java new file mode 100644 index 0000000..9db2f8d --- /dev/null +++ b/src/main/java/ru/bvn13/voidforum/forms/SeoRobotAgentForm.java @@ -0,0 +1,18 @@ +package ru.bvn13.voidforum.forms; + +import lombok.Data; + +import javax.validation.constraints.NotNull; + +@Data +public class SeoRobotAgentForm { + + @NotNull + private Long id = 0L; + + @NotNull + private String userAgent = ""; + + @NotNull + private Boolean isRegexp = false; +} diff --git a/src/main/java/ru/bvn13/voidforum/forms/SettingsForm.java b/src/main/java/ru/bvn13/voidforum/forms/SettingsForm.java new file mode 100644 index 0000000..d42a2c2 --- /dev/null +++ b/src/main/java/ru/bvn13/voidforum/forms/SettingsForm.java @@ -0,0 +1,30 @@ +package ru.bvn13.voidforum.forms; + +import lombok.Data; +import org.hibernate.validator.constraints.NotEmpty; + +import javax.validation.constraints.NotNull; + +/** + * bvn13 + */ +@Data +public class SettingsForm { + + @NotEmpty + @NotNull + private String siteName; + + @NotNull + private String siteSlogan; + + @NotNull + private Integer pageSize; + + @NotNull + private String storagePath; + + @NotNull + private String mainUri; + +} diff --git a/src/main/java/ru/bvn13/voidforum/forms/StoredFileForm.java b/src/main/java/ru/bvn13/voidforum/forms/StoredFileForm.java new file mode 100644 index 0000000..187ff3a --- /dev/null +++ b/src/main/java/ru/bvn13/voidforum/forms/StoredFileForm.java @@ -0,0 +1,22 @@ +package ru.bvn13.voidforum.forms; + +import lombok.Data; + +import javax.validation.constraints.NotNull; + +@Data +public class StoredFileForm { + + @NotNull + private String title; + + @NotNull + private String name; + + @NotNull + private String path; + + @NotNull + private Long size; + +} diff --git a/src/main/java/ru/bvn13/voidforum/forms/UserForm.java b/src/main/java/ru/bvn13/voidforum/forms/UserForm.java new file mode 100644 index 0000000..b0e0603 --- /dev/null +++ b/src/main/java/ru/bvn13/voidforum/forms/UserForm.java @@ -0,0 +1,22 @@ +package ru.bvn13.voidforum.forms; + +import lombok.Data; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; +import javax.validation.constraints.Email; + +/** + * bvn13 . + */ +@Data +public class UserForm { + + @NotBlank(message = "Enter your password") + private String password; + + @NotBlank(message = "Specify your new password") + private String newPassword; + +} diff --git a/src/main/java/ru/bvn13/voidforum/models/BaseModel.java b/src/main/java/ru/bvn13/voidforum/models/BaseModel.java new file mode 100644 index 0000000..d937f85 --- /dev/null +++ b/src/main/java/ru/bvn13/voidforum/models/BaseModel.java @@ -0,0 +1,80 @@ +package ru.bvn13.voidforum.models; + +import org.apache.commons.lang3.builder.HashCodeBuilder; + +import javax.persistence.*; +import java.io.Serializable; +import java.util.Date; + +/** + * An abstract base model class for entities + * + * @author bvn13 + */ +@MappedSuperclass +public abstract class BaseModel implements Comparable, Serializable { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "id") + private Long id; + + @Column(nullable = false) + private Date createdAt; + + @Column(nullable = false) + private Date updatedAt; + + @PrePersist + public void prePersist(){ + createdAt = updatedAt = new Date(); + } + + @PreUpdate + public void preUpdate(){ + updatedAt = new Date(); + } + + @Override + public int compareTo(BaseModel o) { + return this.getId().compareTo(o.getId()); + } + + public boolean equals(Object other) { + if (other == null || other.getClass() != this.getClass()) + return false; + + return this.getId().equals(((BaseModel) other).getId()); + } + + + public int hashCode() { + return new HashCodeBuilder().append(getId()).toHashCode(); + } + + + public Long getId() { + return id; + } + + public void setId(Long _id) { + id = _id; + } + + public Date getCreatedAt() { + return createdAt; + } + + public void setCreatedAt(Date createdAt) { + this.createdAt = createdAt; + } + + public Date getUpdatedAt() { + return updatedAt; + } + + public void setUpdatedAt(Date updatedAt) { + this.updatedAt = updatedAt; + } + +} \ No newline at end of file diff --git a/src/main/java/ru/bvn13/voidforum/models/Comment.java b/src/main/java/ru/bvn13/voidforum/models/Comment.java new file mode 100644 index 0000000..1b79bec --- /dev/null +++ b/src/main/java/ru/bvn13/voidforum/models/Comment.java @@ -0,0 +1,49 @@ +package ru.bvn13.voidforum.models; + +import lombok.Getter; +import lombok.Setter; +import org.hibernate.annotations.Type; +import ru.bvn13.voidforum.models.support.CommentFormat; + +import javax.persistence.*; +import java.util.ArrayList; +import java.util.Collection; + +@Entity +@Table(name = "comments") +@Getter +@Setter +public class Comment extends BaseModel { + + @ManyToOne + private User user; + + @ManyToOne + private Post post; + + @ManyToOne + private Comment parentComment; + + + @OneToMany(fetch = FetchType.LAZY, mappedBy = "parentComment", cascade = CascadeType.REMOVE) + private Collection children = new ArrayList<>(); + + + @Type(type="text") + @Getter + @Setter + private String content; + + @Type(type = "text") + private String renderedContent; + + @Column(nullable = false) + @Enumerated(EnumType.STRING) + private CommentFormat commentFormat = CommentFormat.MARKDOWN; + + @Column(nullable = false, columnDefinition = "boolean DEFAULT false") + private Boolean deletedMark; + + @Column(nullable = false, columnDefinition = "integer DEFAULT 0") + private Integer depth; +} diff --git a/src/main/java/ru/bvn13/voidforum/models/Like.java b/src/main/java/ru/bvn13/voidforum/models/Like.java new file mode 100644 index 0000000..497c364 --- /dev/null +++ b/src/main/java/ru/bvn13/voidforum/models/Like.java @@ -0,0 +1,32 @@ +package ru.bvn13.voidforum.models; + +import lombok.Getter; +import lombok.Setter; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.ManyToOne; +import javax.persistence.Table; + +@Entity +@Table(name = "posts_likes") +@Getter +@Setter +public class Like extends BaseModel { + + @ManyToOne + private User user; + + @ManyToOne + private Post post; + + @Column(nullable = false) + private Integer sympathy; + + @Column(nullable = false) + private String clientIp; + + @Column(nullable = false, columnDefinition = "boolean default false") + private Boolean isAdmin; + +} diff --git a/src/main/java/ru/bvn13/voidforum/models/Post.java b/src/main/java/ru/bvn13/voidforum/models/Post.java new file mode 100644 index 0000000..d657f12 --- /dev/null +++ b/src/main/java/ru/bvn13/voidforum/models/Post.java @@ -0,0 +1,101 @@ +package ru.bvn13.voidforum.models; + +import com.fasterxml.jackson.annotation.JsonInclude; +import lombok.Getter; +import lombok.Setter; +import org.hibernate.annotations.Type; +import org.springframework.util.StringUtils; +import ru.bvn13.voidforum.models.support.PostFormat; +import ru.bvn13.voidforum.models.support.PostStatus; +import ru.bvn13.voidforum.models.support.PostType; + +import javax.persistence.*; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashSet; +import java.util.Set; + +/** + * bvn13 + */ +@Entity +@Table(name = "posts") +@Getter +@Setter +public class Post extends BaseModel { + private static final SimpleDateFormat SLUG_DATE_FORMAT = new SimpleDateFormat("yyyy/MM/dd"); + + @ManyToOne + private User user; + + @Column(nullable = false) + private String title; + + @Type(type="text") + private String content; + + @Type(type = "text") + private String renderedContent; + + @Column(nullable = false) + @Enumerated(EnumType.STRING) + private PostStatus postStatus = PostStatus.PUBLISHED; + + @Column(nullable = false) + @Enumerated(EnumType.STRING) + private PostFormat postFormat = PostFormat.MARKDOWN; + + @Column(nullable = false) + @Enumerated(EnumType.STRING) + private PostType postType = PostType.POST; + + @ManyToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL) + @JoinTable(name = "posts_tags", + joinColumns = {@JoinColumn(name = "post_id", nullable = false, updatable = false)}, + inverseJoinColumns = {@JoinColumn(name = "tag_id", nullable = false, updatable = false)} + ) + private Set tags = new HashSet<>(); + + @Column(nullable = false, columnDefinition = "character varying DEFAULT ''") + private String seoKeywords = ""; + + @Column(nullable = false, columnDefinition = "character varying DEFAULT ''") + private String seoDescription = ""; + + @OneToOne + private SeoPostData seoData; + + @Type(type="text") + private String permalink; + + public void setPermalink(String permalink){ + String token = permalink.toLowerCase().replace("\n", " ").replaceAll("[^a-z\\d\\s]", " "); + this.permalink = StringUtils.arrayToDelimitedString(StringUtils.tokenizeToStringArray(token, " "), "-"); + } + + private Long visitsCount = 0L; + public Long getVisitsCount() { + if (this.visitsCount == null) return 0L; + else return this.visitsCount; + } + + private Integer sympathyCount = 0; + public Integer getSympathyCount() { + if (this.sympathyCount == null) return 0; + else return this.sympathyCount; + } + + @OneToMany(fetch = FetchType.LAZY, mappedBy = "post", cascade = CascadeType.REMOVE) + private Collection comments = new ArrayList<>(); + + @JsonInclude + @Transient + private Comment lastComment; + + @Column(nullable = false, columnDefinition = "boolean DEFAULT false") + private Boolean deletedMark; + + @Column(nullable = false, columnDefinition = "boolean DEFAULT false") + private Boolean censored; +} diff --git a/src/main/java/ru/bvn13/voidforum/models/Privilege.java b/src/main/java/ru/bvn13/voidforum/models/Privilege.java new file mode 100644 index 0000000..664d034 --- /dev/null +++ b/src/main/java/ru/bvn13/voidforum/models/Privilege.java @@ -0,0 +1,26 @@ +package ru.bvn13.voidforum.models; + +import lombok.Getter; +import lombok.Setter; + +import javax.persistence.*; +import java.util.Collection; + +@Entity +@Table(name = "privileges") +@Getter +@Setter +public class Privilege extends BaseModel { + + private String name; + + @ManyToMany(fetch = FetchType.LAZY, mappedBy = "privileges") + private Collection roles; + + public Privilege() {} + + public Privilege(String name) { + this.name = name; + } + +} diff --git a/src/main/java/ru/bvn13/voidforum/models/Role.java b/src/main/java/ru/bvn13/voidforum/models/Role.java new file mode 100644 index 0000000..f775a96 --- /dev/null +++ b/src/main/java/ru/bvn13/voidforum/models/Role.java @@ -0,0 +1,34 @@ +package ru.bvn13.voidforum.models; + + +import lombok.Getter; +import lombok.Setter; + +import javax.persistence.*; +import java.util.Collection; + +@Entity +@Table(name = "roles") +@Getter +@Setter +public class Role extends BaseModel { + + private String name; + + @ManyToMany(fetch = FetchType.LAZY, mappedBy = "roles") + private Collection users; + + @ManyToMany(fetch = FetchType.LAZY) + @JoinTable(name = "roles_privileges", + joinColumns = {@JoinColumn(name = "role_id", referencedColumnName = "id")}, + inverseJoinColumns = {@JoinColumn(name = "privilege_id", referencedColumnName = "id")} + ) + private Collection privileges; + + public Role() {} + + public Role(String name) { + this.name = name; + } + +} diff --git a/src/main/java/ru/bvn13/voidforum/models/SeoPostData.java b/src/main/java/ru/bvn13/voidforum/models/SeoPostData.java new file mode 100644 index 0000000..a72ffe6 --- /dev/null +++ b/src/main/java/ru/bvn13/voidforum/models/SeoPostData.java @@ -0,0 +1,42 @@ +package ru.bvn13.voidforum.models; + +import lombok.Getter; +import lombok.Setter; +import ru.bvn13.voidforum.models.support.OgLocale; +import ru.bvn13.voidforum.models.support.OgType; + +import javax.persistence.*; + +@Entity +@Table(name = "seo_posts_data") +@Getter +@Setter +public class SeoPostData extends BaseModel { + + @OneToOne(fetch = FetchType.LAZY, mappedBy = "seoData", cascade = CascadeType.ALL) + private Post post; + + @Column + private String ogTitle = ""; + + @Column + @Enumerated(EnumType.STRING) + private OgType ogType = OgType.ARTICLE; + + @Column + private String ogImage = ""; + + @Column + private String ogVideo = ""; + + @Column + @Enumerated(EnumType.STRING) + private OgLocale ogLocale = OgLocale.en_EN; + + /*@Column + private String ogUrl; + + @Column + private String ogDescription;*/ + +} diff --git a/src/main/java/ru/bvn13/voidforum/models/SeoRobotAgent.java b/src/main/java/ru/bvn13/voidforum/models/SeoRobotAgent.java new file mode 100644 index 0000000..d2753f9 --- /dev/null +++ b/src/main/java/ru/bvn13/voidforum/models/SeoRobotAgent.java @@ -0,0 +1,30 @@ +package ru.bvn13.voidforum.models; + +import lombok.Getter; +import lombok.Setter; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.Table; + +@Entity +@Table(name = "seo_robots_agents") +@Getter +@Setter +public class SeoRobotAgent extends BaseModel { + + @Column(nullable = false) + private String userAgent; + + @Column(nullable = false, columnDefinition = "boolean default false") + private Boolean isRegexp; + + public SeoRobotAgent() { + + } + + public SeoRobotAgent(String userAgent) { + this.userAgent = userAgent; + } + +} diff --git a/src/main/java/ru/bvn13/voidforum/models/Setting.java b/src/main/java/ru/bvn13/voidforum/models/Setting.java new file mode 100644 index 0000000..f397a34 --- /dev/null +++ b/src/main/java/ru/bvn13/voidforum/models/Setting.java @@ -0,0 +1,30 @@ +package ru.bvn13.voidforum.models; + +import lombok.Getter; +import lombok.Setter; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.Lob; +import javax.persistence.Table; +import java.io.Serializable; + +/** + * A generic setting model + * + * bvn13 + */ +@Entity +@Table(name = "settings") +@Getter +@Setter +public class Setting extends BaseModel{ + + @Column(name = "_key", unique = true, nullable = false) + private String key; + + @Lob + @Column(name = "_value") + private Serializable value; + +} diff --git a/src/main/java/ru/bvn13/voidforum/models/StoredFile.java b/src/main/java/ru/bvn13/voidforum/models/StoredFile.java new file mode 100644 index 0000000..2ef1840 --- /dev/null +++ b/src/main/java/ru/bvn13/voidforum/models/StoredFile.java @@ -0,0 +1,64 @@ +package ru.bvn13.voidforum.models; + + +import lombok.Getter; +import lombok.Setter; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.ManyToOne; +import javax.persistence.Table; + +@Entity +@Table(name = "stored_files") +@Getter +@Setter +public class StoredFile extends BaseModel { + + @ManyToOne + private User user; + + @Column(nullable = false) + private String title; + + @Column(nullable = false) + private String name; + + @Column(nullable = false) + private String path; + + @Column(columnDefinition = "bigint default 0") + private Long size; + + public String getSizeFormatted() { + double bytes = this.getSize(); + double kilobytes = (bytes / 1024); + double megabytes = (kilobytes / 1024); + double gigabytes = (megabytes / 1024); + double terabytes = (gigabytes / 1024); + double petabytes = (terabytes / 1024); + double exabytes = (petabytes / 1024); + double zettabytes = (exabytes / 1024); + double yottabytes = (zettabytes / 1024); + if (Math.floor(yottabytes) > 0d) { + return String.format("%.3f Yb", yottabytes); + } else if (Math.floor(zettabytes) > 0d) { + return String.format("%.3f Zb", zettabytes); + } else if (Math.floor(exabytes) > 0d) { + return String.format("%.3f Eb", exabytes); + } else if (Math.floor(petabytes) > 0d) { + return String.format("%.3f Pb", petabytes); + } else if (Math.floor(terabytes) > 0d) { + return String.format("%.3f Tb", terabytes); + } else if (Math.floor(gigabytes) > 0d) { + return String.format("%.3f Gb", gigabytes); + } else if (Math.floor(megabytes) > 0d) { + return String.format("%.3f Mb", megabytes); + } else if (Math.floor(kilobytes) > 0d) { + return String.format("%.3f Kb", kilobytes); + } else { + return String.format("%d bytes", (int)bytes); + } + } + +} diff --git a/src/main/java/ru/bvn13/voidforum/models/Tag.java b/src/main/java/ru/bvn13/voidforum/models/Tag.java new file mode 100644 index 0000000..13a4fe5 --- /dev/null +++ b/src/main/java/ru/bvn13/voidforum/models/Tag.java @@ -0,0 +1,32 @@ +package ru.bvn13.voidforum.models; + +import lombok.Getter; +import lombok.Setter; + +import javax.persistence.*; +import java.util.ArrayList; +import java.util.List; + +/** + * bvn13 . + */ +@Entity +@Table(name = "tags") +@Getter +@Setter +public class Tag extends BaseModel { + + @Column(nullable = false, unique = true) + private String name; + + @ManyToMany(fetch = FetchType.LAZY, mappedBy = "tags") + private List posts = new ArrayList<>(); + + public Tag(){ + + } + + public Tag(String name){ + this.setName(name); + } +} diff --git a/src/main/java/ru/bvn13/voidforum/models/User.java b/src/main/java/ru/bvn13/voidforum/models/User.java new file mode 100644 index 0000000..713f29b --- /dev/null +++ b/src/main/java/ru/bvn13/voidforum/models/User.java @@ -0,0 +1,70 @@ +package ru.bvn13.voidforum.models; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import lombok.Getter; +import lombok.Setter; +import ru.bvn13.voidforum.services.RoleService; +import ru.bvn13.voidforum.services.UserService; + +import javax.persistence.*; +import java.util.ArrayList; +import java.util.Collection; +import java.util.concurrent.atomic.AtomicReference; + +/** + * bvn13 + */ +@Entity +@Table(name = "users") +@Getter +@Setter +public class User extends BaseModel { + + @Column(unique = true) + private String email; + + @Column(unique = true) + private String nickname; + + @JsonIgnore + private String password; + + private Boolean disabled; + + @ManyToMany(fetch = FetchType.LAZY) + @JoinTable(name = "users_roles", + joinColumns = {@JoinColumn(name = "user_id", referencedColumnName = "id")}, + inverseJoinColumns = {@JoinColumn(name = "role_id", referencedColumnName = "id")} + ) + private Collection roles; + + @OneToMany(fetch = FetchType.LAZY, mappedBy = "user", cascade = CascadeType.REMOVE) + private Collection posts = new ArrayList<>(); + + @OneToMany(fetch = FetchType.LAZY, mappedBy = "user", cascade = CascadeType.REMOVE) + private Collection storedFiles = new ArrayList<>(); + + @OneToMany(fetch = FetchType.LAZY, mappedBy = "user", cascade = CascadeType.REMOVE) + private Collection comments = new ArrayList<>(); + + public User() { + + } + + /* + public Boolean isAdmin() { + return UserService.hasRole(this, RoleService.ROLE_ADMIN) || UserService.hasRole(this, RoleService.ROLE_OWNER); + } + + public Boolean isOwner() { + return UserService.hasRole(this, RoleService.ROLE_OWNER); + } + */ + + public User(String email, String nickname, String password, String role) { + this.email = email; + this.nickname = nickname; + this.password = password; + this.roles.add(new Role(role)); + } +} diff --git a/src/main/java/ru/bvn13/voidforum/models/Visit.java b/src/main/java/ru/bvn13/voidforum/models/Visit.java new file mode 100644 index 0000000..aa04d1e --- /dev/null +++ b/src/main/java/ru/bvn13/voidforum/models/Visit.java @@ -0,0 +1,32 @@ +package ru.bvn13.voidforum.models; + +import lombok.Getter; +import lombok.Setter; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.ManyToOne; +import javax.persistence.Table; + +@Entity +@Table(name = "visits") +@Getter +@Setter +public class Visit extends BaseModel { + + @ManyToOne + private User user; + + @Column(nullable = false) + private String clientIp; + + @ManyToOne + private Post post; + + @Column(nullable = false, columnDefinition = "boolean default false") + private Boolean isAdmin; + + @Column + private String userAgent; + +} diff --git a/src/main/java/ru/bvn13/voidforum/models/support/CommentFormat.java b/src/main/java/ru/bvn13/voidforum/models/support/CommentFormat.java new file mode 100644 index 0000000..b9e178c --- /dev/null +++ b/src/main/java/ru/bvn13/voidforum/models/support/CommentFormat.java @@ -0,0 +1,27 @@ +package ru.bvn13.voidforum.models.support; + +public enum CommentFormat { + + HTML("Html"), + MARKDOWN("Markdown"); + + private String name; + + CommentFormat(String name){ + this.name = name; + } + + public String getName(){ + return name; + } + + public String getId() { + return name(); + } + + @Override + public String toString() { + return getName(); + } + +} diff --git a/src/main/java/ru/bvn13/voidforum/models/support/HttpContentTypeSerializer.java b/src/main/java/ru/bvn13/voidforum/models/support/HttpContentTypeSerializer.java new file mode 100644 index 0000000..6a9d6e5 --- /dev/null +++ b/src/main/java/ru/bvn13/voidforum/models/support/HttpContentTypeSerializer.java @@ -0,0 +1,40 @@ +package ru.bvn13.voidforum.models.support; + +import java.util.Hashtable; + +public class HttpContentTypeSerializer { + + private static final Hashtable variants = new Hashtable(); + + private static final String defaultVariant = "application/octet-stream"; + + static { + variants.put("aac", "audio/aac"); + variants.put("abw", "application/x-abiword"); + variants.put("", ""); + variants.put("", ""); + variants.put("", ""); + variants.put("", ""); + variants.put("", ""); + variants.put("", ""); + } + + public static String getContentType(String fileName) { + + if (fileName.isEmpty()) { + return defaultVariant; + } + + String fileArray[]=fileName.split("\\."); + + String extension = fileArray[fileArray.length-1]; + + if (variants.containsKey(extension)) { + return variants.get(extension); + } + + return defaultVariant; + } + + +} diff --git a/src/main/java/ru/bvn13/voidforum/models/support/OgLocale.java b/src/main/java/ru/bvn13/voidforum/models/support/OgLocale.java new file mode 100644 index 0000000..3a4af3b --- /dev/null +++ b/src/main/java/ru/bvn13/voidforum/models/support/OgLocale.java @@ -0,0 +1,31 @@ +package ru.bvn13.voidforum.models.support; + +public enum OgLocale { + + en_EN("en_EN"), + ru_RU("ru_RU"); + + private String name; + + OgLocale(String name){ + this.name = name; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getId(){ + return name(); + } + + @Override + public String toString() { + return getName(); + } + +} diff --git a/src/main/java/ru/bvn13/voidforum/models/support/OgType.java b/src/main/java/ru/bvn13/voidforum/models/support/OgType.java new file mode 100644 index 0000000..64b9046 --- /dev/null +++ b/src/main/java/ru/bvn13/voidforum/models/support/OgType.java @@ -0,0 +1,27 @@ +package ru.bvn13.voidforum.models.support; + +public enum OgType { + + WEBSITE("website"), + ARTICLE("article"); + + private String name; + + OgType(String name){ + this.name = name; + } + + public String getName(){ + return name; + } + + public String getId() { + return name(); + } + + @Override + public String toString() { + return getName(); + } + +} diff --git a/src/main/java/ru/bvn13/voidforum/models/support/PostFormat.java b/src/main/java/ru/bvn13/voidforum/models/support/PostFormat.java new file mode 100644 index 0000000..b81d0db --- /dev/null +++ b/src/main/java/ru/bvn13/voidforum/models/support/PostFormat.java @@ -0,0 +1,28 @@ +package ru.bvn13.voidforum.models.support; + +/** + * bvn13 + */ +public enum PostFormat { + HTML("Html"), + MARKDOWN("Markdown"); + + private String name; + + PostFormat(String name){ + this.name = name; + } + + public String getName(){ + return name; + } + + public String getId() { + return name(); + } + + @Override + public String toString() { + return getName(); + } +} \ No newline at end of file diff --git a/src/main/java/ru/bvn13/voidforum/models/support/PostStatus.java b/src/main/java/ru/bvn13/voidforum/models/support/PostStatus.java new file mode 100644 index 0000000..438fa58 --- /dev/null +++ b/src/main/java/ru/bvn13/voidforum/models/support/PostStatus.java @@ -0,0 +1,32 @@ +package ru.bvn13.voidforum.models.support; + +/** + * bvn13 + */ +public enum PostStatus { + DRAFT("Draft"), + PUBLISHED("Published"); + + private String name; + + PostStatus(String name){ + this.name = name; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getId(){ + return name(); + } + + @Override + public String toString() { + return getName(); + } +} diff --git a/src/main/java/ru/bvn13/voidforum/models/support/PostType.java b/src/main/java/ru/bvn13/voidforum/models/support/PostType.java new file mode 100644 index 0000000..f20aefc --- /dev/null +++ b/src/main/java/ru/bvn13/voidforum/models/support/PostType.java @@ -0,0 +1,32 @@ +package ru.bvn13.voidforum.models.support; + +/** + * bvn13 + */ +public enum PostType { + PAGE("Page"), + POST("Post"); + + private String name; + + PostType(String name){ + this.name = name; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getId(){ + return name(); + } + + @Override + public String toString() { + return getName(); + } +} diff --git a/src/main/java/ru/bvn13/voidforum/models/support/WebError.java b/src/main/java/ru/bvn13/voidforum/models/support/WebError.java new file mode 100644 index 0000000..389d8f8 --- /dev/null +++ b/src/main/java/ru/bvn13/voidforum/models/support/WebError.java @@ -0,0 +1,21 @@ +package ru.bvn13.voidforum.models.support; + +import lombok.Getter; +import lombok.Setter; + +import java.io.Serializable; + +@Getter +@Setter +public class WebError implements Serializable { + + private String field; + + private String errorMessage; + + public WebError(String field, String errorMessage) { + this.field = field; + this.errorMessage = errorMessage; + } + +} diff --git a/src/main/java/ru/bvn13/voidforum/repositories/CommentRepository.java b/src/main/java/ru/bvn13/voidforum/repositories/CommentRepository.java new file mode 100644 index 0000000..095214b --- /dev/null +++ b/src/main/java/ru/bvn13/voidforum/repositories/CommentRepository.java @@ -0,0 +1,18 @@ +package ru.bvn13.voidforum.repositories; + +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; +import ru.bvn13.voidforum.models.Comment; +import ru.bvn13.voidforum.models.Post; + +import java.util.List; + +@Repository +public interface CommentRepository extends JpaRepository { + List findAllByPostOrderById(Post post); + List findAllByPostAndParentCommentOrderById(Post post, Comment parentComment); + + List findAllByPostAndDeletedMarkOrderById(Post post, Boolean deletedMark); + List findAllByPostAndParentCommentAndDeletedMarkOrderById(Post post, Comment parentComment, Boolean deletedMark); + +} diff --git a/src/main/java/ru/bvn13/voidforum/repositories/LikeRepository.java b/src/main/java/ru/bvn13/voidforum/repositories/LikeRepository.java new file mode 100644 index 0000000..572c963 --- /dev/null +++ b/src/main/java/ru/bvn13/voidforum/repositories/LikeRepository.java @@ -0,0 +1,22 @@ +package ru.bvn13.voidforum.repositories; + +import ru.bvn13.voidforum.models.Like; +import ru.bvn13.voidforum.models.Post; +import ru.bvn13.voidforum.models.User; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; +import org.springframework.stereotype.Repository; + +@Repository +public interface LikeRepository extends JpaRepository { + + @Query("SELECT SUM(l.sympathy) FROM Like AS l WHERE l.user = :user AND l.post = :post GROUP BY l.user, l.post") + Integer getTotalLikesByUserAndPost(@Param("user") User user, @Param("post") Post post); + + @Query("SELECT SUM(l.sympathy) FROM Like AS l WHERE l.post = :post GROUP BY l.post") + Integer getTotalLikesByPost(@Param("post") Post post); + + @Query("SELECT SUM(l.sympathy) FROM Like AS l WHERE l.clientIp = :clientIp AND l.post = :post GROUP BY l.clientIp, l.post") + Integer getTotalLikesByClientIpAndPost(@Param("clientIp") String clientIp, @Param("post") Post post); +} diff --git a/src/main/java/ru/bvn13/voidforum/repositories/PostRepository.java b/src/main/java/ru/bvn13/voidforum/repositories/PostRepository.java new file mode 100644 index 0000000..85fde3d --- /dev/null +++ b/src/main/java/ru/bvn13/voidforum/repositories/PostRepository.java @@ -0,0 +1,49 @@ +package ru.bvn13.voidforum.repositories; + +import ru.bvn13.voidforum.models.Post; +import ru.bvn13.voidforum.models.User; +import ru.bvn13.voidforum.models.support.PostStatus; +import ru.bvn13.voidforum.models.support.PostType; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; +import org.springframework.stereotype.Repository; +import org.springframework.transaction.annotation.Transactional; + +import java.util.List; + +/** + * bvn13 + */ +@Repository +@Transactional +public interface PostRepository extends JpaRepository { + Post findByPermalinkAndPostStatus(String permalink, PostStatus postStatus); + + Post findByIdAndPostStatus(Long postId, PostStatus postStatus); + + Page findAllByPostType(PostType postType, Pageable pageRequest); + + Page findAllByPostTypeAndPostStatus(PostType postType, PostStatus postStatus, Pageable pageRequest); + + Page findAllByPostTypeAndPostStatusAndDeletedMarkAndCensored(PostType postType, PostStatus postStatus, Boolean deletedMark, Boolean censored, Pageable pageRequest); + + List findAllByPostTypeAndPostStatus(PostType postType, PostStatus postStatus); + + @Query("SELECT p FROM Post p INNER JOIN p.tags t WHERE t.name = :tag") + Page findByTag(@Param("tag") String tag, Pageable pageable); + + @Query("SELECT t.name, count(p) as tag_count from Post p " + + "INNER JOIN p.tags t " + + "WHERE p.postStatus = :status " + + "GROUP BY t.id " + + "ORDER BY tag_count DESC") + List countPostsByTags(@Param("status") PostStatus status); + + Page findAllByPostTypeAndPostStatusAndDeletedMark(PostType postType, PostStatus postStatus, Boolean deletedMark, Pageable pageRequest); + + Page findAllByUser(User user, Pageable pageRequest); +} + diff --git a/src/main/java/ru/bvn13/voidforum/repositories/PrivilegeRepository.java b/src/main/java/ru/bvn13/voidforum/repositories/PrivilegeRepository.java new file mode 100644 index 0000000..b1be882 --- /dev/null +++ b/src/main/java/ru/bvn13/voidforum/repositories/PrivilegeRepository.java @@ -0,0 +1,22 @@ +package ru.bvn13.voidforum.repositories; + +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; +import ru.bvn13.voidforum.models.Privilege; +import ru.bvn13.voidforum.models.Role; + +import java.util.Collection; +import java.util.List; + +public interface PrivilegeRepository extends JpaRepository { + Privilege findByName(String name); + @Query("SELECT p FROM Privilege AS p " + + "INNER JOIN p.roles AS r " + + "WHERE r = :role") + List findAllByRole(@Param("role") Role role); + /*@Query("SELECT p FROM Privilege AS p " + + "INNER JOIN p.roles AS r " + + "WHERE r IN :roles") + List findAllByRolesList(@Param("roles") Collection roles);*/ +} diff --git a/src/main/java/ru/bvn13/voidforum/repositories/RoleRepository.java b/src/main/java/ru/bvn13/voidforum/repositories/RoleRepository.java new file mode 100644 index 0000000..b746d12 --- /dev/null +++ b/src/main/java/ru/bvn13/voidforum/repositories/RoleRepository.java @@ -0,0 +1,17 @@ +package ru.bvn13.voidforum.repositories; + +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; +import ru.bvn13.voidforum.models.Role; +import ru.bvn13.voidforum.models.User; + +import java.util.List; + +public interface RoleRepository extends JpaRepository { + Role findByName(String role_name); + @Query("SELECT r FROM Role AS r " + + "INNER JOIN r.users AS u " + + "WHERE u = :user") + List findAllByUser(@Param("user") User user); +} diff --git a/src/main/java/ru/bvn13/voidforum/repositories/SeoPostDataRepository.java b/src/main/java/ru/bvn13/voidforum/repositories/SeoPostDataRepository.java new file mode 100644 index 0000000..fddb39c --- /dev/null +++ b/src/main/java/ru/bvn13/voidforum/repositories/SeoPostDataRepository.java @@ -0,0 +1,9 @@ +package ru.bvn13.voidforum.repositories; + +import ru.bvn13.voidforum.models.SeoPostData; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +@Repository +public interface SeoPostDataRepository extends JpaRepository { +} diff --git a/src/main/java/ru/bvn13/voidforum/repositories/SeoRobotAgentRepository.java b/src/main/java/ru/bvn13/voidforum/repositories/SeoRobotAgentRepository.java new file mode 100644 index 0000000..f82cb8b --- /dev/null +++ b/src/main/java/ru/bvn13/voidforum/repositories/SeoRobotAgentRepository.java @@ -0,0 +1,8 @@ +package ru.bvn13.voidforum.repositories; + +import ru.bvn13.voidforum.models.SeoRobotAgent; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface SeoRobotAgentRepository extends JpaRepository { + +} diff --git a/src/main/java/ru/bvn13/voidforum/repositories/SettingRepository.java b/src/main/java/ru/bvn13/voidforum/repositories/SettingRepository.java new file mode 100644 index 0000000..f083621 --- /dev/null +++ b/src/main/java/ru/bvn13/voidforum/repositories/SettingRepository.java @@ -0,0 +1,15 @@ +package ru.bvn13.voidforum.repositories; + +import ru.bvn13.voidforum.models.Setting; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; +import org.springframework.transaction.annotation.Transactional; + +/** + * bvn13 + */ +@Repository +@Transactional +public interface SettingRepository extends JpaRepository { + Setting findByKey(String key); +} diff --git a/src/main/java/ru/bvn13/voidforum/repositories/StoredFileRepository.java b/src/main/java/ru/bvn13/voidforum/repositories/StoredFileRepository.java new file mode 100644 index 0000000..195740c --- /dev/null +++ b/src/main/java/ru/bvn13/voidforum/repositories/StoredFileRepository.java @@ -0,0 +1,15 @@ +package ru.bvn13.voidforum.repositories; + +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.stereotype.Repository; +import ru.bvn13.voidforum.models.StoredFile; +import org.springframework.data.jpa.repository.JpaRepository; +import ru.bvn13.voidforum.models.User; + +@Repository +public interface StoredFileRepository extends JpaRepository { + StoredFile findById(Long id); + StoredFile findByName(String name); + Page findAllByUserOrderByIdDesc(User user, Pageable pageRequest); +} diff --git a/src/main/java/ru/bvn13/voidforum/repositories/TagRepository.java b/src/main/java/ru/bvn13/voidforum/repositories/TagRepository.java new file mode 100644 index 0000000..0a7edba --- /dev/null +++ b/src/main/java/ru/bvn13/voidforum/repositories/TagRepository.java @@ -0,0 +1,11 @@ +package ru.bvn13.voidforum.repositories; + +import org.springframework.data.jpa.repository.JpaRepository; +import ru.bvn13.voidforum.models.Tag; + +/** + * bvn13 . + */ +public interface TagRepository extends JpaRepository { + Tag findByName(String name); +} diff --git a/src/main/java/ru/bvn13/voidforum/repositories/UserRepository.java b/src/main/java/ru/bvn13/voidforum/repositories/UserRepository.java new file mode 100644 index 0000000..cf52a56 --- /dev/null +++ b/src/main/java/ru/bvn13/voidforum/repositories/UserRepository.java @@ -0,0 +1,29 @@ +package ru.bvn13.voidforum.repositories; + +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; +import ru.bvn13.voidforum.models.Role; +import ru.bvn13.voidforum.models.User; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; +import org.springframework.transaction.annotation.Transactional; + +import java.util.List; + +/** + * bvn13 + */ +@Repository +@Transactional +public interface UserRepository extends JpaRepository { + User findByEmail(String email); + User findByNickname(String nickname); + @Query("SELECT u FROM User AS u " + + "INNER JOIN u.roles AS r " + + "WHERE r.name = :roleName") + List findAllByOneRoleByNameOrderById(@Param("roleName") String rname); + @Query("SELECT u FROM User AS u " + + "INNER JOIN u.roles AS r " + + "WHERE r = :role") + List findAllByOneRoleOrderById(@Param("role") Role role); +} diff --git a/src/main/java/ru/bvn13/voidforum/repositories/VisitRepository.java b/src/main/java/ru/bvn13/voidforum/repositories/VisitRepository.java new file mode 100644 index 0000000..b55aa14 --- /dev/null +++ b/src/main/java/ru/bvn13/voidforum/repositories/VisitRepository.java @@ -0,0 +1,29 @@ +package ru.bvn13.voidforum.repositories; + +import ru.bvn13.voidforum.models.Post; +import ru.bvn13.voidforum.models.Visit; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; + +import java.util.List; + +public interface VisitRepository extends JpaRepository { + + @Query( "SELECT COUNT(DISTINCT v.clientIp) " + + "FROM Visit AS v " + + //"LEFT JOIN v.robotsAgents AS ra " + + //"ON v.userAgent LIKE concat('%', ra.userAgent, '%') "+ + "WHERE v.post = :post AND v.isAdmin = FALSE " //+ + //"AND ra.id IS NULL " + ) + Long getUniquePostVisitsCount(@Param("post") Post post); + + @Query( "SELECT v.clientIp, NULLIF(v.userAgent, '') " + + "FROM Visit AS v " + + "WHERE v.post = :post AND v.isAdmin = FALSE " + + "GROUP BY v.clientIp, NULLIF(v.userAgent, '') " + ) + List getVisitsByPostAndIsAdminIsFalse(@Param("post") Post post); + +} diff --git a/src/main/java/ru/bvn13/voidforum/services/AppSetting.java b/src/main/java/ru/bvn13/voidforum/services/AppSetting.java new file mode 100644 index 0000000..09f980b --- /dev/null +++ b/src/main/java/ru/bvn13/voidforum/services/AppSetting.java @@ -0,0 +1,93 @@ +package ru.bvn13.voidforum.services; + +import com.domingosuarez.boot.autoconfigure.jade4j.JadeHelper; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.ArrayList; +import java.util.List; + +/** + * bvn13 + */ +@JadeHelper("App") +@Service +public class AppSetting { + + private SettingService settingService; + + private String siteName = "void Forum();"; + private String siteSlogan = "An interesting place to discover"; + private Integer pageSize = 5; + private String storagePath = "/tmp"; + private String mainUri = "http://localhost/"; + + public static final String SITE_NAME = "site_name"; + public static final String SITE_SLOGAN = "site_slogan"; + public static final String PAGE_SIZE = "page_size"; + public static final String STORAGE_PATH = "storage_path"; + public static final String MAIN_URI = "main_uri"; + + @Autowired + public AppSetting(SettingService settingService){ + this.settingService = settingService; + } + + public String getSiteName(){ + return (String) settingService.get(SITE_NAME, siteName); + } + + public void setSiteName(String siteName) { + this.siteName = siteName; + settingService.put(SITE_NAME, siteName); + } + + public Integer getPageSize() { + return (Integer) settingService.get(PAGE_SIZE, pageSize); + } + + public void setPageSize(Integer pageSize) { + this.pageSize = pageSize; + settingService.put(PAGE_SIZE, pageSize); + } + + public String getSiteSlogan() { + return (String) settingService.get(SITE_SLOGAN, siteSlogan); + } + + public void setSiteSlogan(String siteSlogan) { + this.siteSlogan = siteSlogan; + settingService.put(SITE_SLOGAN, siteSlogan); + } + + public String getStoragePath() { + return (String) settingService.get(STORAGE_PATH, storagePath); + } + + public void setStoragePath(String storagePath) { + this.storagePath = storagePath; + settingService.put(STORAGE_PATH, storagePath); + } + + public String getMainUri() { + return (String) settingService.get(MAIN_URI, mainUri); + } + + public void setMainUri(String mainUri) { + this.mainUri = mainUri; + settingService.put(MAIN_URI, mainUri); + } + + public List getOgLocales() { + ArrayList ogLocales = new ArrayList<>(); + ogLocales.add("en_EN"); + ogLocales.add("ru_RU"); + return ogLocales; + } + + public List getOgTypes() { + ArrayList ogTypes = new ArrayList<>(); + ogTypes.add("article"); + return ogTypes; + } +} diff --git a/src/main/java/ru/bvn13/voidforum/services/CacheSettingService.java b/src/main/java/ru/bvn13/voidforum/services/CacheSettingService.java new file mode 100644 index 0000000..6a76f7a --- /dev/null +++ b/src/main/java/ru/bvn13/voidforum/services/CacheSettingService.java @@ -0,0 +1,71 @@ +package ru.bvn13.voidforum.services; + +import ru.bvn13.voidforum.models.Setting; +import ru.bvn13.voidforum.repositories.SettingRepository; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.cache.annotation.CacheEvict; +import org.springframework.cache.annotation.Cacheable; +import org.springframework.stereotype.Service; + +import java.io.Serializable; + +/** + * bvn13 + */ +@Service +public class CacheSettingService implements SettingService { + + private SettingRepository settingRepository; + + private static final String CACHE_NAME = "cache.settings"; + + @Autowired + public CacheSettingService(SettingRepository settingRepository) { + this.settingRepository = settingRepository; + } + + private static final Logger logger = LoggerFactory.getLogger(SettingService.class); + + @Override + public Serializable get(String key) { + Setting setting = settingRepository.findByKey(key); + Serializable value = null; + try { + value = setting == null ? null : setting.getValue(); + } catch (Exception ex) { + logger.info("Cannot deserialize setting value with key = " + key); + } + + logger.info("Get setting " + key + " from database. Value = " + value); + + return value; + } + + @Override + @Cacheable(value = CACHE_NAME, key = "#key") + public Serializable get(String key, Serializable defaultValue) { + Serializable value = get(key); + return value == null ? defaultValue : value; + } + + @Override + @CacheEvict(value = CACHE_NAME, key = "#key") + public void put(String key, Serializable value) { + logger.info("Update setting " + key + " to database. Value = " + value); + + Setting setting = settingRepository.findByKey(key); + if (setting == null) { + setting = new Setting(); + setting.setKey(key); + } + try { + setting.setValue(value); + settingRepository.save(setting); + } catch (Exception ex) { + + logger.info("Cannot save setting value with type: " + value.getClass() + ". key = " + key); + } + } +} diff --git a/src/main/java/ru/bvn13/voidforum/services/CommentService.java b/src/main/java/ru/bvn13/voidforum/services/CommentService.java new file mode 100644 index 0000000..5687d6d --- /dev/null +++ b/src/main/java/ru/bvn13/voidforum/services/CommentService.java @@ -0,0 +1,88 @@ +package ru.bvn13.voidforum.services; + +import com.domingosuarez.boot.autoconfigure.jade4j.JadeHelper; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import ru.bvn13.voidforum.models.Comment; +import ru.bvn13.voidforum.models.Post; +import ru.bvn13.voidforum.models.User; +import ru.bvn13.voidforum.models.support.CommentFormat; +import ru.bvn13.voidforum.repositories.CommentRepository; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.List; +import java.util.concurrent.atomic.AtomicReference; + +/** + * Created by bvn13 on 09.12.2017. + */ +@JadeHelper("commentService") +//@Service +public class CommentService { + + @Autowired + private UserService userService; + + @Autowired + private CommentRepository commentRepository; + + + private static Comparator commentComparator = new Comparator() { + @Override + public int compare(Comment o1, Comment o2) { + return o1.getId().compareTo(o2.getId()); + } + }; + + + public List getCommentsForPost(Post post) { + List availableComments = null; + //User user = userService.currentUser(); + //if (userService.hasPrivilege(user, PrivilegeService.PRIVILEGE_WRITE)) { + availableComments = commentRepository.findAllByPostOrderById(post); + //} else { + // availableComments = commentRepository.findAllByPostAndDeletedMarkOrderById(post, false); + //} + return availableComments; + } + + public List filterListByParentComment(List comments, Comment parent) { + List children = new ArrayList<>(); + comments.forEach(c -> { + if (c.getParentComment().getId().equals(parent.getId())) { + children.add(c); + } + }); + Collections.sort(children, CommentService.commentComparator); + return children; + } + + public Integer childrenCount(List comments, Comment parent) { + AtomicReference count = new AtomicReference<>(); + comments.forEach(c -> { + if (c.getParentComment().getId().equals(parent.getId())) { + Integer old = count.get(); + count.set(old+1); + } + }); + return count.get(); + } + + public List getAvailableCommentFormats() { + List formats = new ArrayList<>(); + User user = userService.currentUser(); + for (CommentFormat f : CommentFormat.values()) { + if (f.equals(CommentFormat.HTML)) { + if (userService.hasPrivilege(user, PrivilegeService.PRIVILEGE_WRITE_HTML)) { + formats.add(f); + } + } else { + formats.add(f); + } + } + return formats; + } + +} diff --git a/src/main/java/ru/bvn13/voidforum/services/FileStorageService.java b/src/main/java/ru/bvn13/voidforum/services/FileStorageService.java new file mode 100644 index 0000000..c092e29 --- /dev/null +++ b/src/main/java/ru/bvn13/voidforum/services/FileStorageService.java @@ -0,0 +1,116 @@ +package ru.bvn13.voidforum.services; + + +import ru.bvn13.voidforum.error.NotFoundException; +import ru.bvn13.voidforum.models.StoredFile; +import ru.bvn13.voidforum.models.User; +import ru.bvn13.voidforum.models.support.HttpContentTypeSerializer; +import ru.bvn13.voidforum.repositories.StoredFileRepository; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; + +@Service +public class FileStorageService { + + public static final Logger logger = LoggerFactory.getLogger(FileStorageService.class); + + private AppSetting appSetting; + + private StoredFileRepository repository; + + @Autowired + private UserService userService; + + @Autowired + public FileStorageService(StoredFileRepository repository, AppSetting appSetting) { + this.repository = repository; + this.appSetting = appSetting; + logger.debug("== UPLOAD PATH == > "+appSetting.getStoragePath()); + } + + public StoredFile getFileById(Long id) { + return repository.findById(id); + } + + public StoredFile getFileByName(String fileName) { + StoredFile file = null; + + file = repository.findByName(fileName); + if (file == null) { + if (fileName.matches("\\d+")) { + file = this.getFileById(Long.valueOf(fileName)); + } + } + + if (file == null) { + throw new NotFoundException("File " + fileName + " is not found"); + } + + return file; + } + + public void storeFile(User user, String filename, byte[] content) throws IOException { + File storage = new File(appSetting.getStoragePath()); + if (!storage.exists()) { + storage.mkdirs(); + } + String separator = ""; + if (!appSetting.getStoragePath().endsWith("/")) { + separator = "/"; + } + String userFolder = appSetting.getStoragePath() + separator + user.getId() + "/"; + File userStorage = new File(userFolder); + if (!userStorage.exists()) { + userStorage.mkdirs(); + } + + String fullname = userFolder + filename; + Path path = Paths.get(fullname); + Files.write(path, content); + + File file = new File(fullname); + + StoredFile storedFile = new StoredFile(); + storedFile.setPath(path.toAbsolutePath().toString()); + storedFile.setUser(this.userService.currentUser()); + storedFile.setTitle(filename); + storedFile.setName(filename); + storedFile.setSize(file.length()); + + this.repository.saveAndFlush(storedFile); + } + + public byte[] getFileContentById(Long fileId) throws IOException { + StoredFile storedFile = this.repository.findById(fileId); + Path path = Paths.get(storedFile.getPath()); + return Files.readAllBytes(path); + } + + public byte[] getFileContent(String fullname) throws IOException { + Path path = Paths.get(fullname); + return Files.readAllBytes(path); + } + + public void deleteFileById(Long fileId) throws IOException { + StoredFile storedFile = this.repository.findById(fileId); + Path path = Paths.get(storedFile.getPath()); + // first delete info, second delete file + // because file might be deleted already + this.repository.delete(storedFile); + Files.delete(path); + } + + public String getContentType(String fileName) { + return HttpContentTypeSerializer.getContentType(fileName); + } + + +} diff --git a/src/main/java/ru/bvn13/voidforum/services/LikeService.java b/src/main/java/ru/bvn13/voidforum/services/LikeService.java new file mode 100644 index 0000000..1476dd9 --- /dev/null +++ b/src/main/java/ru/bvn13/voidforum/services/LikeService.java @@ -0,0 +1,68 @@ +package ru.bvn13.voidforum.services; + +import ru.bvn13.voidforum.models.Like; +import ru.bvn13.voidforum.models.Post; +import ru.bvn13.voidforum.models.User; +import ru.bvn13.voidforum.repositories.LikeRepository; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +@Service +public class LikeService { + + @Autowired + private LikeRepository likeRepository; + + @Autowired + private UserService userService; + + + public Integer getTotalLikesByPost(Post post) { + return this.likeRepository.getTotalLikesByPost(post); + } + + public Integer getTotalLikesByUserAndPost(User user, Post post) { + return this.likeRepository.getTotalLikesByUserAndPost(user, post); + } + + public void likePost(Post post, String clientIp) { + User user = this.userService.currentUser(); + Integer currentSympathy = 0; + + if (user != null) { + currentSympathy = this.likeRepository.getTotalLikesByUserAndPost(user, post); + } else { + currentSympathy = this.likeRepository.getTotalLikesByClientIpAndPost(clientIp, post); + } + if (currentSympathy == null) currentSympathy = 0; + + Integer sympathyDelta = -currentSympathy + 1; + this.saveSympathy(post, user, clientIp, sympathyDelta); + } + + public void dislikePost(Post post, String clientIp) { + User user = this.userService.currentUser(); + Integer currentSympathy = 0; + + if (user != null) { + currentSympathy = this.likeRepository.getTotalLikesByUserAndPost(user, post); + } else { + currentSympathy = this.likeRepository.getTotalLikesByClientIpAndPost(clientIp, post); + } + if (currentSympathy == null) currentSympathy = 0; + + Integer sympathyDelta = -currentSympathy - 1; + this.saveSympathy(post, user, clientIp, sympathyDelta); + } + + private void saveSympathy(Post post, User user, String clientIp, Integer sympathy) { + Like like = new Like(); + like.setClientIp(clientIp); + like.setPost(post); + like.setUser(user); + like.setIsAdmin(user != null ? userService.hasPrivilege(user, PrivilegeService.PRIVILEGE_ADMIN) : false); + like.setSympathy(sympathy); + this.likeRepository.save(like); + } + +} diff --git a/src/main/java/ru/bvn13/voidforum/services/PostService.java b/src/main/java/ru/bvn13/voidforum/services/PostService.java new file mode 100644 index 0000000..927a025 --- /dev/null +++ b/src/main/java/ru/bvn13/voidforum/services/PostService.java @@ -0,0 +1,359 @@ +package ru.bvn13.voidforum.services; + +import ru.bvn13.voidforum.Constants; +import ru.bvn13.voidforum.error.NotFoundException; +import ru.bvn13.voidforum.models.Post; +import ru.bvn13.voidforum.models.SeoPostData; +import ru.bvn13.voidforum.models.Tag; +import ru.bvn13.voidforum.models.support.PostFormat; +import ru.bvn13.voidforum.models.support.PostStatus; +import ru.bvn13.voidforum.models.support.PostType; +import ru.bvn13.voidforum.repositories.PostRepository; +import ru.bvn13.voidforum.repositories.SeoPostDataRepository; +import ru.bvn13.voidforum.support.web.MarkdownService; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.cache.annotation.CacheEvict; +import org.springframework.cache.annotation.Cacheable; +import org.springframework.cache.annotation.Caching; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Sort; +import org.springframework.stereotype.Service; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +/** + * bvn13 . + */ +@Service +public class PostService { + @Autowired + private PostRepository postRepository; + + @Autowired + private TagService tagService; + + @Autowired + private UserService userService; + + @Autowired + private MarkdownService markdownService; + + @Autowired + private LikeService likeService; + + @Autowired + private VisitService visitService; + + @Autowired + private SeoPostDataRepository seoPostDataRepository; + + + public static final String CACHE_NAME = "cache.post"; + public static final String CACHE_NAME_ARCHIVE = CACHE_NAME + ".archive"; + public static final String CACHE_NAME_PAGE = CACHE_NAME + ".page"; + public static final String CACHE_NAME_TAGS = CACHE_NAME + ".tag"; + public static final String CACHE_NAME_SEO_KEYWORDS = CACHE_NAME + ".seoKeyword"; + public static final String CACHE_NAME_COUNTS = CACHE_NAME + ".counts_tags"; + + private static final Logger logger = LoggerFactory.getLogger(PostService.class); + + @Cacheable(CACHE_NAME) + public Post getPost(Long postId) { + logger.debug("Get post " + postId); + + Post post = postRepository.findOne(postId); + + if (post == null) { + throw new NotFoundException("Post with id " + postId + " is not found."); + } + + return post; + } + + @Cacheable(CACHE_NAME) + public Post getPublishedPost(Long postId) { + logger.debug("Get published post " + postId); + + Post post = this.postRepository.findByIdAndPostStatus(postId, PostStatus.PUBLISHED); + + if (post == null) { + throw new NotFoundException("Post with id " + postId + " is not found."); + } + + return post; + } + + @Cacheable(CACHE_NAME) + public Post getPublishedPostByPermalink(String permalink) { + logger.debug("Get post with permalink " + permalink); + + Post post = postRepository.findByPermalinkAndPostStatus(permalink, PostStatus.PUBLISHED); + + if (post == null) { + throw new NotFoundException("Post with permalink '" + permalink + "' is not found."); + } + + return post; + } + + @Caching(evict = { + @CacheEvict(value = CACHE_NAME_ARCHIVE, allEntries = true), + @CacheEvict(value = CACHE_NAME_PAGE, allEntries = true), + @CacheEvict(value = CACHE_NAME_COUNTS, allEntries = true) + }) + public Post createPost(Post post) { + return this.savePost(post); + } + + @Caching(evict = { + @CacheEvict(value = CACHE_NAME, key = "#post.id"), + @CacheEvict(value = CACHE_NAME, key = "#post.permalink", condition = "#post.permalink != null"), + @CacheEvict(value = CACHE_NAME_TAGS, key = "#post.id.toString().concat('-tags')"), + @CacheEvict(value = CACHE_NAME_SEO_KEYWORDS, key = "#post.id.toString().concat('-seoKeywords')"), + @CacheEvict(value = CACHE_NAME_ARCHIVE, allEntries = true), + @CacheEvict(value = CACHE_NAME_PAGE, allEntries = true), + @CacheEvict(value = CACHE_NAME_COUNTS, allEntries = true) + }) + public Post updatePost(Post post) { + return this.savePost(post); + } + + + private Post savePost(Post post) { + if (post.getPostFormat() == PostFormat.MARKDOWN) { + post.setRenderedContent(String.format("
%s
", markdownService.renderToHtml(post.getContent()))); + } else { + post.setRenderedContent(String.format("
%s
", post.getContent())); + } + this.saveSeoData(post); + return postRepository.save(post); + } + + @Caching(evict = { + @CacheEvict(value = CACHE_NAME, key = "#post.id"), + @CacheEvict(value = CACHE_NAME, key = "#post.permalink", condition = "#post.permalink != null"), + @CacheEvict(value = CACHE_NAME_TAGS, key = "#post.id.toString().concat('-tags')"), + @CacheEvict(value = CACHE_NAME_SEO_KEYWORDS, key = "#post.id.toString().concat('-seoKeywords')"), + @CacheEvict(value = CACHE_NAME_ARCHIVE, allEntries = true), + @CacheEvict(value = CACHE_NAME_PAGE, allEntries = true), + @CacheEvict(value = CACHE_NAME_COUNTS, allEntries = true) + }) + public void deletePost(Post post) { + post.setDeletedMark(!post.getDeletedMark()); + postRepository.save(post); + } + + public void censorePost(Post post) { + post.setCensored(!post.getCensored()); + postRepository.save(post); + } + + @Cacheable(value = CACHE_NAME_ARCHIVE, key = "#root.method.name") + public List getArchivePosts() { + logger.debug("Get all archive posts from database."); + + Iterable posts = postRepository.findAllByPostTypeAndPostStatus( + PostType.POST, + PostStatus.PUBLISHED, + new PageRequest(0, Integer.MAX_VALUE, Sort.Direction.DESC, "createdAt")); + + List cachedPosts = new ArrayList<>(); + posts.forEach(post -> cachedPosts.add(extractPostMeta(post))); + + return cachedPosts; + } + + @Cacheable(value = CACHE_NAME_TAGS, key = "#post.id.toString().concat('-tags')") + public List getPostTags(Post post) { + logger.debug("Get tags of post " + post.getId()); + + List tags = new ArrayList<>(); + + // Load the post first. If not, when the post is cached before while the tags not, + // then the LAZY loading of post tags will cause an initialization error because + // of not hibernate connection session + postRepository.findOne(post.getId()).getTags().forEach(tags::add); + return tags; + } + + @Cacheable(value = CACHE_NAME_SEO_KEYWORDS, key = "#post.id.toString().concat('-seoKeywords')") + public String getSeoKeywordsAsString(Post post) { + logger.debug("Get seoKeywordsAsString of post " + post.getId()); + + return post.getSeoKeywords(); + } + + private Post extractPostMeta(Post post) { + Post archivePost = new Post(); + archivePost.setId(post.getId()); + archivePost.setTitle(post.getTitle()); + archivePost.setPermalink(post.getPermalink()); + archivePost.setCreatedAt(post.getCreatedAt()); + + archivePost.setSympathyCount(this.likeService.getTotalLikesByPost(post)); + archivePost.setVisitsCount(this.visitService.getUniqueVisitsCount(post)); + + return archivePost; + } + + @Cacheable(value = CACHE_NAME_PAGE, key = "T(java.lang.String).valueOf(#page).concat('-').concat(#pageSize)") + public Page getAllPublishedPostsByPage(int page, int pageSize) { + logger.debug("Get posts by page " + page); + + Page posts = postRepository.findAllByPostTypeAndPostStatus( + PostType.POST, + PostStatus.PUBLISHED, + new PageRequest(page, pageSize, Sort.Direction.DESC, "createdAt")); + + posts.forEach(p -> { + p.setSympathyCount(this.likeService.getTotalLikesByPost(p)); + p.setVisitsCount(this.visitService.getUniqueVisitsCount(p)); + }); + + return posts; + } + + @Cacheable(value = CACHE_NAME_PAGE, key = "T(java.lang.String).valueOf(#page).concat('-').concat(#pageSize)") + public Page getAllPublishedNotDeletedPostsByPage(int page, int pageSize) { + logger.debug("Get not deleted posts by page " + page); + + Page posts = postRepository.findAllByPostTypeAndPostStatusAndDeletedMark( + PostType.POST, + PostStatus.PUBLISHED, + false, + new PageRequest(page, pageSize, Sort.Direction.DESC, "createdAt")); + + posts.forEach(p -> { + p.setSympathyCount(this.likeService.getTotalLikesByPost(p)); + p.setVisitsCount(this.visitService.getUniqueVisitsCount(p)); + }); + + return posts; + } + + @Cacheable(value = CACHE_NAME_PAGE, key = "T(java.lang.String).valueOf(#page).concat('-').concat(#pageSize)") + public Page getAllPublishedNotCensoredNotDeletedPostsByPage(int page, int pageSize) { + logger.debug("Get not censored posts by page " + page); + + Page posts = postRepository.findAllByPostTypeAndPostStatusAndDeletedMarkAndCensored( + PostType.POST, + PostStatus.PUBLISHED, + false, false, + new PageRequest(page, pageSize, Sort.Direction.DESC, "createdAt")); + + posts.forEach(p -> { + p.setSympathyCount(this.likeService.getTotalLikesByPost(p)); + p.setVisitsCount(this.visitService.getUniqueVisitsCount(p)); + }); + + return posts; + } + + + public List getAllPublishedPosts() { + logger.debug("Get all published posts"); + + return this.postRepository.findAllByPostTypeAndPostStatus(PostType.POST, PostStatus.PUBLISHED); + } + +// public Post createAboutPage() { +// logger.debug("Create default about page"); +// +// Post post = new Post(); +// post.setTitle(Constants.ABOUT_PAGE_PERMALINK); +// post.setContent(Constants.ABOUT_PAGE_PERMALINK.toLowerCase()); +// post.setPermalink(Constants.ABOUT_PAGE_PERMALINK); +// post.setUser(userService.getSuperUser()); +// post.setPostFormat(PostFormat.MARKDOWN); +// +// return createPost(post); +// } + +// public Post createProjectsPage() { +// logger.debug("Create default projects page"); +// +// Post post = new Post(); +// post.setTitle(Constants.PROJECTS_PAGE_PERMALINK); +// post.setContent(Constants.PROJECTS_PAGE_PERMALINK.toLowerCase()); +// post.setPermalink(Constants.PROJECTS_PAGE_PERMALINK); +// post.setUser(userService.getSuperUser()); +// post.setPostFormat(PostFormat.MARKDOWN); +// +// return createPost(post); +// } + + public Set parseTagNames(String tagNames) { + Set tags = new HashSet<>(); + + if (tagNames != null && !tagNames.isEmpty()) { + tagNames = tagNames.toLowerCase(); + String[] names = tagNames.split("\\s*,\\s*"); + for (String name : names) { + tags.add(tagService.findOrCreateByName(name)); + } + } + + return tags; + } + + public String getTagNames(Set tags) { + if (tags == null || tags.isEmpty()) + return ""; + + StringBuilder names = new StringBuilder(); + tags.forEach(tag -> names.append(tag.getName()).append(",")); + names.deleteCharAt(names.length() - 1); + + return names.toString(); + } + + // cache or not? + public Page findPostsByTag(String tagName, int page, int pageSize) { + return postRepository.findByTag(tagName, new PageRequest(page, pageSize, Sort.Direction.DESC, "createdAt")); + } + + @Cacheable(value = CACHE_NAME_COUNTS, key = "#root.method.name") + public List countPostsByTags() { + logger.debug("Count posts group by tags."); + + return postRepository.countPostsByTags(PostStatus.PUBLISHED); + } + + public Post findPostByPermalink(String permalink) { + Post post = null; + + try{ + post = this.getPublishedPostByPermalink(permalink); + } catch (NotFoundException ex){ + if (permalink.matches("\\d+")) { + if (this.userService.isCurrentUserAdmin()) { + post = this.getPost(Long.valueOf(permalink)); + } else { + post = this.getPublishedPost(Long.valueOf(permalink)); + } + }/* else if (permalink.toLowerCase().trim().equals(Constants.PROJECTS_PAGE_PERMALINK)) { + post = this.createProjectsPage(); + }*/ + } + + if (post == null) { + throw new NotFoundException("Post with permalink " + permalink + " is not found"); + } + + return post; + } + + private void saveSeoData(Post post) { + if (post.getSeoData() != null && post.getSeoData().getId() == null) { + SeoPostData data = post.getSeoData(); + this.seoPostDataRepository.save(data); + } + } + +} diff --git a/src/main/java/ru/bvn13/voidforum/services/PrivilegeService.java b/src/main/java/ru/bvn13/voidforum/services/PrivilegeService.java new file mode 100644 index 0000000..c4d365e --- /dev/null +++ b/src/main/java/ru/bvn13/voidforum/services/PrivilegeService.java @@ -0,0 +1,13 @@ +package ru.bvn13.voidforum.services; + +import org.springframework.stereotype.Service; + +@Service +public class PrivilegeService { + public static final String PRIVILEGE_OWNER = "OWNER_PRIVILEGE"; + public static final String PRIVILEGE_ADMIN = "ADMIN_PRIVILEGE"; + public static final String PRIVILEGE_READ = "READ_PRIVILEGE"; + public static final String PRIVILEGE_WRITE = "WRITE_PRIVILEGE"; + public static final String PRIVILEGE_WRITE_HTML = "WRITE_PRIVILEGE_HTML"; + public static final String PRIVILEGE_BLOCKED = "BLOCKED_PRIVILEGE"; +} diff --git a/src/main/java/ru/bvn13/voidforum/services/RequestProcessorService.java b/src/main/java/ru/bvn13/voidforum/services/RequestProcessorService.java new file mode 100644 index 0000000..3c59369 --- /dev/null +++ b/src/main/java/ru/bvn13/voidforum/services/RequestProcessorService.java @@ -0,0 +1,23 @@ +package ru.bvn13.voidforum.services; + +import org.springframework.stereotype.Service; + +import javax.servlet.http.HttpServletRequest; + +@Service +public class RequestProcessorService { + + public String getRealIp(HttpServletRequest request) { + String xRealIp = request.getHeader("X-Real-IP"); + if (xRealIp == null || request.getHeader("X-Real-IP").isEmpty()) { + return request.getRemoteAddr(); + } + return xRealIp; + } + + public String getUserAgent(HttpServletRequest request) { + String userAgent = request.getHeader("User-Agent"); + return userAgent; + } + +} diff --git a/src/main/java/ru/bvn13/voidforum/services/RoleService.java b/src/main/java/ru/bvn13/voidforum/services/RoleService.java new file mode 100644 index 0000000..fcd1198 --- /dev/null +++ b/src/main/java/ru/bvn13/voidforum/services/RoleService.java @@ -0,0 +1,15 @@ +package ru.bvn13.voidforum.services; + +import org.springframework.stereotype.Service; + +@Service +public class RoleService { + public static final String ROLE_OWNER = "ROLE_OWNER"; + public static final String ROLE_ADMIN = "ROLE_ADMIN"; + public static final String ROLE_ADMIN_WITH_HTML_EDITOR = "ROLE_ADMIN_WITH_HTML_EDITOR"; + public static final String ROLE_USER = "ROLE_USER"; + public static final String ROLE_USER_WITH_HTML_EDITOR = "ROLE_USER_WITH_HTML_EDITOR"; + public static final String ROLE_VISITOR = "ROLE_VISITOR"; + public static final String ROLE_BLOCKED = "ROLE_BLOCKED"; + +} diff --git a/src/main/java/ru/bvn13/voidforum/services/SeoRobotAgentService.java b/src/main/java/ru/bvn13/voidforum/services/SeoRobotAgentService.java new file mode 100644 index 0000000..3b65427 --- /dev/null +++ b/src/main/java/ru/bvn13/voidforum/services/SeoRobotAgentService.java @@ -0,0 +1,10 @@ +package ru.bvn13.voidforum.services; + +import org.springframework.stereotype.Service; + +@Service +public class SeoRobotAgentService { + + + +} diff --git a/src/main/java/ru/bvn13/voidforum/services/SeoService.java b/src/main/java/ru/bvn13/voidforum/services/SeoService.java new file mode 100644 index 0000000..70b91bd --- /dev/null +++ b/src/main/java/ru/bvn13/voidforum/services/SeoService.java @@ -0,0 +1,81 @@ +package ru.bvn13.voidforum.services; + +import ru.bvn13.voidforum.models.Post; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.transform.Transformer; +import javax.xml.transform.TransformerException; +import javax.xml.transform.TransformerFactory; +import javax.xml.transform.dom.DOMSource; +import javax.xml.transform.stream.StreamResult; +import java.io.StringWriter; +import java.text.SimpleDateFormat; +import java.util.List; + +@Service +public class SeoService { + + public static final SimpleDateFormat dateFormatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssXXX"); + + @Autowired + private AppSetting appSetting; + + + public String createSitemap(List posts) { + + String slash = appSetting.getMainUri().trim().endsWith("/") ? "" : "/"; + + try { + DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance(); + DocumentBuilder docBuilder = docFactory.newDocumentBuilder(); + + Document doc = docBuilder.newDocument(); + Element root = doc.createElement("urlset"); + root.setAttribute("xmlns", "http://www.sitemaps.org/schemas/sitemap/0.9"); + doc.appendChild(root); + + for(Post post : posts) { + Element url = doc.createElement("url"); + //loc + Element loc = doc.createElement("loc"); + loc.appendChild(doc.createTextNode(String.format("%s%sposts/%s", appSetting.getMainUri().trim(), slash, post.getPermalink() == null || post.getPermalink().isEmpty() ? post.getId() : post.getPermalink()))); + url.appendChild(loc); + //lastmod + //yyyy-MM-dd'T'HH:mm:ss + Element lastMod = doc.createElement("lastmod"); + lastMod.appendChild(doc.createTextNode(dateFormatter.format(post.getUpdatedAt()))); + url.appendChild(lastMod); + // + Element changeFreq = doc.createElement("changefreq"); + changeFreq.appendChild(doc.createTextNode("daily")); + url.appendChild(changeFreq); + + root.appendChild(url); + } + + // write the content into xml file + TransformerFactory transformerFactory = TransformerFactory.newInstance(); + Transformer transformer = transformerFactory.newTransformer(); + DOMSource source = new DOMSource(doc); + + StringWriter sw = new StringWriter(); + transformer.transform(new DOMSource(doc), new StreamResult(sw)); + return sw.toString(); + + } catch (ParserConfigurationException e) { + e.printStackTrace(); + return null; + } catch (TransformerException tfe) { + tfe.printStackTrace(); + return null; + } + + } + +} diff --git a/src/main/java/ru/bvn13/voidforum/services/SettingService.java b/src/main/java/ru/bvn13/voidforum/services/SettingService.java new file mode 100644 index 0000000..c7823b3 --- /dev/null +++ b/src/main/java/ru/bvn13/voidforum/services/SettingService.java @@ -0,0 +1,12 @@ +package ru.bvn13.voidforum.services; + +import java.io.Serializable; + +/** + * bvn13 + */ +public interface SettingService { + Serializable get(String key); + Serializable get(String key, Serializable defaultValue); + void put(String key, Serializable value); +} diff --git a/src/main/java/ru/bvn13/voidforum/services/TagService.java b/src/main/java/ru/bvn13/voidforum/services/TagService.java new file mode 100644 index 0000000..c80ab3a --- /dev/null +++ b/src/main/java/ru/bvn13/voidforum/services/TagService.java @@ -0,0 +1,63 @@ +package ru.bvn13.voidforum.services; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.cache.annotation.CacheEvict; +import org.springframework.cache.annotation.Cacheable; +import org.springframework.cache.annotation.Caching; +import org.springframework.stereotype.Service; +import ru.bvn13.voidforum.models.Tag; +import ru.bvn13.voidforum.repositories.TagRepository; + +import java.util.List; + + +/** + * bvn13 . + */ +@Service +public class TagService { + private TagRepository tagRepository; + + private static final Logger logger = LoggerFactory.getLogger(PostService.class); + + public static final String CACHE_NAME = "cache.tag"; + public static final String CACHE_NAME_TAGS = "cache.tag.all"; + + public static final String CACHE_TYPE = "'_Tag_'"; + public static final String CACHE_KEY = CACHE_TYPE + " + #tagName"; + public static final String CACHE_TAG_KEY = CACHE_TYPE + " + #tag.name"; + + @Autowired + public TagService(TagRepository tagRepository){ + this.tagRepository = tagRepository; + } + + public Tag findOrCreateByName(String name){ + Tag tag = tagRepository.findByName(name); + if (tag == null){ + tag = tagRepository.save(new Tag(name)); + } + return tag; + } + + @Cacheable(value = CACHE_NAME, key = CACHE_KEY) + public Tag getTag(String tagName) { + return tagRepository.findByName(tagName); + } + + @Caching(evict = { + @CacheEvict(value = CACHE_NAME, key = CACHE_TAG_KEY), + @CacheEvict(value = CACHE_NAME_TAGS, allEntries = true) + }) + public void deleteTag(Tag tag){ + tagRepository.delete(tag); + } + + @Cacheable(value = CACHE_NAME_TAGS, key = "#root.method.name") + public List getAllTags(){ + return tagRepository.findAll(); + } + +} diff --git a/src/main/java/ru/bvn13/voidforum/services/UserService.java b/src/main/java/ru/bvn13/voidforum/services/UserService.java new file mode 100644 index 0000000..98b879d --- /dev/null +++ b/src/main/java/ru/bvn13/voidforum/services/UserService.java @@ -0,0 +1,233 @@ +package ru.bvn13.voidforum.services; + +import com.domingosuarez.boot.autoconfigure.jade4j.JadeHelper; +import org.hibernate.Hibernate; +import org.hibernate.SessionFactory; +import org.hibernate.hql.internal.ast.util.SessionFactoryHelper; +import ru.bvn13.voidforum.error.EmailExistsException; +import ru.bvn13.voidforum.error.NicknameExistsException; +import ru.bvn13.voidforum.models.Privilege; +import ru.bvn13.voidforum.models.User; +import ru.bvn13.voidforum.models.Role; +import ru.bvn13.voidforum.models.support.PostFormat; +import ru.bvn13.voidforum.repositories.PrivilegeRepository; +import ru.bvn13.voidforum.repositories.UserRepository; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.authentication.AnonymousAuthenticationToken; +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.core.authority.SimpleGrantedAuthority; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.security.core.userdetails.UserDetailsService; +import org.springframework.security.core.userdetails.UsernameNotFoundException; +import org.springframework.security.crypto.password.PasswordEncoder; +import ru.bvn13.voidforum.repositories.RoleRepository; +import ru.bvn13.voidforum.utils.DTOUtil; + +import javax.annotation.PostConstruct; +import javax.inject.Inject; +import javax.transaction.Transactional; +import java.util.*; +import java.util.concurrent.atomic.AtomicReference; + +@JadeHelper("userService") +public class UserService implements UserDetailsService { + + private static final Logger logger = LoggerFactory.getLogger(UserService.class); + + @Autowired + private UserRepository userRepository; + + @Autowired + private RoleRepository roleRepository; + + @Autowired + private PrivilegeRepository privilegeRepository; + + @Inject + private PasswordEncoder passwordEncoder; + +// @Autowired +// private SessionFactory sessionFactory; + + + + @PostConstruct + protected void initialize() { + //getSuperUser(); + } + + public User createUser(User user){ + user.setPassword(passwordEncoder.encode(user.getPassword())); + return userRepository.save(user); + } + + + @Override + public UserDetails loadUserByUsername(String email) throws UsernameNotFoundException { + + org.springframework.security.core.userdetails.User springUser = null; + + //sessionFactory.openSession(); + + User user = userRepository.findByEmail(email); + if (user == null) { + springUser = new org.springframework.security.core.userdetails.User( + " ", " ", true, true, true, true, + getAuthorities(Arrays.asList( + roleRepository.findByName(RoleService.ROLE_VISITOR)) + ) + ); + } else { + List roles = roleRepository.findAllByUser(user); + springUser = new org.springframework.security.core.userdetails.User( + user.getEmail(), user.getPassword(), !user.getDisabled(), true, true, + true, getAuthorities(roles) + ); + } + + //sessionFactory.close(); + + return springUser; + } + + private Collection getAuthorities(Collection roles) { + return getGrantedAuthorities(getPrivileges(roles)); + } + + public List getPrivileges(Collection roles) { + + List privileges = new ArrayList<>(); + List collection = new ArrayList<>(); + for (Role role : roles) { + //role.setPrivileges(privilegeRepository.findAllByRole(role)); + collection.addAll(privilegeRepository.findAllByRole(role)); + } + for (Privilege item : collection) { + privileges.add(item.getName()); + } + return privileges; + } + + private List getGrantedAuthorities(List privileges) { + List authorities = new ArrayList<>(); + for (String privilege : privileges) { + authorities.add(new SimpleGrantedAuthority(privilege)); + } + return authorities; + } + + + public User currentUser(){ + Authentication auth = SecurityContextHolder.getContext().getAuthentication(); + if(auth == null || auth instanceof AnonymousAuthenticationToken){ + return null; + } + + String email = ((org.springframework.security.core.userdetails.User) auth.getPrincipal()).getUsername(); + + return userRepository.findByEmail(email); + } + + public Boolean isCurrentUserAdmin() { + User user = this.currentUser(); + Boolean isAdmin = user != null ? this.hasPrivilege(user, PrivilegeService.PRIVILEGE_ADMIN) : false; + return isAdmin; + } + + public boolean changePassword(User user, String password, String newPassword){ + if (password == null || newPassword == null || password.isEmpty() || newPassword.isEmpty()) + return false; + + logger.info("" + passwordEncoder.matches(password, user.getPassword())); + boolean match = passwordEncoder.matches(password, user.getPassword()); + if (!match) + return false; + + user.setPassword(passwordEncoder.encode(newPassword)); + userRepository.save(user); + + logger.info("User @"+user.getEmail() + " changed password."); + + return true; + } + + + public Boolean currentUserHasPrivilege(String privilege) { + User user = this.currentUser(); + return this.hasPrivilege(user, privilege); + } + + + public User registerNewUserAccount(User user) throws EmailExistsException, NicknameExistsException { + + if (emailExist(user.getEmail())) { + throw new EmailExistsException("There is an account with that email address: " + user.getEmail()); + } + if (nicknameExists(user.getNickname())) { + throw new NicknameExistsException("There is an account with that nickname: " + user.getNickname()); + } + user.setPassword(passwordEncoder.encode(user.getPassword())); + user.setDisabled(false); + + user.setRoles(Arrays.asList(roleRepository.findByName(RoleService.ROLE_USER))); + return userRepository.save(user); + } + + + public Boolean emailExist(String email) { + return this.userRepository.findByEmail(email) != null; + } + + public Boolean nicknameExists(String nickname) { + return this.userRepository.findByNickname(nickname) != null; + } + + public Boolean hasRole(User user, String role) { + if (user == null) { + return false; + } + AtomicReference hasRole = new AtomicReference<>(false); + user.getRoles().forEach(r -> { + if (r.getName().equals(role)) { + hasRole.set(true); + } + }); + return hasRole.get(); + } + + public Boolean hasPrivilege(User user, String privilege) { + if (user == null) { + return false; + } + AtomicReference hasPrivilege = new AtomicReference<>(false); + user.getRoles().forEach(r -> { + r.getPrivileges().forEach(p -> { + if (p.getName().equals(privilege)) { + hasPrivilege.set(true); + } + }); + }); + return hasPrivilege.get(); + } + + + public List getAvailablePostFormats(User user) { + List availableFormats = new ArrayList<>(); + for (PostFormat postFormat : PostFormat.values()) { + if (postFormat.equals(PostFormat.HTML)) { + if (hasPrivilege(user, PrivilegeService.PRIVILEGE_WRITE_HTML)) { + availableFormats.add(postFormat); + } + } else { + availableFormats.add(postFormat); + } + } + return availableFormats; + } + +} diff --git a/src/main/java/ru/bvn13/voidforum/services/VisitService.java b/src/main/java/ru/bvn13/voidforum/services/VisitService.java new file mode 100644 index 0000000..46bca31 --- /dev/null +++ b/src/main/java/ru/bvn13/voidforum/services/VisitService.java @@ -0,0 +1,103 @@ +package ru.bvn13.voidforum.services; + +import ru.bvn13.voidforum.models.Post; +import ru.bvn13.voidforum.models.SeoRobotAgent; +import ru.bvn13.voidforum.models.User; +import ru.bvn13.voidforum.models.Visit; +import ru.bvn13.voidforum.repositories.SeoRobotAgentRepository; +import ru.bvn13.voidforum.repositories.VisitRepository; +import org.hibernate.SQLQuery; +import org.hibernate.Session; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import javax.persistence.EntityManager; +import java.math.BigInteger; +import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +@Service +public class VisitService { + + @Autowired + private VisitRepository visitRepository; + + @Autowired + private SeoRobotAgentRepository seoRobotAgentRepository; + + @Autowired + private UserService userService; + + @Autowired + private EntityManager entityManager; + + public void saveVisit(Post post, String clientIp, String userAgent) { +// if (this.userService.currentUser().isAdmin()) +// return; + + User user = this.userService.currentUser(); + + Visit visit = new Visit(); + visit.setClientIp(clientIp); + visit.setPost(post); + visit.setUser(user); + visit.setIsAdmin(user != null ? userService.hasPrivilege(user, PrivilegeService.PRIVILEGE_ADMIN) : false); + visit.setUserAgent(userAgent); + this.visitRepository.save(visit); + } + + public Long getUniqueVisitsCount(Post post) { + + Session session = (Session) this.entityManager.getDelegate(); + SQLQuery query = session.createSQLQuery( + "SELECT COUNT(DISTINCT v.clientIp) " + + "FROM visits AS v " + + "LEFT JOIN seo_robots_agents AS ra " + + //"ON LOWER(v.userAgent) LIKE concat('%', LOWER(ra.userAgent), '%') " + + "ON CASE WHEN ra.isregexp = TRUE THEN " + + "LOWER(v.userAgent) SIMILAR TO concat(LOWER(ra.userAgent)) " + + "ELSE " + + "LOWER(v.userAgent) LIKE concat('%', LOWER(ra.userAgent), '%') " + + "END " + + "WHERE v.post_id = :post_id AND v.isAdmin = FALSE " + + "AND ra.id IS NULL "); + query.setLong("post_id", post.getId()); + List result = query.list(); + if (result.size() > 0L) { + return ((BigInteger)result.get(0)).longValue(); + } + + return 0L; + + } + + public Long getUniqueVisitsCount_old(Post post) { + //return this.visitRepository.getUniquePostVisitsCount(post); + + // exclude queries from robots if matches by UserAgent + List robotsAgents = this.seoRobotAgentRepository.findAll(); + + final Long[] count = {0L}; + + this.visitRepository.getVisitsByPostAndIsAdminIsFalse(post).forEach(vr -> { + + Object[] v = (Object[]) vr; + + if (robotsAgents.size() == 0 || v[1] == null) { + count[0]++; + } else { + robotsAgents.forEach(ra -> { + Pattern p = Pattern.compile(".*("+ra.getUserAgent()+").*", Pattern.CASE_INSENSITIVE); + Matcher m = p.matcher((String) v[1]); + if (!m.matches()) { + count[0]++; + } + }); + } + }); + + return count[0]; + } + +} diff --git a/src/main/java/ru/bvn13/voidforum/support/InitialDataLoader.java b/src/main/java/ru/bvn13/voidforum/support/InitialDataLoader.java new file mode 100644 index 0000000..6c9fab8 --- /dev/null +++ b/src/main/java/ru/bvn13/voidforum/support/InitialDataLoader.java @@ -0,0 +1,133 @@ +package ru.bvn13.voidforum.support; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.ApplicationListener; +import org.springframework.context.event.ContextRefreshedEvent; +import org.springframework.security.crypto.password.PasswordEncoder; +import org.springframework.stereotype.Component; +import ru.bvn13.voidforum.Constants; +import ru.bvn13.voidforum.models.Privilege; +import ru.bvn13.voidforum.models.User; +import ru.bvn13.voidforum.models.Role; +import ru.bvn13.voidforum.repositories.PrivilegeRepository; +import ru.bvn13.voidforum.repositories.UserRepository; +import ru.bvn13.voidforum.repositories.RoleRepository; +import ru.bvn13.voidforum.services.PrivilegeService; +import ru.bvn13.voidforum.services.RoleService; + +import javax.transaction.Transactional; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.List; + +@Component +public class InitialDataLoader implements ApplicationListener { + + boolean alreadySetup = false; + + @Autowired + private UserRepository userRepository; + + @Autowired + private RoleRepository roleRepository; + + @Autowired + private PrivilegeRepository privilegeRepository; + + @Autowired + private PasswordEncoder passwordEncoder; + + @Override + @Transactional + public void onApplicationEvent(ContextRefreshedEvent event) { + + if (alreadySetup) + return; + + Privilege ownerPrivilege = createPrivilegeIfNotFound(PrivilegeService.PRIVILEGE_OWNER); + Privilege adminPrivilege = createPrivilegeIfNotFound(PrivilegeService.PRIVILEGE_ADMIN); + Privilege readPrivilege = createPrivilegeIfNotFound(PrivilegeService.PRIVILEGE_READ); + Privilege writePrivilege = createPrivilegeIfNotFound(PrivilegeService.PRIVILEGE_WRITE); + Privilege writeHtmlPrivilege = createPrivilegeIfNotFound(PrivilegeService.PRIVILEGE_WRITE_HTML); + Privilege blockedPrivilege = createPrivilegeIfNotFound(PrivilegeService.PRIVILEGE_BLOCKED); + + + Role roleOwner = createRoleIfNotFound(RoleService.ROLE_OWNER, Arrays.asList(ownerPrivilege, adminPrivilege, writePrivilege, writeHtmlPrivilege, readPrivilege)); + + createRoleIfNotFound(RoleService.ROLE_ADMIN, Arrays.asList(adminPrivilege, readPrivilege, writePrivilege)); + createRoleIfNotFound(RoleService.ROLE_ADMIN_WITH_HTML_EDITOR, Arrays.asList(adminPrivilege, readPrivilege, writePrivilege, writeHtmlPrivilege)); + createRoleIfNotFound(RoleService.ROLE_USER, Arrays.asList(readPrivilege, writePrivilege)); + createRoleIfNotFound(RoleService.ROLE_USER_WITH_HTML_EDITOR, Arrays.asList(readPrivilege, writePrivilege, writeHtmlPrivilege)); + createRoleIfNotFound(RoleService.ROLE_VISITOR, Arrays.asList(readPrivilege)); + createRoleIfNotFound(RoleService.ROLE_BLOCKED, Arrays.asList(readPrivilege, blockedPrivilege)); + + + if (userRepository.findAllByOneRoleByNameOrderById(RoleService.ROLE_OWNER).size() == 0) { + User user = new User(); + user.setNickname(Constants.DEFAULT_ADMIN_NICKNAME); + user.setEmail(Constants.DEFAULT_ADMIN_EMAIL); + user.setPassword(passwordEncoder.encode(Constants.DEFAULT_ADMIN_PASSWORD)); + user.setRoles(Arrays.asList(roleOwner)); + user.setDisabled(false); + userRepository.save(user); + } + + alreadySetup = true; + } + + @Transactional + public Privilege createPrivilegeIfNotFound(String name) { + + Privilege privilege = privilegeRepository.findByName(name); + if (privilege == null) { + privilege = new Privilege(name); + privilegeRepository.save(privilege); + } + return privilege; + } + + @Transactional + public Role createRoleIfNotFound(String name, Collection privileges) { + + Role role = roleRepository.findByName(name); + if (role == null) { + role = new Role(name); + role.setPrivileges(privileges); + } else { + // add new privileges + for (Privilege privilege : privileges) { + boolean found = false; + for (Privilege p : role.getPrivileges()) { + if (p.getName().equals(privilege.getName())) { + found = true; + break; + } + } + if (!found) { + role.getPrivileges().add(privilege); + } + } + // remove unused privileges + List privilegeListForRemoving = new ArrayList<>(); + for (Privilege p : role.getPrivileges()) { + boolean found = false; + for (Privilege privilege : privileges) { + if (p.getName().equals(privilege.getName())) { + found = true; + break; + } + } + if (!found) { + privilegeListForRemoving.add(p); + } + } + for (Privilege privilege : privilegeListForRemoving) { + role.getPrivileges().remove(privilege); + } + } + roleRepository.save(role); + return role; + } + +} diff --git a/src/main/java/ru/bvn13/voidforum/support/web/FlexmarkMarkdownService.java b/src/main/java/ru/bvn13/voidforum/support/web/FlexmarkMarkdownService.java new file mode 100644 index 0000000..2413083 --- /dev/null +++ b/src/main/java/ru/bvn13/voidforum/support/web/FlexmarkMarkdownService.java @@ -0,0 +1,48 @@ +package ru.bvn13.voidforum.support.web; + +import com.vladsch.flexmark.ast.Node; +import com.vladsch.flexmark.ext.gfm.strikethrough.StrikethroughExtension; +import com.vladsch.flexmark.ext.tables.TablesExtension; +import com.vladsch.flexmark.ext.youtube.embedded.YouTubeLinkExtension; +import com.vladsch.flexmark.html.HtmlRenderer; +import com.vladsch.flexmark.parser.Parser; +import com.vladsch.flexmark.util.options.MutableDataSet; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.stereotype.Service; + +import java.util.Arrays; + +@Service +@Qualifier("flexmark") +public class FlexmarkMarkdownService implements MarkdownService, SyntaxHighlightService { + @Override + public String renderToHtml(String content) { + + MutableDataSet options = new MutableDataSet(); + + // uncomment to set optional extensions + options.set(Parser.EXTENSIONS, Arrays.asList( + TablesExtension.create(), + StrikethroughExtension.create(), + //YoutubeLinkTransformer.YouTubeLinkExtension.create(), + YouTubeLinkExtension.create() + )); + + // uncomment to convert soft-breaks to hard breaks + //options.set(HtmlRenderer.SOFT_BREAK, "
\n"); + + Parser parser = Parser.builder(options).build(); + HtmlRenderer renderer = HtmlRenderer.builder(options).build(); + + // You can re-use parser and renderer instances + Node document = parser.parse(content); + String html = renderer.render(document); // "

This is Sparta

\n" + + return html; + } + + @Override + public String highlight(String content) { + return content; + } +} diff --git a/src/main/java/ru/bvn13/voidforum/support/web/MarkdownService.java b/src/main/java/ru/bvn13/voidforum/support/web/MarkdownService.java new file mode 100644 index 0000000..2241a0e --- /dev/null +++ b/src/main/java/ru/bvn13/voidforum/support/web/MarkdownService.java @@ -0,0 +1,8 @@ +package ru.bvn13.voidforum.support.web; + +/** + * @author bvn13 + */ +public interface MarkdownService { + public String renderToHtml(String content); +} diff --git a/src/main/java/ru/bvn13/voidforum/support/web/Message.java b/src/main/java/ru/bvn13/voidforum/support/web/Message.java new file mode 100644 index 0000000..f1b4a96 --- /dev/null +++ b/src/main/java/ru/bvn13/voidforum/support/web/Message.java @@ -0,0 +1,46 @@ +package ru.bvn13.voidforum.support.web; + +/** + * A message to be displayed in web context. Depending on the type, different style will be applied. + */ +public class Message implements java.io.Serializable { + /** + * Name of the flash attribute. + */ + public static final String MESSAGE_ATTRIBUTE = "message"; + + /** + * The type of the message to be displayed. The type is used to show message in a different style. + */ + public static enum Type { + DANGER, WARNING, INFO, SUCCESS; + } + + private final String message; + private final Type type; + private final Object[] args; + + public Message(String message, Type type) { + this.message = message; + this.type = type; + this.args = null; + } + + public Message(String message, Type type, Object... args) { + this.message = message; + this.type = type; + this.args = args; + } + + public String getMessage() { + return message; + } + + public Type getType() { + return type; + } + + public Object[] getArgs() { + return args; + } +} diff --git a/src/main/java/ru/bvn13/voidforum/support/web/MessageHelper.java b/src/main/java/ru/bvn13/voidforum/support/web/MessageHelper.java new file mode 100644 index 0000000..1247617 --- /dev/null +++ b/src/main/java/ru/bvn13/voidforum/support/web/MessageHelper.java @@ -0,0 +1,53 @@ +package ru.bvn13.voidforum.support.web; + +import org.springframework.ui.Model; +import org.springframework.web.servlet.mvc.support.RedirectAttributes; + +import static ru.bvn13.voidforum.support.web.Message.MESSAGE_ATTRIBUTE; + +public final class MessageHelper { + + private MessageHelper() { + + } + + public static void addSuccessAttribute(RedirectAttributes ra, String message, Object... args) { + addAttribute(ra, message, Message.Type.SUCCESS, args); + } + + public static void addErrorAttribute(RedirectAttributes ra, String message, Object... args) { + addAttribute(ra, message, Message.Type.DANGER, args); + } + + public static void addInfoAttribute(RedirectAttributes ra, String message, Object... args) { + addAttribute(ra, message, Message.Type.INFO, args); + } + + public static void addWarningAttribute(RedirectAttributes ra, String message, Object... args) { + addAttribute(ra, message, Message.Type.WARNING, args); + } + + private static void addAttribute(RedirectAttributes ra, String message, Message.Type type, Object... args) { + ra.addFlashAttribute(MESSAGE_ATTRIBUTE, new Message(message, type, args)); + } + + public static void addSuccessAttribute(Model model, String message, Object... args) { + addAttribute(model, message, Message.Type.SUCCESS, args); + } + + public static void addErrorAttribute(Model model, String message, Object... args) { + addAttribute(model, message, Message.Type.DANGER, args); + } + + public static void addInfoAttribute(Model model, String message, Object... args) { + addAttribute(model, message, Message.Type.INFO, args); + } + + public static void addWarningAttribute(Model model, String message, Object... args) { + addAttribute(model, message, Message.Type.WARNING, args); + } + + private static void addAttribute(Model model, String message, Message.Type type, Object... args) { + model.addAttribute(MESSAGE_ATTRIBUTE, new Message(message, type, args)); + } +} diff --git a/src/main/java/ru/bvn13/voidforum/support/web/SyntaxHighlightService.java b/src/main/java/ru/bvn13/voidforum/support/web/SyntaxHighlightService.java new file mode 100644 index 0000000..a007450 --- /dev/null +++ b/src/main/java/ru/bvn13/voidforum/support/web/SyntaxHighlightService.java @@ -0,0 +1,8 @@ +package ru.bvn13.voidforum.support.web; + +/** + * @author bvn13 + */ +public interface SyntaxHighlightService { + public String highlight(String content); +} diff --git a/src/main/java/ru/bvn13/voidforum/support/web/ViewHelperVF.java b/src/main/java/ru/bvn13/voidforum/support/web/ViewHelperVF.java new file mode 100644 index 0000000..3420623 --- /dev/null +++ b/src/main/java/ru/bvn13/voidforum/support/web/ViewHelperVF.java @@ -0,0 +1,133 @@ +package ru.bvn13.voidforum.support.web; + + +import com.domingosuarez.boot.autoconfigure.jade4j.JadeHelper; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import ru.bvn13.voidforum.models.Post; +import ru.bvn13.voidforum.models.support.WebError; +import ru.bvn13.voidforum.services.AppSetting; + +import java.text.DateFormatSymbols; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.Map; + +/** + * @author bvn13 + */ +@Service +@JadeHelper("viewHelper") +public class ViewHelperVF { + + private static Logger logger = LoggerFactory.getLogger(ViewHelperVF.class); + + private static DateFormatSymbols ruDateFormatSymbolsFull = new DateFormatSymbols(){ + @Override + public String[] getMonths() { + return new String[]{"январь", "февраль", "март", "апрель", "май", "июнь", "июль", "август", "сентябрь", "октябрь", "ноябрь", "декабрь"}; + } + }; + private static DateFormatSymbols ruDateFormatSymbolsShort = new DateFormatSymbols(){ + @Override + public String[] getMonths() { + return new String[]{"янв", "фев", "мар", "апр", "май", "июн", "июл", "авг", "сен", "окт", "ноя", "дек"}; + } + }; + + private static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("MMMM dd, yyyy", ViewHelperVF.ruDateFormatSymbolsFull); + private static final SimpleDateFormat DATE_FORMAT_MONTH_DAY = new SimpleDateFormat("MMM dd", ViewHelperVF.ruDateFormatSymbolsShort); + + private AppSetting appSetting; + + private String applicationEnv; + + @Autowired + public ViewHelperVF(AppSetting appSetting){ + this.appSetting = appSetting; + } + + private long startTime; + + public long getResponseTime(){ + return System.currentTimeMillis() - startTime; + } + + public long getStartTime() { + return startTime; + } + + public void setStartTime(long startTime) { + this.startTime = startTime; + } + + public String getFormattedDate(Date date){ + return date == null ? "" : DATE_FORMAT.format(date); + } + + public String getMonthAndDay(Date date){ + return date == null ? "" : DATE_FORMAT_MONTH_DAY.format(date); + } + + public String metaTitle(String title){ + return title + " · " + appSetting.getSiteName(); + } + + public String getApplicationEnv() { + return applicationEnv; + } + + public Boolean isProductionMode() { + return this.applicationEnv.equalsIgnoreCase("production"); + } + + public void setApplicationEnv(String applicationEnv) { + this.applicationEnv = applicationEnv; + } + + public String formatNumberByThousands(Long number) { + if (number == null) + return "0"; + + double thousands = number / 1000; + double millions = thousands / 1000; + if (millions > 0d) { + return String.format("%.3f", millions); + } else if (thousands > 0d) { + return String.format("%.3fK", thousands); + } else { + return String.format("%d", number); + } + } + + public String formatNumberByThousands(Integer number) { + return this.formatNumberByThousands((long) number); + } + + public String errorFormat(Map errors, String field) { + if (errors != null && errors.containsKey(field)) { + return errors.get(field).getErrorMessage(); + } else { + return ""; + } + } + + public String getPostUrl(Post post) { + return String.format("%s/posts/%s", + this.appSetting.getMainUri().endsWith("/") ? this.appSetting.getMainUri().substring(0, this.appSetting.getMainUri().length()-1) : this.appSetting.getMainUri(), + post.getPermalink().isEmpty() ? post.getId() : post.getPermalink() + ); + } + + public String getAbsoluteUrl(String url) { + if (url.isEmpty()) { + return ""; + } + return String.format("%s/%s", + this.appSetting.getMainUri().endsWith("/") ? this.appSetting.getMainUri().substring(0, this.appSetting.getMainUri().length()-1) : this.appSetting.getMainUri(), + url.startsWith("/") ? url.substring(1) : url + ); + } +} diff --git a/src/main/java/ru/bvn13/voidforum/utils/DTOUtil.java b/src/main/java/ru/bvn13/voidforum/utils/DTOUtil.java new file mode 100644 index 0000000..77afc11 --- /dev/null +++ b/src/main/java/ru/bvn13/voidforum/utils/DTOUtil.java @@ -0,0 +1,55 @@ +package ru.bvn13.voidforum.utils; + +import org.hibernate.Hibernate; +import org.hibernate.proxy.HibernateProxy; +import org.modelmapper.ModelMapper; +import org.modelmapper.convention.MatchingStrategies; + +import java.util.ArrayList; +import java.util.List; + +/** + * @author bvn13 + */ +public class DTOUtil { + + private static ModelMapper MAPPER = null; + + private static ModelMapper getMapper(){ + if(MAPPER == null){ + MAPPER = new ModelMapper(); + MAPPER.getConfiguration().setMatchingStrategy(MatchingStrategies.STRICT); + } + + return MAPPER; + } + + public static T map(S source, Class targetClass) { + return getMapper().map(source, targetClass); + } + + public static void mapTo(S source, T dist) { + getMapper().map(source, dist); + } + + public static List mapList(List source, Class targetClass) { + List list = new ArrayList<>(); + for (S s : source) { + list.add(getMapper().map(s, targetClass)); + } + return list; + } + + public static T initializeAndUnproxy(T entity) { + if (entity == null) { + throw new + NullPointerException("Entity passed for initialization is null"); + } + + Hibernate.initialize(entity); + if (entity instanceof HibernateProxy) { + entity = (T) ((HibernateProxy) entity).getHibernateLazyInitializer().getImplementation(); + } + return entity; + } +} diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml new file mode 100644 index 0000000..ba61ecb --- /dev/null +++ b/src/main/resources/application.yml @@ -0,0 +1,46 @@ +server: + port: 9000 + contextPath: + +spring: + profiles: + active: dev + + thymeleaf: + #mode: html5 + #suffix: .html + cache: false + + jade4j: + caching: false + + dataSource: + driverClassName: org.postgresql.Driver + url: jdbc:postgresql://localhost:5432/voidforum + username: voidforum + password: vfpass + + hibernate: + dialect: org.hibernate.dialect.PostgreSQLDialect + hbm2ddl.auto: update + show_sql: false + + redis: + embedded : false + host: localhost + port: 6379 + default_expire_time: 86400 + + session: + store-type: redis + + + jpa: + properties: + hibernate: + current_session_context_class: org.springframework.orm.hibernate5.SpringSessionContext + + http: + multipart: + max-file-size: 100Mb + max-request-size: 100Mb diff --git a/src/main/resources/i18n/messages.properties b/src/main/resources/i18n/messages.properties new file mode 100644 index 0000000..d51250f --- /dev/null +++ b/src/main/resources/i18n/messages.properties @@ -0,0 +1,7 @@ +view.index.title=Home page +signup.success=Congratulations {0}! You have successfully signed up. +signin.already=You have already signed in. + +# Validation messages +notBlank.message = The value may not be empty! +email.message = The value must be a valid email! \ No newline at end of file diff --git a/src/main/resources/logback.xml b/src/main/resources/logback.xml new file mode 100644 index 0000000..5688450 --- /dev/null +++ b/src/main/resources/logback.xml @@ -0,0 +1,37 @@ + + + VoidForum + + + + + %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{32} - %msg%n + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/main/resources/resources/css/account/account.css b/src/main/resources/resources/css/account/account.css new file mode 100644 index 0000000..da8a9e5 --- /dev/null +++ b/src/main/resources/resources/css/account/account.css @@ -0,0 +1,45 @@ +body { + -webkit-font-smoothing: antialiased; + color: #434343; +} + +.main-container{ + padding-top: 60px; +} + +form .item-row{ + margin-top: 10px; +} + +td.operations, th.operations{ + text-align: center; + width: 120px; +} +td.operations a{ + margin-left: 5px; +} + +.post-form textarea{ + height: 350px; +} + + +.post-form #content-editor{ + height: 430px; + width: 100%; +} + + +.settings-form tbody td.setting-label{ + width: 250px; + text-align: right; + padding-right: 20px; + vertical-align: middle; + font-weight: bold; +} + +.profile .row .col-sm-2{ + font-weight: bold; + text-align: right; + padding-right: 30px; +} diff --git a/src/main/resources/resources/css/admin/admin.css b/src/main/resources/resources/css/admin/admin.css new file mode 100644 index 0000000..da8a9e5 --- /dev/null +++ b/src/main/resources/resources/css/admin/admin.css @@ -0,0 +1,45 @@ +body { + -webkit-font-smoothing: antialiased; + color: #434343; +} + +.main-container{ + padding-top: 60px; +} + +form .item-row{ + margin-top: 10px; +} + +td.operations, th.operations{ + text-align: center; + width: 120px; +} +td.operations a{ + margin-left: 5px; +} + +.post-form textarea{ + height: 350px; +} + + +.post-form #content-editor{ + height: 430px; + width: 100%; +} + + +.settings-form tbody td.setting-label{ + width: 250px; + text-align: right; + padding-right: 20px; + vertical-align: middle; + font-weight: bold; +} + +.profile .row .col-sm-2{ + font-weight: bold; + text-align: right; + padding-right: 30px; +} diff --git a/src/main/resources/resources/css/modal.css b/src/main/resources/resources/css/modal.css new file mode 100644 index 0000000..084afef --- /dev/null +++ b/src/main/resources/resources/css/modal.css @@ -0,0 +1,90 @@ + +.markdown-body .markdown-post img, +.markdown-body .html-post img.clickable { + border-radius: 5px; + cursor: pointer; + transition: 0.3s; +} + +.markdown-body .markdown-post img:hover, +.markdown-body .html-post img.clickable:hover { + opacity: 0.7; +} + +/* The Modal (background) */ +.modal { + display: none; /* Hidden by default */ + position: fixed; /* Stay in place */ + z-index: 999; /* Sit on top */ + padding-top: 100px; /* Location of the box */ + left: 0; + top: 0; + width: 100%; /* Full width */ + height: 100%; /* Full height */ + overflow: auto; /* Enable scroll if needed */ + background-color: rgb(0,0,0); /* Fallback color */ + background-color: rgba(0,0,0,0.9); /* Black w/ opacity */ +} + +/* Modal Content (image) */ +.modal-content { + margin: auto; + display: block; + width: 80%; + max-width: 700px; +} + +/* Caption of Modal Image */ +#caption { + margin: auto; + display: block; + width: 80%; + max-width: 700px; + text-align: center; + color: #ccc; + padding: 10px 0; + height: 150px; +} + +/* Add Animation */ +.modal-content, #caption { + -webkit-animation-name: zoom; + -webkit-animation-duration: 0.6s; + animation-name: zoom; + animation-duration: 0.6s; +} + +@-webkit-keyframes zoom { + from {-webkit-transform:scale(0)} + to {-webkit-transform:scale(1)} +} + +@keyframes zoom { + from {transform:scale(0)} + to {transform:scale(1)} +} + +/* The Close Button */ +.close { + position: absolute; + top: 15px; + right: 35px; + color: #f1f1f1; + font-size: 40px; + font-weight: bold; + transition: 0.3s; +} + +.close:hover, +.close:focus { + color: #bbb; + text-decoration: none; + cursor: pointer; +} + +/* 100% Image Width on Smaller Screens */ +@media only screen and (max-width: 700px){ + .modal-content { + width: 100%; + } +} \ No newline at end of file diff --git a/src/main/resources/resources/css/mystyle.css b/src/main/resources/resources/css/mystyle.css new file mode 100644 index 0000000..6da8d38 --- /dev/null +++ b/src/main/resources/resources/css/mystyle.css @@ -0,0 +1,177 @@ + +img { + border-radius: 10px; +} + +.main-container { + max-width: none; +} + +.container { + max-width: none; +} + + +.markdown-body { + box-sizing: border-box; + min-width: 200px; + max-width: 980px; + margin: 0 auto; + padding: 15px; + font-family: none !important; +} + +@media (max-width: 767px) { + .markdown-body { + padding: 15px; + } + .header-title { + padding: 0px; + } +} + +.my-font { + /* use same as in theme */ + font-family: "Helvetica Neue", Helvetica, "Microsoft Yahei", "Hiragino Sans GB", "Microsoft Sans Serif", "WenQuanYi Micro Hei", sans !important; +} + +.col-centered { + margin: 0 auto; + float: none; +} + +.post { + padding-top: 0px !important; +} + +.markdown-body img { + width: 100%; + height: auto; +} + +img.flip-vert { + -moz-transform: scaleY(-1); + -o-transform: scaleY(-1); + -webkit-transform: scaleY(-1); + transform: scaleY(-1); + filter: FlipV; + -ms-filter: "FlipV"; +} + +img.flip-hor { + -moz-transform: scaleX(-1); + -o-transform: scaleX(-1); + -webkit-transform: scaleX(-1); + transform: scaleX(-1); + filter: FlipH; + -ms-filter: "FlipH"; +} + +img.flip-both { + -moz-transform: scale(-1, -1); + -o-transform: scale(-1, -1); + -webkit-transform: scale(-1, -1); + transform: scale(-1, -1); +} + +img.borderless { + border: none; + border-radius: 0px; +} + +.sympathy { + padding-left: 5px; + padding-right: 5px; + font-size: 20px; + top: 3px; + position: relative; +} + +.sympathy-block { + padding-left: 10px; + padding-right: 10px; + /*border: grey 1px solid;*/ + /*border-radius: 2px;*/ +} + +.sympathy-button { + cursor: pointer; +} + +.youtube-embedded { + border: none; +} + +@media (max-width: 767px) { + .youtube-embedded { + width: 100%; + /*height: auto;*/ + } +} + +.text-left { + text-align: left !important; +} + +.sympathy-readonly { + +} + +.sympathy-readonly .sympathy { + font-size: 15px; +} + +.sympathy-readonly img { + +} + +.text-mini { + font-size: 12px; +} + + +.table { display: table } +.tr { display: table-row } +.thead { display: table-header-group } +.tbody { display: table-row-group } +.tfoot { display: table-footer-group } +.col { display: table-column } +.colgroup { display: table-column-group } +.td, .th { display: table-cell; vertical-align: top; } +.caption { display: table-caption } + +.post-list {} +.post-info {} +.post-name { + float: left; + padding-top: 7px; +} +.post-name a h2 { + color: #0000ff; +} +.post-name a:visited h2 { + color: #369; +} +.post-tags { + padding-left: 20px; +} +.post-tag { + padding-left: 10px; + margin-left: 5px; +} +.post-subinfo { + +} +.post-username { + padding-left: 3px; +} + +.operations a { + color: white; + margin-left: 5px; +} +.post-status { + float: left; + color: red; + padding-right: 10px; +} \ No newline at end of file diff --git a/src/main/resources/resources/css/theme-light.css b/src/main/resources/resources/css/theme-light.css new file mode 100644 index 0000000..12ddd5b --- /dev/null +++ b/src/main/resources/resources/css/theme-light.css @@ -0,0 +1,275 @@ +html{ + font-size: 100%; +} + +body { + background: #fff; + font: 300 1em/1.8 "Helvetica Neue",Helvetica, Microsoft Yahei, Hiragino Sans GB, Microsoft Sans Serif, WenQuanYi Micro Hei, sans; + -webkit-font-smoothing: antialiased; + color: #515862; +} + +a{ + -webkit-transition-property: opacity; + -moz-transition-property: opacity; + -o-transition-property: opacity; + transition-property: opacity; + -webkit-transition: all 0.3s ease; + -moz-transition: all 0.3s ease; + -o-transition: all 0.3s ease; + transition: all 0.3s ease; +} + +/* override typo css */ +h1, h2, h3, h4, h5, h6{ + color: #47596D; + -webkit-font-smoothing: normal; +} +.typo a{ + color: #337ab7; +} +.typo a:hover{ + color: #666; +} + +hr{ + border-color: #eee; +} + +/* end */ + +pre{ + background: #F9F9F9; + border-radius: 3px; + border-color: #eee; + font-size: 0.8em; + line-height: 1.55; + overflow: auto; + word-break: keep-all; + word-wrap: normal; +} + +a.btn-default{ + color: #888; +} + +a.btn-default:hover{ + background: #fff; + color: #333; + border-color: #333; +} + +.navbar{ + z-index: 100; +} + +.navbar a.navbar-brand{ + color: #9caab0; + font-weight: bold; +} + +.navbar .container{ + border-bottom: 1px #eee solid; + padding-top: 10px; +} + +.navbar li a{ + color: #9caab0; + text-transform: uppercase; + font-weight: bold; + font-size: 0.9em; +} + +.nav>li>a:focus, .nav>li>a:hover{ + background: none; + color: #888; +} + +@media screen and (max-width: 480px) { + #navbar{ + text-align: center; + } + .nav>li{ + display: inline-block; + } +} + +.container{ + padding-top: 20px; + max-width: 840px; +} + +.main-container{ + padding-top: 0; +} + +form input, form button{ + margin-top: 10px; +} + + +.header-title{ + padding: 0 100px; + width: 100%; + position: relative; +} + +.header-title h1 { + margin-top: 20px; +} + +.header-title p{ + font-size: 0.9em; + +} +.header-title p.meta{ + color: #999; + font-size: 0.9em; +} + +.header-title .avatar img{ + margin-top: 20px; + border-radius: 50%; + box-shadow: 0 0 0 3px #fff, 0 0 0 4px #ccc; + width: 80px; + height: 80px; +} + +.header-title-wrapper{ + display: table-cell; + vertical-align: middle; + margin: 0 auto; + text-align: center; + width: 100%; + display: block; +} + + +.post{ + padding: 50px 80px; + margin-bottom: 30px; +} + +@media screen and (max-width: 480px) { + .post{ + padding: 30px 10px; + } + .post h2.title, .post .meta{ + text-align: center; + } +} + + +.post .meta, .typo .post .meta{ + color: rgba(187,187,187,0.8); + font-size: 0.9em; +} + +.post h1 > a, .post h2 > a, .post h3 > a, .post h4 > a{ + color: #75889E; + text-decoration: none; +} + +.post h2.title{ + margin-bottom: 20px; + margin-top: 15px; +} + + +.post h2.title a:hover, .post h2.title a:focus{ + color: #888; +} + +.post .info{ + margin-top: 30px; + text-align: center; + color: #888; + font-size: 0.9em; +} + +.post .comments{ + margin-top: 30px; + padding-top: 30px; + border-top: 1px #eee solid; +} + +.post ul.tags{ + margin-left: 0; + padding-left: 0; +} + +.post ul.tags li{ + display: inline-block; + list-style: none; + margin-left: 10px; +} + +.latest-posts{ + width: 80%; + margin: 0 auto; + margin-top: 30px; + margin-bottom: 50px; +} + +.loadmore{ + text-align: center; + margin-top: 40px; +} + +.post-item{ + text-align: center; + width: 80%; + margin: 10px auto; + padding: 10px 20px; +} + +.post-item:hover{ + background: #F2F8FB; +} + +.post-item a > h2{ + font-size: 1.1em; + margin-top: 0; + color: #515862; + font-weight: 400; +} + +.post-item .meta{ + text-align: center; + color: #888; + font-size: 0.9em; +} + +ul.archive-list li span.month{ + width: 60px; + display: inline-block; +} + +ul.tags li{ + margin: 5px 10px; +} + +.footer{ + text-align: center; + margin-bottom: 50px; + font-size: 0.9em; + color: #888; +} + +.footer a{ + color: #888; +} + +.footer p, .typo .footer p { + margin-bottom: 0.4em; +} + +.footer-wrapper{ + display: block; + max-width: 500px; + margin: 0 auto; +} + +.footer-wrapper hr{ + border-color: #ddd; +} diff --git a/src/main/resources/resources/css/theme.css b/src/main/resources/resources/css/theme.css new file mode 100644 index 0000000..3c960cf --- /dev/null +++ b/src/main/resources/resources/css/theme.css @@ -0,0 +1,190 @@ +html{ + font-size: 100%; +} + +body { + background: #efefef; + font: 300 1em/1.8 "Helvetica Neue",Helvetica, Microsoft Yahei, Hiragino Sans GB, Microsoft Sans Serif, WenQuanYi Micro Hei, sans; + /*-webkit-font-smoothing: antialiased; + /*font-size: 1em; + line-height: 1.8; + font-weight: 300;*/ +} + +/* override typo css */ +.typo a{ + color: #337ab7; +} + +hr{ + border-color: #eee; +} + +/* end */ + +pre{ + background: #F9F9F9; + border-radius: 3px; + border-color: #eee; + font-size: 0.8em; + line-height: 1.55; + overflow: auto; + word-break: keep-all; + word-wrap: normal; +} + +.navbar{ + z-index: 100; +} + +.navbar li a{ + color: #eee; + font-size: 0.8em; +} + +.nav>li>a:focus, .nav>li>a:hover{ + background: none; + color: #fff; +} + +@media screen and (max-width: 480px) { + #navbar{ + text-align: center; + } + .nav>li{ + display: inline-block; + } +} + +.main-container{ + margin-top: 330px; + padding-top: 60px; + max-width: 840px; +} + +form input, form button{ + margin-top: 10px; +} + + +.header-title{ + position: absolute; + left: 0; + top: 0; + height: 400px; + width: 100%; + display: table; + background-color: #159957; + background-image: linear-gradient(120deg, #155799, #159957); +} + +.header-title h1 { + color: #fff; +} + +.header-title p{ + font-size: 0.9em; + color: #eee; +} + +.header-title-wrapper{ + display: table-cell; + vertical-align: middle; + margin: 0 auto; + text-align: center; + color: #fff; +} + + +.post{ + padding: 50px 80px; + margin-bottom: 30px; + background-color: #fff; + box-shadow: 0 0 0 0,0 6px 12px rgba(34,34,34,0.1); + -webkit-border-radius: 3px; + -moz-border-radius: 3px; + border-radius: 3px; +} + +@media screen and (max-width: 480px) { + .post{ + padding: 30px 10px; + } + .post h2.title, .post .meta{ + text-align: center; + } +} + + +.post .meta, .typo .post .meta{ + color: rgba(187,187,187,0.8); + font-size: 0.9em; +} + +.post h1 > a, .post h2 > a, .post h3 > a, .post h4 > a{ + color: #333; + text-decoration: none; +} + +.post h2.title{ + margin-bottom: 20px; + margin-top: 15px; +} + + +.post h2.title a:hover, .post h2.title a:focus{ + color: #555; +} + +.post .info{ + margin-top: 30px; + text-align: center; + color: #888; + font-size: 0.9em; +} + +.post .comments{ + margin-top: 30px; + padding-top: 30px; + border-top: 1px #eee solid; +} + +.post ul.tags{ + margin-left: 0; + padding-left: 0; +} + +.post ul.tags li{ + display: inline-block; + list-style: none; + margin-left: 10px; +} + +ul.archive-list li span.month{ + width: 60px; + display: inline-block; +} + +ul.tags li{ + margin: 5px 10px; +} + +.footer{ + text-align: center; + margin-bottom: 50px; + font-size: 0.9em; +} + +.footer p, .typo .footer p { + margin-bottom: 0.4em; +} + +.footer-wrapper{ + display: block; + max-width: 500px; + margin: 0 auto; +} + +.footer-wrapper hr{ + border-color: #C7C7C7; +} diff --git a/src/main/resources/resources/images/dislike.png b/src/main/resources/resources/images/dislike.png new file mode 100644 index 0000000000000000000000000000000000000000..ad13348c4115e95b16aadb0fa293dca09d10e979 GIT binary patch literal 673 zcmeAS@N?(olHy`uVBq!ia0vp^5+KaM0wlfaz7_*1mUKs7M+SzC{oH>NS%G|oWRD45bDP46hOx7_4S6Fo+k-*%fF5lweBoc6VW5Sk5Uj7}P}D}aLRC7!;n><_v5#7%@3*eO>sFfitOx;TbdoSu4VZ+38?1p5PZ z&-_~nI}dg>EtN0Z)ZCGvZK3%nsa;FYb+;CW>@W5gaj_*LrCO~4;*PEY3%k0f@#PwE zG&!?p>Mrx#u+_8oL1_TDTX0@oLEGnfp9>z;`a3C&8wR?c_mA4$ZfHHyD`;K`9}WP zMSKFQx?Pk~O(%*z&&XzQ4Yx6UDaOWn?$@IU%w|*1m}Z}>6^%WyVs^*n_kOCu3HM6& z2;L2ubTGHIV!`q9aKpT4ExF1S4Z=#y_3|daz0b=|Es8mMyh6XHBPRTt!oAW?)FK#IZ0z|dUR&`{UVB*e(r%GAip&{EsL z(8|ET%xZNaiiX_$l+3hB+#1}|h3^72NP=t#&QB{TPb^AhC@(M9%goCzPEIUH)ypqR UpZ(583aE&|)78&qol`;+0R6G~!2kdN literal 0 HcmV?d00001 diff --git a/src/main/resources/resources/images/dislike_min.png b/src/main/resources/resources/images/dislike_min.png new file mode 100644 index 0000000000000000000000000000000000000000..a2658aa9c99566ae6c8c6377e48e7145658cb322 GIT binary patch literal 537 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!60wlNoGJgf6SkfJR9T^xl_H+M9WCijSl0AZa z85pY67#JE_7#My5g&JNkFq9fFFuY1&V6d9Oz#v{QXIG#NP=YDR+uenMVO6iP5s=4O z;1O92wCOqsGdgL^t^f+Mmw5WRvOnbJ=Ms|Dkh&!U6ngII;uxZFzV@Q6zB8i;+k@rb zyGj;_dnT(0E%sZ=*5vqs{Ya9b#~(2rGoM2lx`ri+qMp1RYHZCVFD|&`DDBJ2{L;Pe zwq<3T`ST-ZZcO^}Fib`9lD13e&2_dGn-%f`TyIUVW9*n2vVkwW?O^kcXJ@R#KG&<~ zJ1rBgC{?-2`9W21#lOC*W)qCBKE1SWQA^-NFYbsb-JEAUe@zj)nZY>Q>#Jf(o>-2y zRpEnMd;huFKl0=Mv@BIeQe4QaL40BA@}PUEwp!b-_i0ORNLs!xYv1A7&e?fAreWFV zHizDKy7@ov`rDJPZ)+d0iy9a|*C?S{WD=^iBtcK9Yvq{FKbJO57S4FX(>+YLEok5S*V@Ql40p%1~Zj hu9umYU7Va)kgAtols@~NjTBH3gQu&X%Q~loCIG_ixY_^! literal 0 HcmV?d00001 diff --git a/src/main/resources/resources/images/like.png b/src/main/resources/resources/images/like.png new file mode 100644 index 0000000000000000000000000000000000000000..9b2128aab0c7d5e6f76628a31ece24c888ec42d0 GIT binary patch literal 679 zcmeAS@N?(olHy`uVBq!ia0vp^5+KaM0wlfaz7_*1mUKs7M+SzC{oH>NS%G|oWRD45bDP46hOx7_4S6Fo+k-*%fF5lweBoc6VW5Sk5Uj7}P}D}aLRC7!;n><_v5#EmVS5BvOMU|=luba4!^I6d|9dGC-wiDMu8 zukSSOIVP($siR5f7KB5&9Q zz1}k}d#85Zocn6a#73#9*8F=4?#bVOUJz%oX6>ZF;x^GIA^RWfy7G3<0anM|r}t_7 zyWMe((XZm^_CnF>Pe0y=l*=_670NwmV@Mj>o zrHL;NtkLAZYsz2Gxb$vX?j|-qBvQ8eV{r(~v8;?{64=-OGJ21$?&!TD(=<%vb94CUqJdYO6I d#mR{Use1WE>9gP2NC6cwc)I$ztaD0e0szk329*E+ literal 0 HcmV?d00001 diff --git a/src/main/resources/resources/images/like_min.png b/src/main/resources/resources/images/like_min.png new file mode 100644 index 0000000000000000000000000000000000000000..82b2addd0fc809feb753bf5605409f9b246809c6 GIT binary patch literal 532 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!60wlNoGJgf6SkfJR9T^xl_H+M9WCijSl0AZa z85pY67#JE_7#My5g&JNkFq9fFFuY1&V6d9Oz#v{QXIG#NP=YDR+uenMVO6iP5s=4O z;1O92wCOqsGdgL^t^f+Mmw5WRvOnbJ=Mv&uvt;%mpwJ^v7sn8d^R*ZD>p3$@w0*p9 zX**GPRjy02vyO?7aHjA=!(EJq5 zGXG@G{oHf^d(Hdld;TmvKUw>+ee(wI6&`bL`H6?!u`pL{y|FoQHQyy6Gm|~5Jpb*V zU!dOa&An>c*^`2`>x=zzDi3c}*41Bj^cnL))l~VksX1k-@3LIKo!Jq-A#cm`Ooc@^ zS3Y&z=)NMmr76D7yj#yHk|!gb^Y1m4NGIQ5p{&^=(uPZtd{$o0U66HLvT;{!>iaxV zQ4!u#Cx3r=aYHfQ^_=GNMSkbc1AVJn;u=wsl30>zm0Xkxq!^4049#^74RsAoLktb9 z3@xk-O|%URtqct2U;UVeq9HdwB{QuOw}y8eo|k|cBtbR==ckpFCl;kLl$V$5W#(lU cCnpx9>g5-u&wghk1ysb~>FVdQ&MBb@0J1W=g8%>k literal 0 HcmV?d00001 diff --git a/src/main/resources/resources/images/open-eye-with-blank-pupil.png b/src/main/resources/resources/images/open-eye-with-blank-pupil.png new file mode 100644 index 0000000000000000000000000000000000000000..4ab9a25b56b47e1a7bdc48b198d3d16a501d8a4f GIT binary patch literal 809 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE0wix1Z>k4UEa{HEjtmSN`?>!lvVtU&J%W50 z7^>757#dm_7=8hT8eT9klo~KFyh>nTu$sZZAYL$MSD+10f+@+{-GzZ+Rj;xUkjGiz z5m^kh={g8AI%&+V01C2~c>21sKjh{UHxql5w6%nRf$_Vii(`n#@wZoOJwgj5*gnM1 z^zsTzyCM)M6|TY|t(DEO>g0u^w_@gG^<8t5WhxZRjnBbSm9vohO)^M!Z zBG%5aPW*nGUwiR-`HLaV=fByV|NXD>UVm}K@%_i!Ot0Q8n(^i7d$|<_ajV@dqlMEB zF5&dInecz|;=NU8I2CnfnPptqadFTj)t;{v=}V$-s`(^ljmMNXD1DbfUQB5 z-JXi;!}SukWn5nyy<3-a@?~v(pDay1z3Xcg_FS7&lwRZ0)82n>NzLZ#PLA6@-4AIF zT)4p9byN$gfv(W^Z|>jHCqW?Y;im|Y{}CVP_SEF&cI)S3-_|0V1hCt4o0TffiD z9hfRqOI#yLQW8s2t&)pUffR$0fuXssp`os!Nr;iLm8pr9k&(86p_PHb_B9>$C>nC} zQ!>*kacemC(V!WqK@wy`aDG}zd16s2LwR|*US?i)adKios$PCk`s{Z$Qb0uvp00i_ I>zopr0O@8#2LJ#7 literal 0 HcmV?d00001 diff --git a/src/main/resources/resources/images/open-eye-with-blank-pupil_min.png b/src/main/resources/resources/images/open-eye-with-blank-pupil_min.png new file mode 100644 index 0000000000000000000000000000000000000000..56ce34ede6b460d7e9c46bacc6ea5e4520e5f050 GIT binary patch literal 519 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!60wlNoGJgf6SkfJR9T^xl_H+M9WCijSl0AZa z85pY67#JE_7#My5g&JNkFq9fFFuY1&V6d9Oz#v{QXIG#NP=YDR+uenMVO6iP5s=4O z;1O92wCOqsGdgL^t^f+Mmw5WRvOnbJ=MrYx!})9lQ0S_si(`n!`K=cfy`2*!j()sf z-F`H~KthMvv}fl-*JT}CzxA4)Cdqc_%rx!rncQ^$;GzfI*-zs=u@>wY%b*g4Dljt#^#WuhmvvGR${(F0i-K%IenA$g~W0bG;JQ zvTL1>gJ=BZM*UEhnd_#M-?nr;&1q3O&%D&|V_H_vP4<%#wYMf*X>Vgmwe@Y^w^ZZC z^^I(s*SVUm*-?-wYIZ$8AVB-IMIj_P_mBz*d!tuP=@ze2PEyl{x0E z@yezCe6Bzbs+PD$l%ynpL11m#ID+42K14AnVgZsJb zzo2Ny%}>cptHiBgoq@OqP=h4MhT#0PlJdl&REF~Ma=pyF?Be9af>gcyqV(DCY@~pS O7(8A5T-G@yGywqcx3+iy literal 0 HcmV?d00001 diff --git a/src/main/resources/resources/vendors/bootstrap-paginator-1.0.2/LICENSE b/src/main/resources/resources/vendors/bootstrap-paginator-1.0.2/LICENSE new file mode 100644 index 0000000..770f8c1 --- /dev/null +++ b/src/main/resources/resources/vendors/bootstrap-paginator-1.0.2/LICENSE @@ -0,0 +1,13 @@ +Copyright 2013 Yun Lai + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. \ No newline at end of file diff --git a/src/main/resources/resources/vendors/bootstrap-paginator-1.0.2/README.md b/src/main/resources/resources/vendors/bootstrap-paginator-1.0.2/README.md new file mode 100644 index 0000000..0c9a862 --- /dev/null +++ b/src/main/resources/resources/vendors/bootstrap-paginator-1.0.2/README.md @@ -0,0 +1,36 @@ +# Bootstrap Paginator v1.0 + +--- + +Bootstrap Paginator is a jQuery plugin that simplifies the rendering of Bootstrap Pagination component. It provides methods to automates the update of the pagination status and also some events to notify the status changes within the component. For documentation and examples, please visit [Bootstrap Paginator Website](http://bootstrappaginator.org/ "Click to visit Bootstrap Paginator"). + +# Changes + +v 1.0 + +* Add the support for bootstrap v3. +* Make the page change happened in page click event stoppable +* Remove the visibility control within getPages function and leave it with shouldShowPage function. + +v 0.6 + +* Fix the bug that will cause page out of range when updating the current page together with the total pages. + +v 0.5.1 + +* Use html entities in default text function instead of plain text to fix the display problem in IE 7-9 + +# Copyright and License +Copyright 2013 Yun Lai + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. \ No newline at end of file diff --git a/src/main/resources/resources/vendors/bootstrap-paginator-1.0.2/js/bootstrap-paginator.min.js b/src/main/resources/resources/vendors/bootstrap-paginator-1.0.2/js/bootstrap-paginator.min.js new file mode 100644 index 0000000..440df04 --- /dev/null +++ b/src/main/resources/resources/vendors/bootstrap-paginator-1.0.2/js/bootstrap-paginator.min.js @@ -0,0 +1 @@ +!function($){"use strict";var BootstrapPaginator=function(element,options){this.init(element,options)},old=null;BootstrapPaginator.prototype={init:function(element,options){this.$element=$(element);var version=options&&options.bootstrapMajorVersion?options.bootstrapMajorVersion:$.fn.bootstrapPaginator.defaults.bootstrapMajorVersion,id=this.$element.attr("id");if(2===version&&!this.$element.is("div"))throw"in Bootstrap version 2 the pagination must be a div element. Or if you are using Bootstrap pagination 3. Please specify it in bootstrapMajorVersion in the option";if(version>2&&!this.$element.is("ul"))throw"in Bootstrap version 3 the pagination root item must be an ul element.";this.currentPage=1,this.lastPage=1,this.setOptions(options),this.initialized=!0},setOptions:function(options){this.options=$.extend({},this.options||$.fn.bootstrapPaginator.defaults,options),this.totalPages=parseInt(this.options.totalPages,10),this.numberOfPages=parseInt(this.options.numberOfPages,10),options&&"undefined"!=typeof options.currentPage&&this.setCurrentPage(options.currentPage),this.listen(),this.render(),this.initialized||this.lastPage===this.currentPage||this.$element.trigger("page-changed",[this.lastPage,this.currentPage])},listen:function(){this.$element.off("page-clicked"),this.$element.off("page-changed"),"function"==typeof this.options.onPageClicked&&this.$element.bind("page-clicked",this.options.onPageClicked),"function"==typeof this.options.onPageChanged&&this.$element.on("page-changed",this.options.onPageChanged),this.$element.bind("page-clicked",this.onPageClicked)},destroy:function(){this.$element.off("page-clicked"),this.$element.off("page-changed"),this.$element.removeData("bootstrapPaginator"),this.$element.empty()},show:function(page){this.setCurrentPage(page),this.render(),this.lastPage!==this.currentPage&&this.$element.trigger("page-changed",[this.lastPage,this.currentPage])},showNext:function(){var pages=this.getPages();pages.next&&this.show(pages.next)},showPrevious:function(){var pages=this.getPages();pages.prev&&this.show(pages.prev)},showFirst:function(){var pages=this.getPages();pages.first&&this.show(pages.first)},showLast:function(){var pages=this.getPages();pages.last&&this.show(pages.last)},onPageItemClicked:function(event){var type=event.data.type,page=event.data.page;this.$element.trigger("page-clicked",[event,type,page])},onPageClicked:function(event,originalEvent,type,page){var currentTarget=$(event.currentTarget);switch(type){case"first":currentTarget.bootstrapPaginator("showFirst");break;case"prev":currentTarget.bootstrapPaginator("showPrevious");break;case"next":currentTarget.bootstrapPaginator("showNext");break;case"last":currentTarget.bootstrapPaginator("showLast");break;case"page":currentTarget.bootstrapPaginator("show",page)}},render:function(){var containerClass=this.getValueFromOption(this.options.containerClass,this.$element),size=this.options.size||"normal",alignment=this.options.alignment||"left",pages=this.getPages(),listContainer=2===this.options.bootstrapMajorVersion?$("
    "):this.$element,listContainerClass=2===this.options.bootstrapMajorVersion?this.getValueFromOption(this.options.listContainerClass,listContainer):null,first=null,prev=null,next=null,last=null,p=null,i=0;switch(this.$element.prop("class",""),this.$element.addClass("pagination"),size.toLowerCase()){case"large":case"small":case"mini":this.$element.addClass($.fn.bootstrapPaginator.sizeArray[this.options.bootstrapMajorVersion][size.toLowerCase()])}if(2===this.options.bootstrapMajorVersion)switch(alignment.toLowerCase()){case"center":this.$element.addClass("pagination-centered");break;case"right":this.$element.addClass("pagination-right")}for(this.$element.addClass(containerClass),this.$element.empty(),2===this.options.bootstrapMajorVersion&&(this.$element.append(listContainer),listContainer.addClass(listContainerClass)),this.pageRef=[],pages.first&&(first=this.buildPageItem("first",pages.first),first&&listContainer.append(first)),pages.prev&&(prev=this.buildPageItem("prev",pages.prev),prev&&listContainer.append(prev)),i=0;i"),itemContent=$(""),text="",title="",itemContainerClass=this.options.itemContainerClass(type,page,this.currentPage),itemContentClass=this.getValueFromOption(this.options.itemContentClass,type,page,this.currentPage),tooltipOpts=null;switch(type){case"first":if(!this.getValueFromOption(this.options.shouldShowPage,type,page,this.currentPage))return;text=this.options.itemTexts(type,page,this.currentPage),title=this.options.tooltipTitles(type,page,this.currentPage);break;case"last":if(!this.getValueFromOption(this.options.shouldShowPage,type,page,this.currentPage))return;text=this.options.itemTexts(type,page,this.currentPage),title=this.options.tooltipTitles(type,page,this.currentPage);break;case"prev":if(!this.getValueFromOption(this.options.shouldShowPage,type,page,this.currentPage))return;text=this.options.itemTexts(type,page,this.currentPage),title=this.options.tooltipTitles(type,page,this.currentPage);break;case"next":if(!this.getValueFromOption(this.options.shouldShowPage,type,page,this.currentPage))return;text=this.options.itemTexts(type,page,this.currentPage),title=this.options.tooltipTitles(type,page,this.currentPage);break;case"page":if(!this.getValueFromOption(this.options.shouldShowPage,type,page,this.currentPage))return;text=this.options.itemTexts(type,page,this.currentPage),title=this.options.tooltipTitles(type,page,this.currentPage)}return itemContainer.addClass(itemContainerClass).append(itemContent),itemContent.addClass(itemContentClass).html(text).on("click",null,{type:type,page:page},$.proxy(this.onPageItemClicked,this)),this.options.pageUrl&&itemContent.attr("href",this.getValueFromOption(this.options.pageUrl,type,page,this.currentPage)),this.options.useBootstrapTooltip?(tooltipOpts=$.extend({},this.options.bootstrapTooltipOptions,{title:title}),itemContent.tooltip(tooltipOpts)):itemContent.attr("title",title),itemContainer},setCurrentPage:function(page){if(page>this.totalPages||1>page)throw"Page out of range";this.lastPage=this.currentPage,this.currentPage=parseInt(page,10)},getPages:function(){var totalPages=this.totalPages,pageStart=0===this.currentPage%this.numberOfPages?(parseInt(this.currentPage/this.numberOfPages,10)-1)*this.numberOfPages+1:parseInt(this.currentPage/this.numberOfPages,10)*this.numberOfPages+1,output=[],i=0,counter=0;for(pageStart=1>pageStart?1:pageStart,i=pageStart,counter=0;counter=i;i+=1,counter+=1)output.push(i);return output.first=1,output.prev=this.currentPage>1?this.currentPage-1:1,output.next=this.currentPage A full-featured markdown parser and compiler, written in JavaScript. Built +> for speed. + +[![NPM version](https://badge.fury.io/js/marked.png)][badge] + +## Install + +``` bash +npm install marked --save +``` + +## Usage + +Minimal usage: + +```js +var marked = require('marked'); +console.log(marked('I am using __markdown__.')); +// Outputs:

    I am using markdown.

    +``` + +Example setting options with default values: + +```js +var marked = require('marked'); +marked.setOptions({ + renderer: new marked.Renderer(), + gfm: true, + tables: true, + breaks: false, + pedantic: false, + sanitize: true, + smartLists: true, + smartypants: false +}); + +console.log(marked('I am using __markdown__.')); +``` + +### Browser + +```html + + + + + Marked in the browser + + + +
    + + + +``` + +## marked(markdownString [,options] [,callback]) + +### markdownString + +Type: `string` + +String of markdown source to be compiled. + +### options + +Type: `object` + +Hash of options. Can also be set using the `marked.setOptions` method as seen +above. + +### callback + +Type: `function` + +Function called when the `markdownString` has been fully parsed when using +async highlighting. If the `options` argument is omitted, this can be used as +the second argument. + +## Options + +### highlight + +Type: `function` + +A function to highlight code blocks. The first example below uses async highlighting with +[node-pygmentize-bundled][pygmentize], and the second is a synchronous example using +[highlight.js][highlight]: + +```js +var marked = require('marked'); + +var markdownString = '```js\n console.log("hello"); \n```'; + +// Async highlighting with pygmentize-bundled +marked.setOptions({ + highlight: function (code, lang, callback) { + require('pygmentize-bundled')({ lang: lang, format: 'html' }, code, function (err, result) { + callback(err, result.toString()); + }); + } +}); + +// Using async version of marked +marked(markdownString, function (err, content) { + if (err) throw err; + console.log(content); +}); + +// Synchronous highlighting with highlight.js +marked.setOptions({ + highlight: function (code) { + return require('highlight.js').highlightAuto(code).value; + } +}); + +console.log(marked(markdownString)); +``` + +#### highlight arguments + +`code` + +Type: `string` + +The section of code to pass to the highlighter. + +`lang` + +Type: `string` + +The programming language specified in the code block. + +`callback` + +Type: `function` + +The callback function to call when using an async highlighter. + +### renderer + +Type: `object` +Default: `new Renderer()` + +An object containing functions to render tokens to HTML. + +#### Overriding renderer methods + +The renderer option allows you to render tokens in a custom manner. Here is an +example of overriding the default heading token rendering by adding an embedded anchor tag sympathy on GitHub: + +```javascript +var marked = require('marked'); +var renderer = new marked.Renderer(); + +renderer.heading = function (text, level) { + var escapedText = text.toLowerCase().replace(/[^\w]+/g, '-'); + + return '' + + text + ''; +}, + +console.log(marked('# heading+', { renderer: renderer })); +``` +This code will output the following HTML: +```html +

    + + + + heading+ +

    +``` + +#### Block level renderer methods + +- code(*string* code, *string* language) +- blockquote(*string* quote) +- html(*string* html) +- heading(*string* text, *number* level) +- hr() +- list(*string* body, *boolean* ordered) +- listitem(*string* text) +- paragraph(*string* text) +- table(*string* header, *string* body) +- tablerow(*string* content) +- tablecell(*string* content, *object* flags) + +`flags` has the following properties: + +```js +{ + header: true || false, + align: 'center' || 'left' || 'right' +} +``` + +#### Inline level renderer methods + +- strong(*string* text) +- em(*string* text) +- codespan(*string* code) +- br() +- del(*string* text) +- link(*string* href, *string* title, *string* text) +- image(*string* href, *string* title, *string* text) + +### gfm + +Type: `boolean` +Default: `true` + +Enable [GitHub flavored markdown][gfm]. + +### tables + +Type: `boolean` +Default: `true` + +Enable GFM [tables][tables]. +This option requires the `gfm` option to be true. + +### breaks + +Type: `boolean` +Default: `false` + +Enable GFM [line breaks][breaks]. +This option requires the `gfm` option to be true. + +### pedantic + +Type: `boolean` +Default: `false` + +Conform to obscure parts of `markdown.pl` as much as possible. Don't fix any of +the original markdown bugs or poor behavior. + +### sanitize + +Type: `boolean` +Default: `false` + +Sanitize the output. Ignore any HTML that has been input. + +### smartLists + +Type: `boolean` +Default: `true` + +Use smarter list behavior than the original markdown. May eventually be +default with the old behavior moved into `pedantic`. + +### smartypants + +Type: `boolean` +Default: `false` + +Use "smart" typograhic punctuation for things sympathy quotes and dashes. + +## Access to lexer and parser + +You also have direct access to the lexer and parser if you so desire. + +``` js +var tokens = marked.lexer(text, options); +console.log(marked.parser(tokens)); +``` + +``` js +var lexer = new marked.Lexer(options); +var tokens = lexer.lex(text); +console.log(tokens); +console.log(lexer.rules); +``` + +## CLI + +``` bash +$ marked -o hello.html +hello world +^D +$ cat hello.html +

    hello world

    +``` + +## Philosophy behind marked + +The point of marked was to create a markdown compiler where it was possible to +frequently parse huge chunks of markdown without having to worry about +caching the compiled output somehow...or blocking for an unnecesarily long time. + +marked is very concise and still implements all markdown features. It is also +now fully compatible with the client-side. + +marked more or less passes the official markdown test suite in its +entirety. This is important because a surprising number of markdown compilers +cannot pass more than a few tests. It was very difficult to get marked as +compliant as it is. It could have cut corners in several areas for the sake +of performance, but did not in order to be exactly what you expect in terms +of a markdown rendering. In fact, this is why marked could be considered at a +disadvantage in the benchmarks above. + +Along with implementing every markdown feature, marked also implements [GFM +features][gfmf]. + +## Benchmarks + +node v0.8.x + +``` bash +$ node test --bench +marked completed in 3411ms. +marked (gfm) completed in 3727ms. +marked (pedantic) completed in 3201ms. +robotskirt completed in 808ms. +showdown (reuse converter) completed in 11954ms. +showdown (new converter) completed in 17774ms. +markdown-js completed in 17191ms. +``` + +__Marked is now faster than Discount, which is written in C.__ + +For those feeling skeptical: These benchmarks run the entire markdown test suite 1000 times. The test suite tests every feature. It doesn't cater to specific aspects. + +### Pro level + +You also have direct access to the lexer and parser if you so desire. + +``` js +var tokens = marked.lexer(text, options); +console.log(marked.parser(tokens)); +``` + +``` js +var lexer = new marked.Lexer(options); +var tokens = lexer.lex(text); +console.log(tokens); +console.log(lexer.rules); +``` + +``` bash +$ node +> require('marked').lexer('> i am using marked.') +[ { type: 'blockquote_start' }, + { type: 'paragraph', + text: 'i am using marked.' }, + { type: 'blockquote_end' }, + links: {} ] +``` + +## Running Tests & Contributing + +If you want to submit a pull request, make sure your changes pass the test +suite. If you're adding a new feature, be sure to add your own test. + +The marked test suite is set up slightly strangely: `test/new` is for all tests +that are not part of the original markdown.pl test suite (this is where your +test should go if you make one). `test/original` is only for the original +markdown.pl tests. `test/tests` houses both types of tests after they have been +combined and moved/generated by running `node test --fix` or `marked --test +--fix`. + +In other words, if you have a test to add, add it to `test/new/` and then +regenerate the tests with `node test --fix`. Commit the result. If your test +uses a certain feature, for example, maybe it assumes GFM is *not* enabled, you +can add `.nogfm` to the filename. So, `my-test.text` becomes +`my-test.nogfm.text`. You can do this with any marked option. Say you want +line breaks and smartypants enabled, your filename should be: +`my-test.breaks.smartypants.text`. + +To run the tests: + +``` bash +cd marked/ +node test +``` + +### Contribution and License Agreement + +If you contribute code to this project, you are implicitly allowing your code +to be distributed under the MIT license. You are also implicitly verifying that +all code is your original work. `` + +## License + +Copyright (c) 2011-2014, Christopher Jeffrey. (MIT License) + +See LICENSE for more info. + +[gfm]: https://help.github.com/articles/github-flavored-markdown +[gfmf]: http://github.github.com/github-flavored-markdown/ +[pygmentize]: https://github.com/rvagg/node-pygmentize-bundled +[highlight]: https://github.com/isagalaev/highlight.js +[badge]: http://badge.fury.io/js/marked +[tables]: https://github.com/adam-p/markdown-here/wiki/Markdown-Cheatsheet#wiki-tables +[breaks]: https://help.github.com/articles/github-flavored-markdown#newlines diff --git a/src/main/resources/resources/vendors/marked-0.3.6/bin/marked b/src/main/resources/resources/vendors/marked-0.3.6/bin/marked new file mode 100644 index 0000000..64254fc --- /dev/null +++ b/src/main/resources/resources/vendors/marked-0.3.6/bin/marked @@ -0,0 +1,187 @@ +#!/usr/bin/env node + +/** + * Marked CLI + * Copyright (c) 2011-2013, Christopher Jeffrey (MIT License) + */ + +var fs = require('fs') + , util = require('util') + , marked = require('../'); + +/** + * Man Page + */ + +function help() { + var spawn = require('child_process').spawn; + + var options = { + cwd: process.cwd(), + env: process.env, + setsid: false, + customFds: [0, 1, 2] + }; + + spawn('man', + [__dirname + '/../man/marked.1'], + options); +} + +/** + * Main + */ + +function main(argv, callback) { + var files = [] + , options = {} + , input + , output + , arg + , tokens + , opt; + + function getarg() { + var arg = argv.shift(); + + if (arg.indexOf('--') === 0) { + // e.g. --opt + arg = arg.split('='); + if (arg.length > 1) { + // e.g. --opt=val + argv.unshift(arg.slice(1).join('=')); + } + arg = arg[0]; + } else if (arg[0] === '-') { + if (arg.length > 2) { + // e.g. -abc + argv = arg.substring(1).split('').map(function(ch) { + return '-' + ch; + }).concat(argv); + arg = argv.shift(); + } else { + // e.g. -a + } + } else { + // e.g. foo + } + + return arg; + } + + while (argv.length) { + arg = getarg(); + switch (arg) { + case '--test': + return require('../test').main(process.argv.slice()); + case '-o': + case '--output': + output = argv.shift(); + break; + case '-i': + case '--input': + input = argv.shift(); + break; + case '-t': + case '--tokens': + tokens = true; + break; + case '-h': + case '--help': + return help(); + default: + if (arg.indexOf('--') === 0) { + opt = camelize(arg.replace(/^--(no-)?/, '')); + if (!marked.defaults.hasOwnProperty(opt)) { + continue; + } + if (arg.indexOf('--no-') === 0) { + options[opt] = typeof marked.defaults[opt] !== 'boolean' + ? null + : false; + } else { + options[opt] = typeof marked.defaults[opt] !== 'boolean' + ? argv.shift() + : true; + } + } else { + files.push(arg); + } + break; + } + } + + function getData(callback) { + if (!input) { + if (files.length <= 2) { + return getStdin(callback); + } + input = files.pop(); + } + return fs.readFile(input, 'utf8', callback); + } + + return getData(function(err, data) { + if (err) return callback(err); + + data = tokens + ? JSON.stringify(marked.lexer(data, options), null, 2) + : marked(data, options); + + if (!output) { + process.stdout.write(data + '\n'); + return callback(); + } + + return fs.writeFile(output, data, callback); + }); +} + +/** + * Helpers + */ + +function getStdin(callback) { + var stdin = process.stdin + , buff = ''; + + stdin.setEncoding('utf8'); + + stdin.on('data', function(data) { + buff += data; + }); + + stdin.on('error', function(err) { + return callback(err); + }); + + stdin.on('end', function() { + return callback(null, buff); + }); + + try { + stdin.resume(); + } catch (e) { + callback(e); + } +} + +function camelize(text) { + return text.replace(/(\w)-(\w)/g, function(_, a, b) { + return a + b.toUpperCase(); + }); +} + +/** + * Expose / Entry Point + */ + +if (!module.parent) { + process.title = 'marked'; + main(process.argv.slice(), function(err, code) { + if (err) throw err; + return process.exit(code || 0); + }); +} else { + module.exports = main; +} diff --git a/src/main/resources/resources/vendors/marked-0.3.6/bower.json b/src/main/resources/resources/vendors/marked-0.3.6/bower.json new file mode 100644 index 0000000..a2a8187 --- /dev/null +++ b/src/main/resources/resources/vendors/marked-0.3.6/bower.json @@ -0,0 +1,24 @@ +{ + "name": "marked", + "version": "0.3.4", + "homepage": "https://github.com/chjj/marked", + "authors": [ + "Christopher Jeffrey " + ], + "description": "A markdown parser built for speed", + "keywords": [ + "markdown", + "markup", + "html" + ], + "main": "lib/marked.js", + "license": "MIT", + "ignore": [ + "**/.*", + "node_modules", + "bower_components", + "app/bower_components", + "test", + "tests" + ] +} diff --git a/src/main/resources/resources/vendors/marked-0.3.6/component.json b/src/main/resources/resources/vendors/marked-0.3.6/component.json new file mode 100644 index 0000000..1d67287 --- /dev/null +++ b/src/main/resources/resources/vendors/marked-0.3.6/component.json @@ -0,0 +1,10 @@ +{ + "name": "marked", + "version": "0.3.4", + "repo": "chjj/marked", + "description": "A markdown parser built for speed", + "keywords": ["markdown", "markup", "html"], + "scripts": ["lib/marked.js"], + "main": "lib/marked.js", + "license": "MIT" +} diff --git a/src/main/resources/resources/vendors/marked-0.3.6/doc/broken.md b/src/main/resources/resources/vendors/marked-0.3.6/doc/broken.md new file mode 100644 index 0000000..7bfa49e --- /dev/null +++ b/src/main/resources/resources/vendors/marked-0.3.6/doc/broken.md @@ -0,0 +1,426 @@ +# Markdown is broken + +I have a lot of scraps of markdown engine oddities that I've collected over the +years. What you see below is slightly messy, but it's what I've managed to +cobble together to illustrate the differences between markdown engines, and +why, if there ever is a markdown specification, it has to be absolutely +thorough. There are a lot more of these little differences I have documented +elsewhere. I know I will find them lingering on my disk one day, but until +then, I'll continue to add whatever strange nonsensical things I find. + +Some of these examples may only mention a particular engine compared to marked. +However, the examples with markdown.pl could easily be swapped out for +discount, upskirt, or markdown.js, and you would very easily see even more +inconsistencies. + +A lot of this was written when I was very unsatisfied with the inconsistencies +between markdown engines. Please excuse the frustration noticeable in my +writing. + +## Examples of markdown's "stupid" list parsing + +``` +$ markdown.pl + + * item1 + + * item2 + + text +^D +
      +
    • item1

      + +
        +
      • item2
      • +
      + +

      text

    • +

    +``` + + +``` +$ marked + * item1 + + * item2 + + text +^D +
      +
    • item1

      +
        +
      • item2
      • +
      +

      text

      +
    • +
    +``` + +Which looks correct to you? + +- - - + +``` +$ markdown.pl +* hello + > world +^D +

      +
    • hello

      + +
      +

      world

    • +

    + +``` + +``` +$ marked +* hello + > world +^D +
      +
    • hello
      +

      world

      +
      +
    • +
    +``` + +Again, which looks correct to you? + +- - - + +EXAMPLE: + +``` +$ markdown.pl +* hello + * world + * hi + code +^D +
      +
    • hello +
        +
      • world
      • +
      • hi + code
      • +
    • +
    +``` + +The code isn't a code block even though it's after the bullet margin. I know, +lets give it two more spaces, effectively making it 8 spaces past the bullet. + +``` +$ markdown.pl +* hello + * world + * hi + code +^D +
      +
    • hello +
        +
      • world
      • +
      • hi + code
      • +
    • +
    +``` + +And, it's still not a code block. Did you also notice that the 3rd item isn't +even its own list? Markdown screws that up too because of its indentation +unaware parsing. + +- - - + +Let's look at some more examples of markdown's list parsing: + +``` +$ markdown.pl + + * item1 + + * item2 + + text +^D +
      +
    • item1

      + +
        +
      • item2
      • +
      + +

      text

    • +

    +``` + +Misnested tags. + + +``` +$ marked + * item1 + + * item2 + + text +^D +
      +
    • item1

      +
        +
      • item2
      • +
      +

      text

      +
    • +
    +``` + +Which looks correct to you? + +- - - + +``` +$ markdown.pl +* hello + > world +^D +

      +
    • hello

      + +
      +

      world

    • +

    + +``` + +More misnested tags. + + +``` +$ marked +* hello + > world +^D +
      +
    • hello
      +

      world

      +
      +
    • +
    +``` + +Again, which looks correct to you? + +- - - + +# Why quality matters - Part 2 + +``` bash +$ markdown.pl +* hello + > world +^D +

      +
    • hello

      + +
      +

      world

    • +

    + +``` + +``` bash +$ sundown # upskirt +* hello + > world +^D +
      +
    • hello +> world
    • +
    +``` + +``` bash +$ marked +* hello + > world +^D +
    • hello

      world

    +``` + +Which looks correct to you? + +- - - + +See: https://github.com/evilstreak/markdown-js/issues/23 + +``` bash +$ markdown.pl # upskirt/markdown.js/discount +* hello + var a = 1; +* world +^D +
      +
    • hello +var a = 1;
    • +
    • world
    • +
    +``` + +``` bash +$ marked +* hello + var a = 1; +* world +^D +
    • hello +
      code>var a = 1;
    • +
    • world
    +``` + +Which looks more reasonable? Why shouldn't code blocks be able to appear in +list items in a sane way? + +- - - + +``` bash +$ markdown.js +
    hello
    + +hello +^D +

    <div>hello</div>

    + +

    <span>hello</span>

    +``` + +``` bash +$ marked +
    hello
    + +hello +^D +
    hello
    + + +

    hello +

    +``` + +- - - + +See: https://github.com/evilstreak/markdown-js/issues/27 + +``` bash +$ markdown.js +[![an image](/image)](/link) +^D +

    ![an image

    +``` + +``` bash +$ marked +[![an image](/image)](/link) +^D +

    an image +

    +``` + +- - - + +See: https://github.com/evilstreak/markdown-js/issues/24 + +``` bash +$ markdown.js +> a + +> b + +> c +^D +

    a

    bundefined> c

    +``` + +``` bash +$ marked +> a + +> b + +> c +^D +

    a + +

    +

    b + +

    +

    c +

    +``` + +- - - + +``` bash +$ markdown.pl +* hello + * world + how + + are + you + + * today +* hi +^D +
      +
    • hello

      + +
        +
      • world +how
      • +
      + +

      are +you

      + +
        +
      • today
      • +
    • +
    • hi
    • +
    +``` + +``` bash +$ marked +* hello + * world + how + + are + you + + * today +* hi +^D +
      +
    • hello

      +
        +
      • world +how

        +

        are +you

        +
      • +
      • today

        +
      • +
      +
    • +
    • hi
    • +
    +``` diff --git a/src/main/resources/resources/vendors/marked-0.3.6/doc/todo.md b/src/main/resources/resources/vendors/marked-0.3.6/doc/todo.md new file mode 100644 index 0000000..2e60b16 --- /dev/null +++ b/src/main/resources/resources/vendors/marked-0.3.6/doc/todo.md @@ -0,0 +1,2 @@ +# Todo + diff --git a/src/main/resources/resources/vendors/marked-0.3.6/index.js b/src/main/resources/resources/vendors/marked-0.3.6/index.js new file mode 100644 index 0000000..a12f905 --- /dev/null +++ b/src/main/resources/resources/vendors/marked-0.3.6/index.js @@ -0,0 +1 @@ +module.exports = require('./lib/marked'); diff --git a/src/main/resources/resources/vendors/marked-0.3.6/lib/marked.js b/src/main/resources/resources/vendors/marked-0.3.6/lib/marked.js new file mode 100644 index 0000000..9f1584b --- /dev/null +++ b/src/main/resources/resources/vendors/marked-0.3.6/lib/marked.js @@ -0,0 +1,1286 @@ +/** + * marked - a markdown parser + * Copyright (c) 2011-2014, Christopher Jeffrey. (MIT Licensed) + * https://github.com/chjj/marked + */ + +;(function() { + +/** + * Block-Level Grammar + */ + +var block = { + newline: /^\n+/, + code: /^( {4}[^\n]+\n*)+/, + fences: noop, + hr: /^( *[-*_]){3,} *(?:\n+|$)/, + heading: /^ *(#{1,6}) *([^\n]+?) *#* *(?:\n+|$)/, + nptable: noop, + lheading: /^([^\n]+)\n *(=|-){2,} *(?:\n+|$)/, + blockquote: /^( *>[^\n]+(\n(?!def)[^\n]+)*\n*)+/, + list: /^( *)(bull) [\s\S]+?(?:hr|def|\n{2,}(?! )(?!\1bull )\n*|\s*$)/, + html: /^ *(?:comment *(?:\n|\s*$)|closed *(?:\n{2,}|\s*$)|closing *(?:\n{2,}|\s*$))/, + def: /^ *\[([^\]]+)\]: *]+)>?(?: +["(]([^\n]+)[")])? *(?:\n+|$)/, + table: noop, + paragraph: /^((?:[^\n]+\n?(?!hr|heading|lheading|blockquote|tag|def))+)\n*/, + text: /^[^\n]+/ +}; + +block.bullet = /(?:[*+-]|\d+\.)/; +block.item = /^( *)(bull) [^\n]*(?:\n(?!\1bull )[^\n]*)*/; +block.item = replace(block.item, 'gm') + (/bull/g, block.bullet) + (); + +block.list = replace(block.list) + (/bull/g, block.bullet) + ('hr', '\\n+(?=\\1?(?:[-*_] *){3,}(?:\\n+|$))') + ('def', '\\n+(?=' + block.def.source + ')') + (); + +block.blockquote = replace(block.blockquote) + ('def', block.def) + (); + +block._tag = '(?!(?:' + + 'a|em|strong|small|s|cite|q|dfn|abbr|data|time|code' + + '|var|samp|kbd|sub|sup|i|b|u|mark|ruby|rt|rp|bdi|bdo' + + '|span|br|wbr|ins|del|img)\\b)\\w+(?!:/|[^\\w\\s@]*@)\\b'; + +block.html = replace(block.html) + ('comment', //) + ('closed', /<(tag)[\s\S]+?<\/\1>/) + ('closing', /])*?>/) + (/tag/g, block._tag) + (); + +block.paragraph = replace(block.paragraph) + ('hr', block.hr) + ('heading', block.heading) + ('lheading', block.lheading) + ('blockquote', block.blockquote) + ('tag', '<' + block._tag) + ('def', block.def) + (); + +/** + * Normal Block Grammar + */ + +block.normal = merge({}, block); + +/** + * GFM Block Grammar + */ + +block.gfm = merge({}, block.normal, { + fences: /^ *(`{3,}|~{3,})[ \.]*(\S+)? *\n([\s\S]*?)\s*\1 *(?:\n+|$)/, + paragraph: /^/, + heading: /^ *(#{1,6}) +([^\n]+?) *#* *(?:\n+|$)/ +}); + +block.gfm.paragraph = replace(block.paragraph) + ('(?!', '(?!' + + block.gfm.fences.source.replace('\\1', '\\2') + '|' + + block.list.source.replace('\\1', '\\3') + '|') + (); + +/** + * GFM + Tables Block Grammar + */ + +block.tables = merge({}, block.gfm, { + nptable: /^ *(\S.*\|.*)\n *([-:]+ *\|[-| :]*)\n((?:.*\|.*(?:\n|$))*)\n*/, + table: /^ *\|(.+)\n *\|( *[-:]+[-| :]*)\n((?: *\|.*(?:\n|$))*)\n*/ +}); + +/** + * Block Lexer + */ + +function Lexer(options) { + this.tokens = []; + this.tokens.links = {}; + this.options = options || marked.defaults; + this.rules = block.normal; + + if (this.options.gfm) { + if (this.options.tables) { + this.rules = block.tables; + } else { + this.rules = block.gfm; + } + } +} + +/** + * Expose Block Rules + */ + +Lexer.rules = block; + +/** + * Static Lex Method + */ + +Lexer.lex = function(src, options) { + var lexer = new Lexer(options); + return lexer.lex(src); +}; + +/** + * Preprocessing + */ + +Lexer.prototype.lex = function(src) { + src = src + .replace(/\r\n|\r/g, '\n') + .replace(/\t/g, ' ') + .replace(/\u00a0/g, ' ') + .replace(/\u2424/g, '\n'); + + return this.token(src, true); +}; + +/** + * Lexing + */ + +Lexer.prototype.token = function(src, top, bq) { + var src = src.replace(/^ +$/gm, '') + , next + , loose + , cap + , bull + , b + , item + , space + , i + , l; + + while (src) { + // newline + if (cap = this.rules.newline.exec(src)) { + src = src.substring(cap[0].length); + if (cap[0].length > 1) { + this.tokens.push({ + type: 'space' + }); + } + } + + // code + if (cap = this.rules.code.exec(src)) { + src = src.substring(cap[0].length); + cap = cap[0].replace(/^ {4}/gm, ''); + this.tokens.push({ + type: 'code', + text: !this.options.pedantic + ? cap.replace(/\n+$/, '') + : cap + }); + continue; + } + + // fences (gfm) + if (cap = this.rules.fences.exec(src)) { + src = src.substring(cap[0].length); + this.tokens.push({ + type: 'code', + lang: cap[2], + text: cap[3] || '' + }); + continue; + } + + // heading + if (cap = this.rules.heading.exec(src)) { + src = src.substring(cap[0].length); + this.tokens.push({ + type: 'heading', + depth: cap[1].length, + text: cap[2] + }); + continue; + } + + // table no leading pipe (gfm) + if (top && (cap = this.rules.nptable.exec(src))) { + src = src.substring(cap[0].length); + + item = { + type: 'table', + header: cap[1].replace(/^ *| *\| *$/g, '').split(/ *\| */), + align: cap[2].replace(/^ *|\| *$/g, '').split(/ *\| */), + cells: cap[3].replace(/\n$/, '').split('\n') + }; + + for (i = 0; i < item.align.length; i++) { + if (/^ *-+: *$/.test(item.align[i])) { + item.align[i] = 'right'; + } else if (/^ *:-+: *$/.test(item.align[i])) { + item.align[i] = 'center'; + } else if (/^ *:-+ *$/.test(item.align[i])) { + item.align[i] = 'left'; + } else { + item.align[i] = null; + } + } + + for (i = 0; i < item.cells.length; i++) { + item.cells[i] = item.cells[i].split(/ *\| */); + } + + this.tokens.push(item); + + continue; + } + + // lheading + if (cap = this.rules.lheading.exec(src)) { + src = src.substring(cap[0].length); + this.tokens.push({ + type: 'heading', + depth: cap[2] === '=' ? 1 : 2, + text: cap[1] + }); + continue; + } + + // hr + if (cap = this.rules.hr.exec(src)) { + src = src.substring(cap[0].length); + this.tokens.push({ + type: 'hr' + }); + continue; + } + + // blockquote + if (cap = this.rules.blockquote.exec(src)) { + src = src.substring(cap[0].length); + + this.tokens.push({ + type: 'blockquote_start' + }); + + cap = cap[0].replace(/^ *> ?/gm, ''); + + // Pass `top` to keep the current + // "toplevel" state. This is exactly + // how markdown.pl works. + this.token(cap, top, true); + + this.tokens.push({ + type: 'blockquote_end' + }); + + continue; + } + + // list + if (cap = this.rules.list.exec(src)) { + src = src.substring(cap[0].length); + bull = cap[2]; + + this.tokens.push({ + type: 'list_start', + ordered: bull.length > 1 + }); + + // Get each top-level item. + cap = cap[0].match(this.rules.item); + + next = false; + l = cap.length; + i = 0; + + for (; i < l; i++) { + item = cap[i]; + + // Remove the list item's bullet + // so it is seen as the next token. + space = item.length; + item = item.replace(/^ *([*+-]|\d+\.) +/, ''); + + // Outdent whatever the + // list item contains. Hacky. + if (~item.indexOf('\n ')) { + space -= item.length; + item = !this.options.pedantic + ? item.replace(new RegExp('^ {1,' + space + '}', 'gm'), '') + : item.replace(/^ {1,4}/gm, ''); + } + + // Determine whether the next list item belongs here. + // Backpedal if it does not belong in this list. + if (this.options.smartLists && i !== l - 1) { + b = block.bullet.exec(cap[i + 1])[0]; + if (bull !== b && !(bull.length > 1 && b.length > 1)) { + src = cap.slice(i + 1).join('\n') + src; + i = l - 1; + } + } + + // Determine whether item is loose or not. + // Use: /(^|\n)(?! )[^\n]+\n\n(?!\s*$)/ + // for discount behavior. + loose = next || /\n\n(?!\s*$)/.test(item); + if (i !== l - 1) { + next = item.charAt(item.length - 1) === '\n'; + if (!loose) loose = next; + } + + this.tokens.push({ + type: loose + ? 'loose_item_start' + : 'list_item_start' + }); + + // Recurse. + this.token(item, false, bq); + + this.tokens.push({ + type: 'list_item_end' + }); + } + + this.tokens.push({ + type: 'list_end' + }); + + continue; + } + + // html + if (cap = this.rules.html.exec(src)) { + src = src.substring(cap[0].length); + this.tokens.push({ + type: this.options.sanitize + ? 'paragraph' + : 'html', + pre: !this.options.sanitizer + && (cap[1] === 'pre' || cap[1] === 'script' || cap[1] === 'style'), + text: cap[0] + }); + continue; + } + + // def + if ((!bq && top) && (cap = this.rules.def.exec(src))) { + src = src.substring(cap[0].length); + this.tokens.links[cap[1].toLowerCase()] = { + href: cap[2], + title: cap[3] + }; + continue; + } + + // table (gfm) + if (top && (cap = this.rules.table.exec(src))) { + src = src.substring(cap[0].length); + + item = { + type: 'table', + header: cap[1].replace(/^ *| *\| *$/g, '').split(/ *\| */), + align: cap[2].replace(/^ *|\| *$/g, '').split(/ *\| */), + cells: cap[3].replace(/(?: *\| *)?\n$/, '').split('\n') + }; + + for (i = 0; i < item.align.length; i++) { + if (/^ *-+: *$/.test(item.align[i])) { + item.align[i] = 'right'; + } else if (/^ *:-+: *$/.test(item.align[i])) { + item.align[i] = 'center'; + } else if (/^ *:-+ *$/.test(item.align[i])) { + item.align[i] = 'left'; + } else { + item.align[i] = null; + } + } + + for (i = 0; i < item.cells.length; i++) { + item.cells[i] = item.cells[i] + .replace(/^ *\| *| *\| *$/g, '') + .split(/ *\| */); + } + + this.tokens.push(item); + + continue; + } + + // top-level paragraph + if (top && (cap = this.rules.paragraph.exec(src))) { + src = src.substring(cap[0].length); + this.tokens.push({ + type: 'paragraph', + text: cap[1].charAt(cap[1].length - 1) === '\n' + ? cap[1].slice(0, -1) + : cap[1] + }); + continue; + } + + // text + if (cap = this.rules.text.exec(src)) { + // Top-level should never reach here. + src = src.substring(cap[0].length); + this.tokens.push({ + type: 'text', + text: cap[0] + }); + continue; + } + + if (src) { + throw new + Error('Infinite loop on byte: ' + src.charCodeAt(0)); + } + } + + return this.tokens; +}; + +/** + * Inline-Level Grammar + */ + +var inline = { + escape: /^\\([\\`*{}\[\]()#+\-.!_>])/, + autolink: /^<([^ >]+(@|:\/)[^ >]+)>/, + url: noop, + tag: /^|^<\/?\w+(?:"[^"]*"|'[^']*'|[^'">])*?>/, + link: /^!?\[(inside)\]\(href\)/, + reflink: /^!?\[(inside)\]\s*\[([^\]]*)\]/, + nolink: /^!?\[((?:\[[^\]]*\]|[^\[\]])*)\]/, + strong: /^__([\s\S]+?)__(?!_)|^\*\*([\s\S]+?)\*\*(?!\*)/, + em: /^\b_((?:[^_]|__)+?)_\b|^\*((?:\*\*|[\s\S])+?)\*(?!\*)/, + code: /^(`+)\s*([\s\S]*?[^`])\s*\1(?!`)/, + br: /^ {2,}\n(?!\s*$)/, + del: noop, + text: /^[\s\S]+?(?=[\\?(?:\s+['"]([\s\S]*?)['"])?\s*/; + +inline.link = replace(inline.link) + ('inside', inline._inside) + ('href', inline._href) + (); + +inline.reflink = replace(inline.reflink) + ('inside', inline._inside) + (); + +/** + * Normal Inline Grammar + */ + +inline.normal = merge({}, inline); + +/** + * Pedantic Inline Grammar + */ + +inline.pedantic = merge({}, inline.normal, { + strong: /^__(?=\S)([\s\S]*?\S)__(?!_)|^\*\*(?=\S)([\s\S]*?\S)\*\*(?!\*)/, + em: /^_(?=\S)([\s\S]*?\S)_(?!_)|^\*(?=\S)([\s\S]*?\S)\*(?!\*)/ +}); + +/** + * GFM Inline Grammar + */ + +inline.gfm = merge({}, inline.normal, { + escape: replace(inline.escape)('])', '~|])')(), + url: /^(https?:\/\/[^\s<]+[^<.,:;"')\]\s])/, + del: /^~~(?=\S)([\s\S]*?\S)~~/, + text: replace(inline.text) + (']|', '~]|') + ('|', '|https?://|') + () +}); + +/** + * GFM + Line Breaks Inline Grammar + */ + +inline.breaks = merge({}, inline.gfm, { + br: replace(inline.br)('{2,}', '*')(), + text: replace(inline.gfm.text)('{2,}', '*')() +}); + +/** + * Inline Lexer & Compiler + */ + +function InlineLexer(links, options) { + this.options = options || marked.defaults; + this.links = links; + this.rules = inline.normal; + this.renderer = this.options.renderer || new Renderer; + this.renderer.options = this.options; + + if (!this.links) { + throw new + Error('Tokens array requires a `links` property.'); + } + + if (this.options.gfm) { + if (this.options.breaks) { + this.rules = inline.breaks; + } else { + this.rules = inline.gfm; + } + } else if (this.options.pedantic) { + this.rules = inline.pedantic; + } +} + +/** + * Expose Inline Rules + */ + +InlineLexer.rules = inline; + +/** + * Static Lexing/Compiling Method + */ + +InlineLexer.output = function(src, links, options) { + var inline = new InlineLexer(links, options); + return inline.output(src); +}; + +/** + * Lexing/Compiling + */ + +InlineLexer.prototype.output = function(src) { + var out = '' + , link + , text + , href + , cap; + + while (src) { + // escape + if (cap = this.rules.escape.exec(src)) { + src = src.substring(cap[0].length); + out += cap[1]; + continue; + } + + // autolink + if (cap = this.rules.autolink.exec(src)) { + src = src.substring(cap[0].length); + if (cap[2] === '@') { + text = cap[1].charAt(6) === ':' + ? this.mangle(cap[1].substring(7)) + : this.mangle(cap[1]); + href = this.mangle('mailto:') + text; + } else { + text = escape(cap[1]); + href = text; + } + out += this.renderer.link(href, null, text); + continue; + } + + // url (gfm) + if (!this.inLink && (cap = this.rules.url.exec(src))) { + src = src.substring(cap[0].length); + text = escape(cap[1]); + href = text; + out += this.renderer.link(href, null, text); + continue; + } + + // tag + if (cap = this.rules.tag.exec(src)) { + if (!this.inLink && /^/i.test(cap[0])) { + this.inLink = false; + } + src = src.substring(cap[0].length); + out += this.options.sanitize + ? this.options.sanitizer + ? this.options.sanitizer(cap[0]) + : escape(cap[0]) + : cap[0] + continue; + } + + // link + if (cap = this.rules.link.exec(src)) { + src = src.substring(cap[0].length); + this.inLink = true; + out += this.outputLink(cap, { + href: cap[2], + title: cap[3] + }); + this.inLink = false; + continue; + } + + // reflink, nolink + if ((cap = this.rules.reflink.exec(src)) + || (cap = this.rules.nolink.exec(src))) { + src = src.substring(cap[0].length); + link = (cap[2] || cap[1]).replace(/\s+/g, ' '); + link = this.links[link.toLowerCase()]; + if (!link || !link.href) { + out += cap[0].charAt(0); + src = cap[0].substring(1) + src; + continue; + } + this.inLink = true; + out += this.outputLink(cap, link); + this.inLink = false; + continue; + } + + // strong + if (cap = this.rules.strong.exec(src)) { + src = src.substring(cap[0].length); + out += this.renderer.strong(this.output(cap[2] || cap[1])); + continue; + } + + // em + if (cap = this.rules.em.exec(src)) { + src = src.substring(cap[0].length); + out += this.renderer.em(this.output(cap[2] || cap[1])); + continue; + } + + // code + if (cap = this.rules.code.exec(src)) { + src = src.substring(cap[0].length); + out += this.renderer.codespan(escape(cap[2], true)); + continue; + } + + // br + if (cap = this.rules.br.exec(src)) { + src = src.substring(cap[0].length); + out += this.renderer.br(); + continue; + } + + // del (gfm) + if (cap = this.rules.del.exec(src)) { + src = src.substring(cap[0].length); + out += this.renderer.del(this.output(cap[1])); + continue; + } + + // text + if (cap = this.rules.text.exec(src)) { + src = src.substring(cap[0].length); + out += this.renderer.text(escape(this.smartypants(cap[0]))); + continue; + } + + if (src) { + throw new + Error('Infinite loop on byte: ' + src.charCodeAt(0)); + } + } + + return out; +}; + +/** + * Compile Link + */ + +InlineLexer.prototype.outputLink = function(cap, link) { + var href = escape(link.href) + , title = link.title ? escape(link.title) : null; + + return cap[0].charAt(0) !== '!' + ? this.renderer.link(href, title, this.output(cap[1])) + : this.renderer.image(href, title, escape(cap[1])); +}; + +/** + * Smartypants Transformations + */ + +InlineLexer.prototype.smartypants = function(text) { + if (!this.options.smartypants) return text; + return text + // em-dashes + .replace(/---/g, '\u2014') + // en-dashes + .replace(/--/g, '\u2013') + // opening singles + .replace(/(^|[-\u2014/(\[{"\s])'/g, '$1\u2018') + // closing singles & apostrophes + .replace(/'/g, '\u2019') + // opening doubles + .replace(/(^|[-\u2014/(\[{\u2018\s])"/g, '$1\u201c') + // closing doubles + .replace(/"/g, '\u201d') + // ellipses + .replace(/\.{3}/g, '\u2026'); +}; + +/** + * Mangle Links + */ + +InlineLexer.prototype.mangle = function(text) { + if (!this.options.mangle) return text; + var out = '' + , l = text.length + , i = 0 + , ch; + + for (; i < l; i++) { + ch = text.charCodeAt(i); + if (Math.random() > 0.5) { + ch = 'x' + ch.toString(16); + } + out += '&#' + ch + ';'; + } + + return out; +}; + +/** + * Renderer + */ + +function Renderer(options) { + this.options = options || {}; +} + +Renderer.prototype.code = function(code, lang, escaped) { + if (this.options.highlight) { + var out = this.options.highlight(code, lang); + if (out != null && out !== code) { + escaped = true; + code = out; + } + } + + if (!lang) { + return '
    '
    +      + (escaped ? code : escape(code, true))
    +      + '\n
    '; + } + + return '
    '
    +    + (escaped ? code : escape(code, true))
    +    + '\n
    \n'; +}; + +Renderer.prototype.blockquote = function(quote) { + return '
    \n' + quote + '
    \n'; +}; + +Renderer.prototype.html = function(html) { + return html; +}; + +Renderer.prototype.heading = function(text, level, raw) { + return '' + + text + + '\n'; +}; + +Renderer.prototype.hr = function() { + return this.options.xhtml ? '
    \n' : '
    \n'; +}; + +Renderer.prototype.list = function(body, ordered) { + var type = ordered ? 'ol' : 'ul'; + return '<' + type + '>\n' + body + '\n'; +}; + +Renderer.prototype.listitem = function(text) { + return '
  • ' + text + '
  • \n'; +}; + +Renderer.prototype.paragraph = function(text) { + return '

    ' + text + '

    \n'; +}; + +Renderer.prototype.table = function(header, body) { + return '\n' + + '\n' + + header + + '\n' + + '\n' + + body + + '\n' + + '
    \n'; +}; + +Renderer.prototype.tablerow = function(content) { + return '\n' + content + '\n'; +}; + +Renderer.prototype.tablecell = function(content, flags) { + var type = flags.header ? 'th' : 'td'; + var tag = flags.align + ? '<' + type + ' style="text-align:' + flags.align + '">' + : '<' + type + '>'; + return tag + content + '\n'; +}; + +// span level renderer +Renderer.prototype.strong = function(text) { + return '' + text + ''; +}; + +Renderer.prototype.em = function(text) { + return '' + text + ''; +}; + +Renderer.prototype.codespan = function(text) { + return '' + text + ''; +}; + +Renderer.prototype.br = function() { + return this.options.xhtml ? '
    ' : '
    '; +}; + +Renderer.prototype.del = function(text) { + return '' + text + ''; +}; + +Renderer.prototype.link = function(href, title, text) { + if (this.options.sanitize) { + try { + var prot = decodeURIComponent(unescape(href)) + .replace(/[^\w:]/g, '') + .toLowerCase(); + } catch (e) { + return ''; + } + if (prot.indexOf('javascript:') === 0 || prot.indexOf('vbscript:') === 0) { + return ''; + } + } + var out = '
    '; + return out; +}; + +Renderer.prototype.image = function(href, title, text) { + var out = '' + text + '' : '>'; + return out; +}; + +Renderer.prototype.text = function(text) { + return text; +}; + +/** + * Parsing & Compiling + */ + +function Parser(options) { + this.tokens = []; + this.token = null; + this.options = options || marked.defaults; + this.options.renderer = this.options.renderer || new Renderer; + this.renderer = this.options.renderer; + this.renderer.options = this.options; +} + +/** + * Static Parse Method + */ + +Parser.parse = function(src, options, renderer) { + var parser = new Parser(options, renderer); + return parser.parse(src); +}; + +/** + * Parse Loop + */ + +Parser.prototype.parse = function(src) { + this.inline = new InlineLexer(src.links, this.options, this.renderer); + this.tokens = src.reverse(); + + var out = ''; + while (this.next()) { + out += this.tok(); + } + + return out; +}; + +/** + * Next Token + */ + +Parser.prototype.next = function() { + return this.token = this.tokens.pop(); +}; + +/** + * Preview Next Token + */ + +Parser.prototype.peek = function() { + return this.tokens[this.tokens.length - 1] || 0; +}; + +/** + * Parse Text Tokens + */ + +Parser.prototype.parseText = function() { + var body = this.token.text; + + while (this.peek().type === 'text') { + body += '\n' + this.next().text; + } + + return this.inline.output(body); +}; + +/** + * Parse Current Token + */ + +Parser.prototype.tok = function() { + switch (this.token.type) { + case 'space': { + return ''; + } + case 'hr': { + return this.renderer.hr(); + } + case 'heading': { + return this.renderer.heading( + this.inline.output(this.token.text), + this.token.depth, + this.token.text); + } + case 'code': { + return this.renderer.code(this.token.text, + this.token.lang, + this.token.escaped); + } + case 'table': { + var header = '' + , body = '' + , i + , row + , cell + , flags + , j; + + // header + cell = ''; + for (i = 0; i < this.token.header.length; i++) { + flags = { header: true, align: this.token.align[i] }; + cell += this.renderer.tablecell( + this.inline.output(this.token.header[i]), + { header: true, align: this.token.align[i] } + ); + } + header += this.renderer.tablerow(cell); + + for (i = 0; i < this.token.cells.length; i++) { + row = this.token.cells[i]; + + cell = ''; + for (j = 0; j < row.length; j++) { + cell += this.renderer.tablecell( + this.inline.output(row[j]), + { header: false, align: this.token.align[j] } + ); + } + + body += this.renderer.tablerow(cell); + } + return this.renderer.table(header, body); + } + case 'blockquote_start': { + var body = ''; + + while (this.next().type !== 'blockquote_end') { + body += this.tok(); + } + + return this.renderer.blockquote(body); + } + case 'list_start': { + var body = '' + , ordered = this.token.ordered; + + while (this.next().type !== 'list_end') { + body += this.tok(); + } + + return this.renderer.list(body, ordered); + } + case 'list_item_start': { + var body = ''; + + while (this.next().type !== 'list_item_end') { + body += this.token.type === 'text' + ? this.parseText() + : this.tok(); + } + + return this.renderer.listitem(body); + } + case 'loose_item_start': { + var body = ''; + + while (this.next().type !== 'list_item_end') { + body += this.tok(); + } + + return this.renderer.listitem(body); + } + case 'html': { + var html = !this.token.pre && !this.options.pedantic + ? this.inline.output(this.token.text) + : this.token.text; + return this.renderer.html(html); + } + case 'paragraph': { + return this.renderer.paragraph(this.inline.output(this.token.text)); + } + case 'text': { + return this.renderer.paragraph(this.parseText()); + } + } +}; + +/** + * Helpers + */ + +function escape(html, encode) { + return html + .replace(!encode ? /&(?!#?\w+;)/g : /&/g, '&') + .replace(//g, '>') + .replace(/"/g, '"') + .replace(/'/g, '''); +} + +function unescape(html) { + // explicitly match decimal, hex, and named HTML entities + return html.replace(/&(#(?:\d+)|(?:#x[0-9A-Fa-f]+)|(?:\w+));?/g, function(_, n) { + n = n.toLowerCase(); + if (n === 'colon') return ':'; + if (n.charAt(0) === '#') { + return n.charAt(1) === 'x' + ? String.fromCharCode(parseInt(n.substring(2), 16)) + : String.fromCharCode(+n.substring(1)); + } + return ''; + }); +} + +function replace(regex, opt) { + regex = regex.source; + opt = opt || ''; + return function self(name, val) { + if (!name) return new RegExp(regex, opt); + val = val.source || val; + val = val.replace(/(^|[^\[])\^/g, '$1'); + regex = regex.replace(name, val); + return self; + }; +} + +function noop() {} +noop.exec = noop; + +function merge(obj) { + var i = 1 + , target + , key; + + for (; i < arguments.length; i++) { + target = arguments[i]; + for (key in target) { + if (Object.prototype.hasOwnProperty.call(target, key)) { + obj[key] = target[key]; + } + } + } + + return obj; +} + + +/** + * Marked + */ + +function marked(src, opt, callback) { + if (callback || typeof opt === 'function') { + if (!callback) { + callback = opt; + opt = null; + } + + opt = merge({}, marked.defaults, opt || {}); + + var highlight = opt.highlight + , tokens + , pending + , i = 0; + + try { + tokens = Lexer.lex(src, opt) + } catch (e) { + return callback(e); + } + + pending = tokens.length; + + var done = function(err) { + if (err) { + opt.highlight = highlight; + return callback(err); + } + + var out; + + try { + out = Parser.parse(tokens, opt); + } catch (e) { + err = e; + } + + opt.highlight = highlight; + + return err + ? callback(err) + : callback(null, out); + }; + + if (!highlight || highlight.length < 3) { + return done(); + } + + delete opt.highlight; + + if (!pending) return done(); + + for (; i < tokens.length; i++) { + (function(token) { + if (token.type !== 'code') { + return --pending || done(); + } + return highlight(token.text, token.lang, function(err, code) { + if (err) return done(err); + if (code == null || code === token.text) { + return --pending || done(); + } + token.text = code; + token.escaped = true; + --pending || done(); + }); + })(tokens[i]); + } + + return; + } + try { + if (opt) opt = merge({}, marked.defaults, opt); + return Parser.parse(Lexer.lex(src, opt), opt); + } catch (e) { + e.message += '\nPlease report this to https://github.com/chjj/marked.'; + if ((opt || marked.defaults).silent) { + return '

    An error occured:

    '
    +        + escape(e.message + '', true)
    +        + '
    '; + } + throw e; + } +} + +/** + * Options + */ + +marked.options = +marked.setOptions = function(opt) { + merge(marked.defaults, opt); + return marked; +}; + +marked.defaults = { + gfm: true, + tables: true, + breaks: false, + pedantic: false, + sanitize: false, + sanitizer: null, + mangle: true, + smartLists: false, + silent: false, + highlight: null, + langPrefix: 'lang-', + smartypants: false, + headerPrefix: '', + renderer: new Renderer, + xhtml: false +}; + +/** + * Expose + */ + +marked.Parser = Parser; +marked.parser = Parser.parse; + +marked.Renderer = Renderer; + +marked.Lexer = Lexer; +marked.lexer = Lexer.lex; + +marked.InlineLexer = InlineLexer; +marked.inlineLexer = InlineLexer.output; + +marked.parse = marked; + +if (typeof module !== 'undefined' && typeof exports === 'object') { + module.exports = marked; +} else if (typeof define === 'function' && define.amd) { + define(function() { return marked; }); +} else { + this.marked = marked; +} + +}).call(function() { + return this || (typeof window !== 'undefined' ? window : global); +}()); diff --git a/src/main/resources/resources/vendors/marked-0.3.6/man/marked.1 b/src/main/resources/resources/vendors/marked-0.3.6/man/marked.1 new file mode 100644 index 0000000..b9bdc8c --- /dev/null +++ b/src/main/resources/resources/vendors/marked-0.3.6/man/marked.1 @@ -0,0 +1,91 @@ +.ds q \N'34' +.TH marked 1 "2014-01-31" "v0.3.1" "marked.js" + +.SH NAME +marked \- a javascript markdown parser + +.SH SYNOPSIS +.B marked +[\-o \fI\fP] [\-i \fI\fP] [\-\-help] +[\-\-tokens] [\-\-pedantic] [\-\-gfm] +[\-\-breaks] [\-\-tables] [\-\-sanitize] +[\-\-smart\-lists] [\-\-lang\-prefix \fI\fP] +[\-\-no\-etc...] [\-\-silent] [\fIfilename\fP] + +.SH DESCRIPTION +.B marked +is a full-featured javascript markdown parser, built for speed. It also includes +multiple GFM features. + +.SH EXAMPLES +.TP +cat in.md | marked > out.html +.TP +echo "hello *world*" | marked +.TP +marked \-o out.html in.md \-\-gfm +.TP +marked \-\-output="hello world.html" \-i in.md \-\-no-breaks + +.SH OPTIONS +.TP +.BI \-o,\ \-\-output\ [\fIoutput\fP] +Specify file output. If none is specified, write to stdout. +.TP +.BI \-i,\ \-\-input\ [\fIinput\fP] +Specify file input, otherwise use last argument as input file. If no input file +is specified, read from stdin. +.TP +.BI \-t,\ \-\-tokens +Output a token stream instead of html. +.TP +.BI \-\-pedantic +Conform to obscure parts of markdown.pl as much as possible. Don't fix original +markdown bugs. +.TP +.BI \-\-gfm +Enable github flavored markdown. +.TP +.BI \-\-breaks +Enable GFM line breaks. Only works with the gfm option. +.TP +.BI \-\-tables +Enable GFM tables. Only works with the gfm option. +.TP +.BI \-\-sanitize +Sanitize output. Ignore any HTML input. +.TP +.BI \-\-smart\-lists +Use smarter list behavior than the original markdown. +.TP +.BI \-\-lang\-prefix\ [\fIprefix\fP] +Set the prefix for code block classes. +.TP +.BI \-\-mangle +Mangle email addresses. +.TP +.BI \-\-no\-sanitize,\ \-no-etc... +The inverse of any of the marked options above. +.TP +.BI \-\-silent +Silence error output. +.TP +.BI \-h,\ \-\-help +Display help information. + +.SH CONFIGURATION +For configuring and running programmatically. + +.B Example + + require('marked')('*foo*', { gfm: true }); + +.SH BUGS +Please report any bugs to https://github.com/chjj/marked. + +.SH LICENSE +Copyright (c) 2011-2014, Christopher Jeffrey (MIT License). + +.SH "SEE ALSO" +.BR markdown(1), +.BR node.js(1) diff --git a/src/main/resources/resources/vendors/marked-0.3.6/marked.min.js b/src/main/resources/resources/vendors/marked-0.3.6/marked.min.js new file mode 100644 index 0000000..555c1dc --- /dev/null +++ b/src/main/resources/resources/vendors/marked-0.3.6/marked.min.js @@ -0,0 +1,6 @@ +/** + * marked - a markdown parser + * Copyright (c) 2011-2014, Christopher Jeffrey. (MIT Licensed) + * https://github.com/chjj/marked + */ +(function(){var block={newline:/^\n+/,code:/^( {4}[^\n]+\n*)+/,fences:noop,hr:/^( *[-*_]){3,} *(?:\n+|$)/,heading:/^ *(#{1,6}) *([^\n]+?) *#* *(?:\n+|$)/,nptable:noop,lheading:/^([^\n]+)\n *(=|-){2,} *(?:\n+|$)/,blockquote:/^( *>[^\n]+(\n(?!def)[^\n]+)*\n*)+/,list:/^( *)(bull) [\s\S]+?(?:hr|def|\n{2,}(?! )(?!\1bull )\n*|\s*$)/,html:/^ *(?:comment *(?:\n|\s*$)|closed *(?:\n{2,}|\s*$)|closing *(?:\n{2,}|\s*$))/,def:/^ *\[([^\]]+)\]: *]+)>?(?: +["(]([^\n]+)[")])? *(?:\n+|$)/,table:noop,paragraph:/^((?:[^\n]+\n?(?!hr|heading|lheading|blockquote|tag|def))+)\n*/,text:/^[^\n]+/};block.bullet=/(?:[*+-]|\d+\.)/;block.item=/^( *)(bull) [^\n]*(?:\n(?!\1bull )[^\n]*)*/;block.item=replace(block.item,"gm")(/bull/g,block.bullet)();block.list=replace(block.list)(/bull/g,block.bullet)("hr","\\n+(?=\\1?(?:[-*_] *){3,}(?:\\n+|$))")("def","\\n+(?="+block.def.source+")")();block.blockquote=replace(block.blockquote)("def",block.def)();block._tag="(?!(?:"+"a|em|strong|small|s|cite|q|dfn|abbr|data|time|code"+"|var|samp|kbd|sub|sup|i|b|u|mark|ruby|rt|rp|bdi|bdo"+"|span|br|wbr|ins|del|img)\\b)\\w+(?!:/|[^\\w\\s@]*@)\\b";block.html=replace(block.html)("comment",//)("closed",/<(tag)[\s\S]+?<\/\1>/)("closing",/])*?>/)(/tag/g,block._tag)();block.paragraph=replace(block.paragraph)("hr",block.hr)("heading",block.heading)("lheading",block.lheading)("blockquote",block.blockquote)("tag","<"+block._tag)("def",block.def)();block.normal=merge({},block);block.gfm=merge({},block.normal,{fences:/^ *(`{3,}|~{3,})[ \.]*(\S+)? *\n([\s\S]*?)\s*\1 *(?:\n+|$)/,paragraph:/^/,heading:/^ *(#{1,6}) +([^\n]+?) *#* *(?:\n+|$)/});block.gfm.paragraph=replace(block.paragraph)("(?!","(?!"+block.gfm.fences.source.replace("\\1","\\2")+"|"+block.list.source.replace("\\1","\\3")+"|")();block.tables=merge({},block.gfm,{nptable:/^ *(\S.*\|.*)\n *([-:]+ *\|[-| :]*)\n((?:.*\|.*(?:\n|$))*)\n*/,table:/^ *\|(.+)\n *\|( *[-:]+[-| :]*)\n((?: *\|.*(?:\n|$))*)\n*/});function Lexer(options){this.tokens=[];this.tokens.links={};this.options=options||marked.defaults;this.rules=block.normal;if(this.options.gfm){if(this.options.tables){this.rules=block.tables}else{this.rules=block.gfm}}}Lexer.rules=block;Lexer.lex=function(src,options){var lexer=new Lexer(options);return lexer.lex(src)};Lexer.prototype.lex=function(src){src=src.replace(/\r\n|\r/g,"\n").replace(/\t/g," ").replace(/\u00a0/g," ").replace(/\u2424/g,"\n");return this.token(src,true)};Lexer.prototype.token=function(src,top,bq){var src=src.replace(/^ +$/gm,""),next,loose,cap,bull,b,item,space,i,l;while(src){if(cap=this.rules.newline.exec(src)){src=src.substring(cap[0].length);if(cap[0].length>1){this.tokens.push({type:"space"})}}if(cap=this.rules.code.exec(src)){src=src.substring(cap[0].length);cap=cap[0].replace(/^ {4}/gm,"");this.tokens.push({type:"code",text:!this.options.pedantic?cap.replace(/\n+$/,""):cap});continue}if(cap=this.rules.fences.exec(src)){src=src.substring(cap[0].length);this.tokens.push({type:"code",lang:cap[2],text:cap[3]||""});continue}if(cap=this.rules.heading.exec(src)){src=src.substring(cap[0].length);this.tokens.push({type:"heading",depth:cap[1].length,text:cap[2]});continue}if(top&&(cap=this.rules.nptable.exec(src))){src=src.substring(cap[0].length);item={type:"table",header:cap[1].replace(/^ *| *\| *$/g,"").split(/ *\| */),align:cap[2].replace(/^ *|\| *$/g,"").split(/ *\| */),cells:cap[3].replace(/\n$/,"").split("\n")};for(i=0;i ?/gm,"");this.token(cap,top,true);this.tokens.push({type:"blockquote_end"});continue}if(cap=this.rules.list.exec(src)){src=src.substring(cap[0].length);bull=cap[2];this.tokens.push({type:"list_start",ordered:bull.length>1});cap=cap[0].match(this.rules.item);next=false;l=cap.length;i=0;for(;i1&&b.length>1)){src=cap.slice(i+1).join("\n")+src;i=l-1}}loose=next||/\n\n(?!\s*$)/.test(item);if(i!==l-1){next=item.charAt(item.length-1)==="\n";if(!loose)loose=next}this.tokens.push({type:loose?"loose_item_start":"list_item_start"});this.token(item,false,bq);this.tokens.push({type:"list_item_end"})}this.tokens.push({type:"list_end"});continue}if(cap=this.rules.html.exec(src)){src=src.substring(cap[0].length);this.tokens.push({type:this.options.sanitize?"paragraph":"html",pre:!this.options.sanitizer&&(cap[1]==="pre"||cap[1]==="script"||cap[1]==="style"),text:cap[0]});continue}if(!bq&&top&&(cap=this.rules.def.exec(src))){src=src.substring(cap[0].length);this.tokens.links[cap[1].toLowerCase()]={href:cap[2],title:cap[3]};continue}if(top&&(cap=this.rules.table.exec(src))){src=src.substring(cap[0].length);item={type:"table",header:cap[1].replace(/^ *| *\| *$/g,"").split(/ *\| */),align:cap[2].replace(/^ *|\| *$/g,"").split(/ *\| */),cells:cap[3].replace(/(?: *\| *)?\n$/,"").split("\n")};for(i=0;i])/,autolink:/^<([^ >]+(@|:\/)[^ >]+)>/,url:noop,tag:/^|^<\/?\w+(?:"[^"]*"|'[^']*'|[^'">])*?>/,link:/^!?\[(inside)\]\(href\)/,reflink:/^!?\[(inside)\]\s*\[([^\]]*)\]/,nolink:/^!?\[((?:\[[^\]]*\]|[^\[\]])*)\]/,strong:/^__([\s\S]+?)__(?!_)|^\*\*([\s\S]+?)\*\*(?!\*)/,em:/^\b_((?:[^_]|__)+?)_\b|^\*((?:\*\*|[\s\S])+?)\*(?!\*)/,code:/^(`+)\s*([\s\S]*?[^`])\s*\1(?!`)/,br:/^ {2,}\n(?!\s*$)/,del:noop,text:/^[\s\S]+?(?=[\\?(?:\s+['"]([\s\S]*?)['"])?\s*/;inline.link=replace(inline.link)("inside",inline._inside)("href",inline._href)();inline.reflink=replace(inline.reflink)("inside",inline._inside)();inline.normal=merge({},inline);inline.pedantic=merge({},inline.normal,{strong:/^__(?=\S)([\s\S]*?\S)__(?!_)|^\*\*(?=\S)([\s\S]*?\S)\*\*(?!\*)/,em:/^_(?=\S)([\s\S]*?\S)_(?!_)|^\*(?=\S)([\s\S]*?\S)\*(?!\*)/});inline.gfm=merge({},inline.normal,{escape:replace(inline.escape)("])","~|])")(),url:/^(https?:\/\/[^\s<]+[^<.,:;"')\]\s])/,del:/^~~(?=\S)([\s\S]*?\S)~~/,text:replace(inline.text)("]|","~]|")("|","|https?://|")()});inline.breaks=merge({},inline.gfm,{br:replace(inline.br)("{2,}","*")(),text:replace(inline.gfm.text)("{2,}","*")()});function InlineLexer(links,options){this.options=options||marked.defaults;this.links=links;this.rules=inline.normal;this.renderer=this.options.renderer||new Renderer;this.renderer.options=this.options;if(!this.links){throw new Error("Tokens array requires a `links` property.")}if(this.options.gfm){if(this.options.breaks){this.rules=inline.breaks}else{this.rules=inline.gfm}}else if(this.options.pedantic){this.rules=inline.pedantic}}InlineLexer.rules=inline;InlineLexer.output=function(src,links,options){var inline=new InlineLexer(links,options);return inline.output(src)};InlineLexer.prototype.output=function(src){var out="",link,text,href,cap;while(src){if(cap=this.rules.escape.exec(src)){src=src.substring(cap[0].length);out+=cap[1];continue}if(cap=this.rules.autolink.exec(src)){src=src.substring(cap[0].length);if(cap[2]==="@"){text=cap[1].charAt(6)===":"?this.mangle(cap[1].substring(7)):this.mangle(cap[1]);href=this.mangle("mailto:")+text}else{text=escape(cap[1]);href=text}out+=this.renderer.link(href,null,text);continue}if(!this.inLink&&(cap=this.rules.url.exec(src))){src=src.substring(cap[0].length);text=escape(cap[1]);href=text;out+=this.renderer.link(href,null,text);continue}if(cap=this.rules.tag.exec(src)){if(!this.inLink&&/^
    /i.test(cap[0])){this.inLink=false}src=src.substring(cap[0].length);out+=this.options.sanitize?this.options.sanitizer?this.options.sanitizer(cap[0]):escape(cap[0]):cap[0];continue}if(cap=this.rules.link.exec(src)){src=src.substring(cap[0].length);this.inLink=true;out+=this.outputLink(cap,{href:cap[2],title:cap[3]});this.inLink=false;continue}if((cap=this.rules.reflink.exec(src))||(cap=this.rules.nolink.exec(src))){src=src.substring(cap[0].length);link=(cap[2]||cap[1]).replace(/\s+/g," ");link=this.links[link.toLowerCase()];if(!link||!link.href){out+=cap[0].charAt(0);src=cap[0].substring(1)+src;continue}this.inLink=true;out+=this.outputLink(cap,link);this.inLink=false;continue}if(cap=this.rules.strong.exec(src)){src=src.substring(cap[0].length);out+=this.renderer.strong(this.output(cap[2]||cap[1]));continue}if(cap=this.rules.em.exec(src)){src=src.substring(cap[0].length);out+=this.renderer.em(this.output(cap[2]||cap[1]));continue}if(cap=this.rules.code.exec(src)){src=src.substring(cap[0].length);out+=this.renderer.codespan(escape(cap[2],true));continue}if(cap=this.rules.br.exec(src)){src=src.substring(cap[0].length);out+=this.renderer.br();continue}if(cap=this.rules.del.exec(src)){src=src.substring(cap[0].length);out+=this.renderer.del(this.output(cap[1]));continue}if(cap=this.rules.text.exec(src)){src=src.substring(cap[0].length);out+=this.renderer.text(escape(this.smartypants(cap[0])));continue}if(src){throw new Error("Infinite loop on byte: "+src.charCodeAt(0))}}return out};InlineLexer.prototype.outputLink=function(cap,link){var href=escape(link.href),title=link.title?escape(link.title):null;return cap[0].charAt(0)!=="!"?this.renderer.link(href,title,this.output(cap[1])):this.renderer.image(href,title,escape(cap[1]))};InlineLexer.prototype.smartypants=function(text){if(!this.options.smartypants)return text;return text.replace(/---/g,"—").replace(/--/g,"–").replace(/(^|[-\u2014/(\[{"\s])'/g,"$1‘").replace(/'/g,"’").replace(/(^|[-\u2014/(\[{\u2018\s])"/g,"$1“").replace(/"/g,"”").replace(/\.{3}/g,"…")};InlineLexer.prototype.mangle=function(text){if(!this.options.mangle)return text;var out="",l=text.length,i=0,ch;for(;i.5){ch="x"+ch.toString(16)}out+="&#"+ch+";"}return out};function Renderer(options){this.options=options||{}}Renderer.prototype.code=function(code,lang,escaped){if(this.options.highlight){var out=this.options.highlight(code,lang);if(out!=null&&out!==code){escaped=true;code=out}}if(!lang){return"
    "+(escaped?code:escape(code,true))+"\n
    "}return'
    '+(escaped?code:escape(code,true))+"\n
    \n"};Renderer.prototype.blockquote=function(quote){return"
    \n"+quote+"
    \n"};Renderer.prototype.html=function(html){return html};Renderer.prototype.heading=function(text,level,raw){return"'+text+"\n"};Renderer.prototype.hr=function(){return this.options.xhtml?"
    \n":"
    \n"};Renderer.prototype.list=function(body,ordered){var type=ordered?"ol":"ul";return"<"+type+">\n"+body+"\n"};Renderer.prototype.listitem=function(text){return"
  • "+text+"
  • \n"};Renderer.prototype.paragraph=function(text){return"

    "+text+"

    \n"};Renderer.prototype.table=function(header,body){return"\n"+"\n"+header+"\n"+"\n"+body+"\n"+"
    \n"};Renderer.prototype.tablerow=function(content){return"\n"+content+"\n"};Renderer.prototype.tablecell=function(content,flags){var type=flags.header?"th":"td";var tag=flags.align?"<"+type+' style="text-align:'+flags.align+'">':"<"+type+">";return tag+content+"\n"};Renderer.prototype.strong=function(text){return""+text+""};Renderer.prototype.em=function(text){return""+text+""};Renderer.prototype.codespan=function(text){return""+text+""};Renderer.prototype.br=function(){return this.options.xhtml?"
    ":"
    "};Renderer.prototype.del=function(text){return""+text+""};Renderer.prototype.link=function(href,title,text){if(this.options.sanitize){try{var prot=decodeURIComponent(unescape(href)).replace(/[^\w:]/g,"").toLowerCase()}catch(e){return""}if(prot.indexOf("javascript:")===0||prot.indexOf("vbscript:")===0){return""}}var out='
    ";return out};Renderer.prototype.image=function(href,title,text){var out=''+text+'":">";return out};Renderer.prototype.text=function(text){return text};function Parser(options){this.tokens=[];this.token=null;this.options=options||marked.defaults;this.options.renderer=this.options.renderer||new Renderer;this.renderer=this.options.renderer;this.renderer.options=this.options}Parser.parse=function(src,options,renderer){var parser=new Parser(options,renderer);return parser.parse(src)};Parser.prototype.parse=function(src){this.inline=new InlineLexer(src.links,this.options,this.renderer);this.tokens=src.reverse();var out="";while(this.next()){out+=this.tok()}return out};Parser.prototype.next=function(){return this.token=this.tokens.pop()};Parser.prototype.peek=function(){return this.tokens[this.tokens.length-1]||0};Parser.prototype.parseText=function(){var body=this.token.text;while(this.peek().type==="text"){body+="\n"+this.next().text}return this.inline.output(body)};Parser.prototype.tok=function(){switch(this.token.type){case"space":{return""}case"hr":{return this.renderer.hr()}case"heading":{return this.renderer.heading(this.inline.output(this.token.text),this.token.depth,this.token.text)}case"code":{return this.renderer.code(this.token.text,this.token.lang,this.token.escaped)}case"table":{var header="",body="",i,row,cell,flags,j;cell="";for(i=0;i/g,">").replace(/"/g,""").replace(/'/g,"'")}function unescape(html){return html.replace(/&([#\w]+);/g,function(_,n){n=n.toLowerCase();if(n==="colon")return":";if(n.charAt(0)==="#"){return n.charAt(1)==="x"?String.fromCharCode(parseInt(n.substring(2),16)):String.fromCharCode(+n.substring(1))}return""})}function replace(regex,opt){regex=regex.source;opt=opt||"";return function self(name,val){if(!name)return new RegExp(regex,opt);val=val.source||val;val=val.replace(/(^|[^\[])\^/g,"$1");regex=regex.replace(name,val);return self}}function noop(){}noop.exec=noop;function merge(obj){var i=1,target,key;for(;iAn error occured:

    "+escape(e.message+"",true)+"
    "}throw e}}marked.options=marked.setOptions=function(opt){merge(marked.defaults,opt);return marked};marked.defaults={gfm:true,tables:true,breaks:false,pedantic:false,sanitize:false,sanitizer:null,mangle:true,smartLists:false,silent:false,highlight:null,langPrefix:"lang-",smartypants:false,headerPrefix:"",renderer:new Renderer,xhtml:false};marked.Parser=Parser;marked.parser=Parser.parse;marked.Renderer=Renderer;marked.Lexer=Lexer;marked.lexer=Lexer.lex;marked.InlineLexer=InlineLexer;marked.inlineLexer=InlineLexer.output;marked.parse=marked;if(typeof module!=="undefined"&&typeof exports==="object"){module.exports=marked}else if(typeof define==="function"&&define.amd){define(function(){return marked})}else{this.marked=marked}}).call(function(){return this||(typeof window!=="undefined"?window:global)}()); \ No newline at end of file diff --git a/src/main/resources/resources/vendors/marked-0.3.6/package.json b/src/main/resources/resources/vendors/marked-0.3.6/package.json new file mode 100644 index 0000000..75f3194 --- /dev/null +++ b/src/main/resources/resources/vendors/marked-0.3.6/package.json @@ -0,0 +1,24 @@ +{ + "name": "marked", + "description": "A markdown parser built for speed", + "author": "Christopher Jeffrey", + "version": "0.3.6", + "main": "./lib/marked.js", + "bin": "./bin/marked", + "man": "./man/marked.1", + "preferGlobal": true, + "repository": "git://github.com/chjj/marked.git", + "homepage": "https://github.com/chjj/marked", + "bugs": { "url": "http://github.com/chjj/marked/issues" }, + "license": "MIT", + "keywords": ["markdown", "markup", "html"], + "tags": ["markdown", "markup", "html"], + "devDependencies": { + "markdown": "*", + "showdown": "*", + "gulp": "^3.8.11", + "gulp-uglify": "^1.1.0", + "gulp-concat": "^2.5.2" + }, + "scripts": { "test": "node test", "bench": "node test --bench" } +} diff --git a/src/main/resources/resources/vendors/marked-0.3.6/test/README b/src/main/resources/resources/vendors/marked-0.3.6/test/README new file mode 100644 index 0000000..51f6560 --- /dev/null +++ b/src/main/resources/resources/vendors/marked-0.3.6/test/README @@ -0,0 +1,10 @@ +In this directory: + +# +# MarkdownTester -- Run tests for Markdown implementations +# +# Copyright (c) 2004-2005 John Gruber +# +# + +Partially modified for testing purposes. diff --git a/src/main/resources/resources/vendors/marked-0.3.6/test/browser/index.html b/src/main/resources/resources/vendors/marked-0.3.6/test/browser/index.html new file mode 100644 index 0000000..fbde129 --- /dev/null +++ b/src/main/resources/resources/vendors/marked-0.3.6/test/browser/index.html @@ -0,0 +1,5 @@ + +marked tests +

    testing...

    + + diff --git a/src/main/resources/resources/vendors/marked-0.3.6/test/browser/index.js b/src/main/resources/resources/vendors/marked-0.3.6/test/browser/index.js new file mode 100644 index 0000000..d5d7ee6 --- /dev/null +++ b/src/main/resources/resources/vendors/marked-0.3.6/test/browser/index.js @@ -0,0 +1,41 @@ +var fs = require('fs'); + +var test = require('../') + , runTests = test.runTests + , load = test.load; + +var express = require('express') + , app = express(); + +app.use(function(req, res, next) { + var setHeader = res.setHeader; + res.setHeader = function(name) { + switch (name) { + case 'Cache-Control': + case 'Last-Modified': + case 'ETag': + return; + } + return setHeader.apply(res, arguments); + }; + next(); +}); + +var dir = __dirname + '/../tests' + , files = {}; + +app.get('/test.js', function(req, res, next) { + var test = fs.readFileSync(__dirname + '/test.js', 'utf8') + , files = load(); + + test = test.replace('__TESTS__', JSON.stringify(files)); + test = test.replace('__MAIN__', runTests + ''); + + res.contentType('.js'); + res.send(test); +}); + +app.use(express.static(__dirname + '/../../lib')); +app.use(express.static(__dirname)); + +app.listen(8080); diff --git a/src/main/resources/resources/vendors/marked-0.3.6/test/browser/test.js b/src/main/resources/resources/vendors/marked-0.3.6/test/browser/test.js new file mode 100644 index 0000000..cef9e37 --- /dev/null +++ b/src/main/resources/resources/vendors/marked-0.3.6/test/browser/test.js @@ -0,0 +1,62 @@ +;(function() { + +var console = {} + , files = __TESTS__; + +console.log = function(text) { + var args = Array.prototype.slice.call(arguments, 1) + , i = 0; + + text = text.replace(/%\w/g, function() { + return args[i++] || ''; + }); + + if (window.console) window.console.log(text); + document.body.innerHTML += '
    ' + escape(text) + '
    '; +}; + +if (!Object.keys) { + Object.keys = function(obj) { + var out = [] + , key; + + for (key in obj) { + if (Object.prototype.hasOwnProperty.call(obj, key)) { + out.push(key); + } + } + + return out; + }; +} + +if (!Array.prototype.forEach) { + Array.prototype.forEach = function(callback, context) { + for (var i = 0; i < this.length; i++) { + callback.call(context || null, this[i], i, obj); + } + }; +} + +if (!String.prototype.trim) { + String.prototype.trim = function() { + return this.replace(/^\s+|\s+$/g, ''); + }; +} + +function load() { + return files; +} + +function escape(html, encode) { + return html + .replace(!encode ? /&(?!#?\w+;)/g : /&/g, '&') + .replace(//g, '>') + .replace(/"/g, '"') + .replace(/'/g, '''); +} + +(__MAIN__)(); + +}).call(this); diff --git a/src/main/resources/resources/vendors/marked-0.3.6/test/index.js b/src/main/resources/resources/vendors/marked-0.3.6/test/index.js new file mode 100644 index 0000000..9c30b9a --- /dev/null +++ b/src/main/resources/resources/vendors/marked-0.3.6/test/index.js @@ -0,0 +1,541 @@ +#!/usr/bin/env node + +/** + * marked tests + * Copyright (c) 2011-2013, Christopher Jeffrey. (MIT Licensed) + * https://github.com/chjj/marked + */ + +/** + * Modules + */ + +var fs = require('fs') + , path = require('path') + , marked = require('../'); + +/** + * Load Tests + */ + +function load() { + var dir = __dirname + '/tests' + , files = {} + , list + , file + , i + , l; + + list = fs + .readdirSync(dir) + .filter(function(file) { + return path.extname(file) !== '.html'; + }) + .sort(function(a, b) { + a = path.basename(a).toLowerCase().charCodeAt(0); + b = path.basename(b).toLowerCase().charCodeAt(0); + return a > b ? 1 : (a < b ? -1 : 0); + }); + + i = 0; + l = list.length; + + for (; i < l; i++) { + file = path.join(dir, list[i]); + files[path.basename(file)] = { + text: fs.readFileSync(file, 'utf8'), + html: fs.readFileSync(file.replace(/[^.]+$/, 'html'), 'utf8') + }; + } + + return files; +} + +/** + * Test Runner + */ + +function runTests(engine, options) { + if (typeof engine !== 'function') { + options = engine; + engine = null; + } + + var engine = engine || marked + , options = options || {} + , files = options.files || load() + , complete = 0 + , failed = 0 + , failures = [] + , keys = Object.keys(files) + , i = 0 + , len = keys.length + , filename + , file + , flags + , text + , html + , j + , l; + + if (options.marked) { + marked.setOptions(options.marked); + } + +main: + for (; i < len; i++) { + filename = keys[i]; + file = files[filename]; + + if (marked._original) { + marked.defaults = marked._original; + delete marked._original; + } + + flags = filename.split('.').slice(1, -1); + if (flags.length) { + marked._original = marked.defaults; + marked.defaults = {}; + Object.keys(marked._original).forEach(function(key) { + marked.defaults[key] = marked._original[key]; + }); + flags.forEach(function(key) { + var val = true; + if (key.indexOf('no') === 0) { + key = key.substring(2); + val = false; + } + if (marked.defaults.hasOwnProperty(key)) { + marked.defaults[key] = val; + } + }); + } + + try { + text = engine(file.text).replace(/\s/g, ''); + html = file.html.replace(/\s/g, ''); + } catch(e) { + console.log('%s failed.', filename); + throw e; + } + + j = 0; + l = html.length; + + for (; j < l; j++) { + if (text[j] !== html[j]) { + failed++; + failures.push(filename); + + text = text.substring( + Math.max(j - 30, 0), + Math.min(j + 30, text.length)); + + html = html.substring( + Math.max(j - 30, 0), + Math.min(j + 30, html.length)); + + console.log( + '\n#%d. %s failed at offset %d. Near: "%s".\n', + i + 1, filename, j, text); + + console.log('\nGot:\n%s\n', text.trim() || text); + console.log('\nExpected:\n%s\n', html.trim() || html); + + if (options.stop) { + break main; + } + + continue main; + } + } + + complete++; + console.log('#%d. %s completed.', i + 1, filename); + } + + console.log('%d/%d tests completed successfully.', complete, len); + if (failed) console.log('%d/%d tests failed.', failed, len); + + // Tests currently failing. + if (~failures.indexOf('def_blocks.text')) { + failed -= 1; + } + + return !failed; +} + +/** + * Benchmark a function + */ + +function bench(name, func) { + var files = bench.files || load(); + + if (!bench.files) { + bench.files = files; + + // Change certain tests to allow + // comparison to older benchmark times. + fs.readdirSync(__dirname + '/new').forEach(function(name) { + if (path.extname(name) === '.html') return; + if (name === 'main.text') return; + delete files[name]; + }); + + files['backslash_escapes.text'] = { + text: 'hello world \\[how](are you) today' + }; + + files['main.text'].text = files['main.text'].text.replace('* * *\n\n', ''); + } + + var start = Date.now() + , times = 1000 + , keys = Object.keys(files) + , i + , l = keys.length + , filename + , file; + + while (times--) { + for (i = 0; i < l; i++) { + filename = keys[i]; + file = files[filename]; + func(file.text); + } + } + + console.log('%s completed in %dms.', name, Date.now() - start); +} + +/** + * Benchmark all engines + */ + +function runBench(options) { + var options = options || {}; + + // Non-GFM, Non-pedantic + marked.setOptions({ + gfm: false, + tables: false, + breaks: false, + pedantic: false, + sanitize: false, + smartLists: false + }); + if (options.marked) { + marked.setOptions(options.marked); + } + bench('marked', marked); + + // GFM + marked.setOptions({ + gfm: true, + tables: false, + breaks: false, + pedantic: false, + sanitize: false, + smartLists: false + }); + if (options.marked) { + marked.setOptions(options.marked); + } + bench('marked (gfm)', marked); + + // Pedantic + marked.setOptions({ + gfm: false, + tables: false, + breaks: false, + pedantic: true, + sanitize: false, + smartLists: false + }); + if (options.marked) { + marked.setOptions(options.marked); + } + bench('marked (pedantic)', marked); + + // robotskirt + try { + bench('robotskirt', (function() { + var rs = require('robotskirt'); + return function(text) { + var parser = rs.Markdown.std(); + return parser.render(text); + }; + })()); + } catch (e) { + console.log('Could not bench robotskirt.'); + } + + // showdown + try { + bench('showdown (reuse converter)', (function() { + var Showdown = require('showdown'); + var convert = new Showdown.converter(); + return function(text) { + return convert.makeHtml(text); + }; + })()); + bench('showdown (new converter)', (function() { + var Showdown = require('showdown'); + return function(text) { + var convert = new Showdown.converter(); + return convert.makeHtml(text); + }; + })()); + } catch (e) { + console.log('Could not bench showdown.'); + } + + // markdown.js + try { + bench('markdown.js', require('markdown').parse); + } catch (e) { + console.log('Could not bench markdown.js.'); + } +} + +/** + * A simple one-time benchmark + */ + +function time(options) { + var options = options || {}; + if (options.marked) { + marked.setOptions(options.marked); + } + bench('marked', marked); +} + +/** + * Markdown Test Suite Fixer + * This function is responsible for "fixing" + * the markdown test suite. There are + * certain aspects of the suite that + * are strange or might make tests + * fail for reasons unrelated to + * conformance. + */ + +function fix(options) { + ['tests', 'original', 'new'].forEach(function(dir) { + try { + fs.mkdirSync(path.resolve(__dirname, dir), 0755); + } catch (e) { + ; + } + }); + + // rm -rf tests + fs.readdirSync(path.resolve(__dirname, 'tests')).forEach(function(file) { + fs.unlinkSync(path.resolve(__dirname, 'tests', file)); + }); + + // cp -r original tests + fs.readdirSync(path.resolve(__dirname, 'original')).forEach(function(file) { + var nfile = file; + if (file.indexOf('hard_wrapped_paragraphs_with_list_like_lines.') === 0) { + nfile = file.replace(/\.(text|html)$/, '.nogfm.$1'); + } + fs.writeFileSync(path.resolve(__dirname, 'tests', nfile), + fs.readFileSync(path.resolve(__dirname, 'original', file))); + }); + + // node fix.js + var dir = __dirname + '/tests'; + + fs.readdirSync(dir).filter(function(file) { + return path.extname(file) === '.html'; + }).forEach(function(file) { + var file = path.join(dir, file) + , html = fs.readFileSync(file, 'utf8'); + + // fix unencoded quotes + html = html + .replace(/='([^\n']*)'(?=[^<>\n]*>)/g, '=&__APOS__;$1&__APOS__;') + .replace(/="([^\n"]*)"(?=[^<>\n]*>)/g, '=&__QUOT__;$1&__QUOT__;') + .replace(/"/g, '"') + .replace(/'/g, ''') + .replace(/&__QUOT__;/g, '"') + .replace(/&__APOS__;/g, '\''); + + // add heading id's + html = html.replace(/<(h[1-6])>([^<]+)<\/\1>/g, function(s, h, text) { + var id = text + .replace(/'/g, '\'') + .replace(/"/g, '"') + .replace(/>/g, '>') + .replace(/</g, '<') + .replace(/&/g, '&'); + + id = id.toLowerCase().replace(/[^\w]+/g, '-'); + + return '<' + h + ' id="' + id + '">' + text + ''; + }); + + fs.writeFileSync(file, html); + }); + + // turn
    into
    + fs.readdirSync(dir).forEach(function(file) { + var file = path.join(dir, file) + , text = fs.readFileSync(file, 'utf8'); + + text = text.replace(/(<|<)hr\s*\/(>|>)/g, '$1hr$2'); + + fs.writeFileSync(file, text); + }); + + // markdown does some strange things. + // it does not encode naked `>`, marked does. + (function() { + var file = dir + '/amps_and_angles_encoding.html'; + var html = fs.readFileSync(file, 'utf8') + .replace('6 > 5.', '6 > 5.'); + + fs.writeFileSync(file, html); + })(); + + // cp new/* tests/ + fs.readdirSync(path.resolve(__dirname, 'new')).forEach(function(file) { + fs.writeFileSync(path.resolve(__dirname, 'tests', file), + fs.readFileSync(path.resolve(__dirname, 'new', file))); + }); +} + +/** + * Argument Parsing + */ + +function parseArg(argv) { + var argv = process.argv.slice(2) + , options = {} + , orphans = [] + , arg; + + function getarg() { + var arg = argv.shift(); + + if (arg.indexOf('--') === 0) { + // e.g. --opt + arg = arg.split('='); + if (arg.length > 1) { + // e.g. --opt=val + argv.unshift(arg.slice(1).join('=')); + } + arg = arg[0]; + } else if (arg[0] === '-') { + if (arg.length > 2) { + // e.g. -abc + argv = arg.substring(1).split('').map(function(ch) { + return '-' + ch; + }).concat(argv); + arg = argv.shift(); + } else { + // e.g. -a + } + } else { + // e.g. foo + } + + return arg; + } + + while (argv.length) { + arg = getarg(); + switch (arg) { + case '-f': + case '--fix': + case 'fix': + options.fix = true; + break; + case '-b': + case '--bench': + options.bench = true; + break; + case '-s': + case '--stop': + options.stop = true; + break; + case '-t': + case '--time': + options.time = true; + break; + default: + if (arg.indexOf('--') === 0) { + opt = camelize(arg.replace(/^--(no-)?/, '')); + if (!marked.defaults.hasOwnProperty(opt)) { + continue; + } + options.marked = options.marked || {}; + if (arg.indexOf('--no-') === 0) { + options.marked[opt] = typeof marked.defaults[opt] !== 'boolean' + ? null + : false; + } else { + options.marked[opt] = typeof marked.defaults[opt] !== 'boolean' + ? argv.shift() + : true; + } + } else { + orphans.push(arg); + } + break; + } + } + + return options; +} + +/** + * Helpers + */ + +function camelize(text) { + return text.replace(/(\w)-(\w)/g, function(_, a, b) { + return a + b.toUpperCase(); + }); +} + +/** + * Main + */ + +function main(argv) { + var opt = parseArg(); + + if (opt.fix) { + return fix(opt); + } + + if (opt.bench) { + return runBench(opt); + } + + if (opt.time) { + return time(opt); + } + + return runTests(opt); +} + +/** + * Execute + */ + +if (!module.parent) { + process.title = 'marked'; + process.exit(main(process.argv.slice()) ? 0 : 1); +} else { + exports = main; + exports.main = main; + exports.runTests = runTests; + exports.runBench = runBench; + exports.load = load; + exports.bench = bench; + module.exports = exports; +} diff --git a/src/main/resources/resources/vendors/marked-0.3.6/test/new/autolink_lines.html b/src/main/resources/resources/vendors/marked-0.3.6/test/new/autolink_lines.html new file mode 100644 index 0000000..aa2bed4 --- /dev/null +++ b/src/main/resources/resources/vendors/marked-0.3.6/test/new/autolink_lines.html @@ -0,0 +1,3 @@ +

    hello world +http://example.com +

    diff --git a/src/main/resources/resources/vendors/marked-0.3.6/test/new/autolink_lines.text b/src/main/resources/resources/vendors/marked-0.3.6/test/new/autolink_lines.text new file mode 100644 index 0000000..c9b61a2 --- /dev/null +++ b/src/main/resources/resources/vendors/marked-0.3.6/test/new/autolink_lines.text @@ -0,0 +1,2 @@ +hello world + diff --git a/src/main/resources/resources/vendors/marked-0.3.6/test/new/blockquote_list_item.html b/src/main/resources/resources/vendors/marked-0.3.6/test/new/blockquote_list_item.html new file mode 100644 index 0000000..83cf0bd --- /dev/null +++ b/src/main/resources/resources/vendors/marked-0.3.6/test/new/blockquote_list_item.html @@ -0,0 +1,3 @@ +

    This fails in markdown.pl and upskirt:

    + +
    • hello

      world

    diff --git a/src/main/resources/resources/vendors/marked-0.3.6/test/new/blockquote_list_item.text b/src/main/resources/resources/vendors/marked-0.3.6/test/new/blockquote_list_item.text new file mode 100644 index 0000000..19e9382 --- /dev/null +++ b/src/main/resources/resources/vendors/marked-0.3.6/test/new/blockquote_list_item.text @@ -0,0 +1,4 @@ +This fails in markdown.pl and upskirt: + +* hello + > world diff --git a/src/main/resources/resources/vendors/marked-0.3.6/test/new/case_insensitive_refs.html b/src/main/resources/resources/vendors/marked-0.3.6/test/new/case_insensitive_refs.html new file mode 100644 index 0000000..c54388e --- /dev/null +++ b/src/main/resources/resources/vendors/marked-0.3.6/test/new/case_insensitive_refs.html @@ -0,0 +1 @@ +

    hi

    diff --git a/src/main/resources/resources/vendors/marked-0.3.6/test/new/case_insensitive_refs.text b/src/main/resources/resources/vendors/marked-0.3.6/test/new/case_insensitive_refs.text new file mode 100644 index 0000000..598915a --- /dev/null +++ b/src/main/resources/resources/vendors/marked-0.3.6/test/new/case_insensitive_refs.text @@ -0,0 +1,3 @@ +[hi] + +[HI]: /url diff --git a/src/main/resources/resources/vendors/marked-0.3.6/test/new/def_blocks.html b/src/main/resources/resources/vendors/marked-0.3.6/test/new/def_blocks.html new file mode 100644 index 0000000..14edc97 --- /dev/null +++ b/src/main/resources/resources/vendors/marked-0.3.6/test/new/def_blocks.html @@ -0,0 +1,28 @@ +
    +

    hello +[1]: hello

    +
    + +
    + +
    +

    hello

    +
    + + +
      +
    • hello
    • +
    • [3]: hello
    • +
    + + +
      +
    • hello
    • +
    + + +
    +

    foo +bar +bar

    +
    diff --git a/src/main/resources/resources/vendors/marked-0.3.6/test/new/def_blocks.text b/src/main/resources/resources/vendors/marked-0.3.6/test/new/def_blocks.text new file mode 100644 index 0000000..4d16292 --- /dev/null +++ b/src/main/resources/resources/vendors/marked-0.3.6/test/new/def_blocks.text @@ -0,0 +1,21 @@ +> hello +> [1]: hello + +* * * + +> hello +[2]: hello + + +* hello +* [3]: hello + + +* hello +[4]: hello + + +> foo +> bar +[1]: foo +> bar diff --git a/src/main/resources/resources/vendors/marked-0.3.6/test/new/double_link.html b/src/main/resources/resources/vendors/marked-0.3.6/test/new/double_link.html new file mode 100644 index 0000000..ff68395 --- /dev/null +++ b/src/main/resources/resources/vendors/marked-0.3.6/test/new/double_link.html @@ -0,0 +1,5 @@ +

    Already linked: http://example.com/.

    + +

    Already linked: http://example.com/.

    + +

    Already linked: http://example.com/.

    diff --git a/src/main/resources/resources/vendors/marked-0.3.6/test/new/double_link.text b/src/main/resources/resources/vendors/marked-0.3.6/test/new/double_link.text new file mode 100644 index 0000000..5021673 --- /dev/null +++ b/src/main/resources/resources/vendors/marked-0.3.6/test/new/double_link.text @@ -0,0 +1,5 @@ +

    Already linked: http://example.com/.

    + +Already linked: [http://example.com/](http://example.com/). + +Already linked: **http://example.com/**. diff --git a/src/main/resources/resources/vendors/marked-0.3.6/test/new/escaped_angles.html b/src/main/resources/resources/vendors/marked-0.3.6/test/new/escaped_angles.html new file mode 100644 index 0000000..7cf47c4 --- /dev/null +++ b/src/main/resources/resources/vendors/marked-0.3.6/test/new/escaped_angles.html @@ -0,0 +1 @@ +

    >

    diff --git a/src/main/resources/resources/vendors/marked-0.3.6/test/new/escaped_angles.text b/src/main/resources/resources/vendors/marked-0.3.6/test/new/escaped_angles.text new file mode 100644 index 0000000..db7422f --- /dev/null +++ b/src/main/resources/resources/vendors/marked-0.3.6/test/new/escaped_angles.text @@ -0,0 +1 @@ +\> diff --git a/src/main/resources/resources/vendors/marked-0.3.6/test/new/gfm_break.breaks.html b/src/main/resources/resources/vendors/marked-0.3.6/test/new/gfm_break.breaks.html new file mode 100644 index 0000000..398ba01 --- /dev/null +++ b/src/main/resources/resources/vendors/marked-0.3.6/test/new/gfm_break.breaks.html @@ -0,0 +1 @@ +

    Look at the
    pretty line
    breaks.

    diff --git a/src/main/resources/resources/vendors/marked-0.3.6/test/new/gfm_break.breaks.text b/src/main/resources/resources/vendors/marked-0.3.6/test/new/gfm_break.breaks.text new file mode 100644 index 0000000..71097d2 --- /dev/null +++ b/src/main/resources/resources/vendors/marked-0.3.6/test/new/gfm_break.breaks.text @@ -0,0 +1,3 @@ +Look at the +pretty line +breaks. diff --git a/src/main/resources/resources/vendors/marked-0.3.6/test/new/gfm_code.html b/src/main/resources/resources/vendors/marked-0.3.6/test/new/gfm_code.html new file mode 100644 index 0000000..872ece7 --- /dev/null +++ b/src/main/resources/resources/vendors/marked-0.3.6/test/new/gfm_code.html @@ -0,0 +1,10 @@ +
    var a = 'hello';
    +console.log(a + ' world');
    +
    echo "hello, ${WORLD}"
    +
    Q: What do you call a tall person who sells stolen goods?
    +
    A longfence!
    +

    How about an empty code block?

    +
    +

    How about a code block with only an empty line?

    +
    
    +
    diff --git a/src/main/resources/resources/vendors/marked-0.3.6/test/new/gfm_code.text b/src/main/resources/resources/vendors/marked-0.3.6/test/new/gfm_code.text new file mode 100644 index 0000000..ca46c1f --- /dev/null +++ b/src/main/resources/resources/vendors/marked-0.3.6/test/new/gfm_code.text @@ -0,0 +1,27 @@ +``` js +var a = 'hello'; +console.log(a + ' world'); +``` + +~~~bash +echo "hello, ${WORLD}" +~~~ + +```````longfence +Q: What do you call a tall person who sells stolen goods? +``````` + +~~~~~~~~~~ ManyTildes +A longfence! +~~~~~~~~~~ + +How about an empty code block? + +```js +``` + +How about a code block with only an empty line? + +```js + +``` diff --git a/src/main/resources/resources/vendors/marked-0.3.6/test/new/gfm_code_hr_list.html b/src/main/resources/resources/vendors/marked-0.3.6/test/new/gfm_code_hr_list.html new file mode 100644 index 0000000..9fbd0fb --- /dev/null +++ b/src/main/resources/resources/vendors/marked-0.3.6/test/new/gfm_code_hr_list.html @@ -0,0 +1,52 @@ +

    foo

    +
      +
    1. bar:

      +
      +
        +
      • one
          +
        • two
            +
          • three
          • +
          • four
          • +
          • five
          • +
          +
        • +
        +
      • +
      +
      +
    2. +
    3. foo:

      +
       line 1
      + line 2
      +
    4. +
    5. foo:

      +
        +
      1. foo bar bar:

        +
         some code here
        +
        +
      2. +
      3. foo bar bar:

        +
         foo
        + ---
        + bar
        + ---
        + foo
        + bar
        +
      4. +
      5. foo bar bar:

        +
         ---
        + foo
        + foo
        + ---
        + bar
        +
      6. +
      7. foo bar bar:

        +
         foo
        + ---
        + bar
        +
      8. +
      9. foo

        +
      10. +
      +
    6. +
    diff --git a/src/main/resources/resources/vendors/marked-0.3.6/test/new/gfm_code_hr_list.text b/src/main/resources/resources/vendors/marked-0.3.6/test/new/gfm_code_hr_list.text new file mode 100644 index 0000000..0eba405 --- /dev/null +++ b/src/main/resources/resources/vendors/marked-0.3.6/test/new/gfm_code_hr_list.text @@ -0,0 +1,53 @@ +## foo + +1. bar: + + > - one + - two + - three + - four + - five + +1. foo: + + ``` + line 1 + line 2 + ``` + +1. foo: + + 1. foo `bar` bar: + + ``` erb + some code here + ``` + + 2. foo `bar` bar: + + ``` erb + foo + --- + bar + --- + foo + bar + ``` + + 3. foo `bar` bar: + + ``` html + --- + foo + foo + --- + bar + ``` + + 4. foo `bar` bar: + + foo + --- + bar + + 5. foo diff --git a/src/main/resources/resources/vendors/marked-0.3.6/test/new/gfm_del.html b/src/main/resources/resources/vendors/marked-0.3.6/test/new/gfm_del.html new file mode 100644 index 0000000..95e9ec7 --- /dev/null +++ b/src/main/resources/resources/vendors/marked-0.3.6/test/new/gfm_del.html @@ -0,0 +1 @@ +

    hello hi world

    diff --git a/src/main/resources/resources/vendors/marked-0.3.6/test/new/gfm_del.text b/src/main/resources/resources/vendors/marked-0.3.6/test/new/gfm_del.text new file mode 100644 index 0000000..d29ca77 --- /dev/null +++ b/src/main/resources/resources/vendors/marked-0.3.6/test/new/gfm_del.text @@ -0,0 +1 @@ +hello ~~hi~~ world diff --git a/src/main/resources/resources/vendors/marked-0.3.6/test/new/gfm_em.html b/src/main/resources/resources/vendors/marked-0.3.6/test/new/gfm_em.html new file mode 100644 index 0000000..8fac346 --- /dev/null +++ b/src/main/resources/resources/vendors/marked-0.3.6/test/new/gfm_em.html @@ -0,0 +1 @@ +

    These words should_not_be_emphasized.

    diff --git a/src/main/resources/resources/vendors/marked-0.3.6/test/new/gfm_em.text b/src/main/resources/resources/vendors/marked-0.3.6/test/new/gfm_em.text new file mode 100644 index 0000000..6319874 --- /dev/null +++ b/src/main/resources/resources/vendors/marked-0.3.6/test/new/gfm_em.text @@ -0,0 +1 @@ +These words should_not_be_emphasized. diff --git a/src/main/resources/resources/vendors/marked-0.3.6/test/new/gfm_hashtag.gfm.html b/src/main/resources/resources/vendors/marked-0.3.6/test/new/gfm_hashtag.gfm.html new file mode 100644 index 0000000..6f9e43f --- /dev/null +++ b/src/main/resources/resources/vendors/marked-0.3.6/test/new/gfm_hashtag.gfm.html @@ -0,0 +1,5 @@ +

    #header

    + +

    header1

    + +

    header2

    diff --git a/src/main/resources/resources/vendors/marked-0.3.6/test/new/gfm_hashtag.gfm.text b/src/main/resources/resources/vendors/marked-0.3.6/test/new/gfm_hashtag.gfm.text new file mode 100644 index 0000000..7656ecf --- /dev/null +++ b/src/main/resources/resources/vendors/marked-0.3.6/test/new/gfm_hashtag.gfm.text @@ -0,0 +1,5 @@ +#header + +# header1 + +# header2 diff --git a/src/main/resources/resources/vendors/marked-0.3.6/test/new/gfm_hashtag.nogfm.html b/src/main/resources/resources/vendors/marked-0.3.6/test/new/gfm_hashtag.nogfm.html new file mode 100644 index 0000000..ecd95d6 --- /dev/null +++ b/src/main/resources/resources/vendors/marked-0.3.6/test/new/gfm_hashtag.nogfm.html @@ -0,0 +1,5 @@ +

    header

    + +

    header1

    + +

    header2

    diff --git a/src/main/resources/resources/vendors/marked-0.3.6/test/new/gfm_hashtag.nogfm.text b/src/main/resources/resources/vendors/marked-0.3.6/test/new/gfm_hashtag.nogfm.text new file mode 100644 index 0000000..7656ecf --- /dev/null +++ b/src/main/resources/resources/vendors/marked-0.3.6/test/new/gfm_hashtag.nogfm.text @@ -0,0 +1,5 @@ +#header + +# header1 + +# header2 diff --git a/src/main/resources/resources/vendors/marked-0.3.6/test/new/gfm_links.html b/src/main/resources/resources/vendors/marked-0.3.6/test/new/gfm_links.html new file mode 100644 index 0000000..4f62ae1 --- /dev/null +++ b/src/main/resources/resources/vendors/marked-0.3.6/test/new/gfm_links.html @@ -0,0 +1,2 @@ +

    This should be a link: +http://example.com/hello-world.

    diff --git a/src/main/resources/resources/vendors/marked-0.3.6/test/new/gfm_links.text b/src/main/resources/resources/vendors/marked-0.3.6/test/new/gfm_links.text new file mode 100644 index 0000000..c133666 --- /dev/null +++ b/src/main/resources/resources/vendors/marked-0.3.6/test/new/gfm_links.text @@ -0,0 +1 @@ +This should be a link: http://example.com/hello-world. diff --git a/src/main/resources/resources/vendors/marked-0.3.6/test/new/gfm_tables.html b/src/main/resources/resources/vendors/marked-0.3.6/test/new/gfm_tables.html new file mode 100644 index 0000000..70bec82 --- /dev/null +++ b/src/main/resources/resources/vendors/marked-0.3.6/test/new/gfm_tables.html @@ -0,0 +1,37 @@ + + + + + + + + +
    Heading 1Heading 2
    Cell 1Cell 2
    Cell 3Cell 4
    + + + + + + + + +
    Header 1Header 2Header 3Header 4
    Cell 1Cell 2Cell 3Cell 4
    Cell 5Cell 6Cell 7Cell 8
    +
    Test code
    + + + + + + + + +
    Header 1Header 2
    Cell 1Cell 2
    Cell 3Cell 4
    + + + + + + + + +
    Header 1Header 2Header 3Header 4
    Cell 1Cell 2Cell 3Cell 4
    Cell 5Cell 6Cell 7Cell 8
    diff --git a/src/main/resources/resources/vendors/marked-0.3.6/test/new/gfm_tables.text b/src/main/resources/resources/vendors/marked-0.3.6/test/new/gfm_tables.text new file mode 100644 index 0000000..5fd6321 --- /dev/null +++ b/src/main/resources/resources/vendors/marked-0.3.6/test/new/gfm_tables.text @@ -0,0 +1,21 @@ +| Heading 1 | Heading 2 +| --------- | --------- +| Cell 1 | Cell 2 +| Cell 3 | Cell 4 + +| Header 1 | Header 2 | Header 3 | Header 4 | +| :------: | -------: | :------- | -------- | +| Cell 1 | Cell 2 | Cell 3 | Cell 4 | +| Cell 5 | Cell 6 | Cell 7 | Cell 8 | + + Test code + +Header 1 | Header 2 +-------- | -------- +Cell 1 | Cell 2 +Cell 3 | Cell 4 + +Header 1|Header 2|Header 3|Header 4 +:-------|:------:|-------:|-------- +Cell 1 |Cell 2 |Cell 3 |Cell 4 +*Cell 5*|Cell 6 |Cell 7 |Cell 8 diff --git a/src/main/resources/resources/vendors/marked-0.3.6/test/new/hr_list_break.html b/src/main/resources/resources/vendors/marked-0.3.6/test/new/hr_list_break.html new file mode 100644 index 0000000..bd3ad1f --- /dev/null +++ b/src/main/resources/resources/vendors/marked-0.3.6/test/new/hr_list_break.html @@ -0,0 +1,10 @@ +
      +
    • hello +world
    • +
    • how +are
    • +
    + +
    + +

    you today?

    diff --git a/src/main/resources/resources/vendors/marked-0.3.6/test/new/hr_list_break.text b/src/main/resources/resources/vendors/marked-0.3.6/test/new/hr_list_break.text new file mode 100644 index 0000000..036fe47 --- /dev/null +++ b/src/main/resources/resources/vendors/marked-0.3.6/test/new/hr_list_break.text @@ -0,0 +1,6 @@ +* hello +world +* how +are +* * * +you today? diff --git a/src/main/resources/resources/vendors/marked-0.3.6/test/new/lazy_blockquotes.html b/src/main/resources/resources/vendors/marked-0.3.6/test/new/lazy_blockquotes.html new file mode 100644 index 0000000..a701d42 --- /dev/null +++ b/src/main/resources/resources/vendors/marked-0.3.6/test/new/lazy_blockquotes.html @@ -0,0 +1,4 @@ +
    +

    hi there +bud

    +
    diff --git a/src/main/resources/resources/vendors/marked-0.3.6/test/new/lazy_blockquotes.text b/src/main/resources/resources/vendors/marked-0.3.6/test/new/lazy_blockquotes.text new file mode 100644 index 0000000..c0e0b15 --- /dev/null +++ b/src/main/resources/resources/vendors/marked-0.3.6/test/new/lazy_blockquotes.text @@ -0,0 +1,2 @@ +> hi there +bud diff --git a/src/main/resources/resources/vendors/marked-0.3.6/test/new/list_item_text.html b/src/main/resources/resources/vendors/marked-0.3.6/test/new/list_item_text.html new file mode 100644 index 0000000..142df36 --- /dev/null +++ b/src/main/resources/resources/vendors/marked-0.3.6/test/new/list_item_text.html @@ -0,0 +1 @@ +
    • item1

      • item2

      text

    diff --git a/src/main/resources/resources/vendors/marked-0.3.6/test/new/list_item_text.text b/src/main/resources/resources/vendors/marked-0.3.6/test/new/list_item_text.text new file mode 100644 index 0000000..a8f81b1 --- /dev/null +++ b/src/main/resources/resources/vendors/marked-0.3.6/test/new/list_item_text.text @@ -0,0 +1,5 @@ + * item1 + + * item2 + + text diff --git a/src/main/resources/resources/vendors/marked-0.3.6/test/new/loose_lists.html b/src/main/resources/resources/vendors/marked-0.3.6/test/new/loose_lists.html new file mode 100644 index 0000000..c1bd82a --- /dev/null +++ b/src/main/resources/resources/vendors/marked-0.3.6/test/new/loose_lists.html @@ -0,0 +1,62 @@ +
      +
    • hello +world

      + +

      how +are

    • +
    • you
    • +
    + + + +

    better behavior:

    + +
    • hello

      • world +how

        are +you

      • today

    • hi
    + + + +
      +
    • hello

    • +
    • world

    • +
    • hi
    • +
    + + + +
      +
    • hello
    • +
    • world

    • +
    • hi

    • +
    + + + +
      +
    • hello
    • +
    • world

      + +

      how

    • +
    • hi
    • +
    + + + +
      +
    • hello
    • +
    • world
    • +
    • how

      + +

      are

    • +
    + + + +
      +
    • hello
    • +
    • world

    • +
    • how

      + +

      are

    • +
    diff --git a/src/main/resources/resources/vendors/marked-0.3.6/test/new/loose_lists.text b/src/main/resources/resources/vendors/marked-0.3.6/test/new/loose_lists.text new file mode 100644 index 0000000..cb360a1 --- /dev/null +++ b/src/main/resources/resources/vendors/marked-0.3.6/test/new/loose_lists.text @@ -0,0 +1,59 @@ +* hello + world + + how + are +* you + + + +better behavior: + +* hello + * world + how + + are + you + + * today +* hi + + + +* hello + +* world +* hi + + + +* hello +* world + +* hi + + + +* hello +* world + + how +* hi + + + +* hello +* world +* how + + are + + + +* hello +* world + +* how + + are diff --git a/src/main/resources/resources/vendors/marked-0.3.6/test/new/main.html b/src/main/resources/resources/vendors/marked-0.3.6/test/new/main.html new file mode 100644 index 0000000..8f78c4d --- /dev/null +++ b/src/main/resources/resources/vendors/marked-0.3.6/test/new/main.html @@ -0,0 +1,4 @@ +

    A heading

    Just a note, I've found that I can't test my markdown parser vs others. For example, both markdown.js and showdown code blocks in lists wrong. They're also completely inconsistent with regards to paragraphs in list items.

    A link. Not anymore.

    • List Item 1

    • List Item 2

      • New List Item 1 Hi, this is a list item.
      • New List Item 2 Another item
        Code goes here.
        +Lots of it...
      • New List Item 3 The last item
    • List Item 3 The final item.

    • List Item 4 The real final item.

    Paragraph.

    • bq Item 1
    • bq Item 2
      • New bq Item 1
      • New bq Item 2 Text here

    Another blockquote! I really need to get more creative with mockup text.. markdown.js breaks here again

    Another Heading

    Hello world. Here is a link. And an image alt.

    Code goes here.
    +Lots of it...
    diff --git a/src/main/resources/resources/vendors/marked-0.3.6/test/new/main.text b/src/main/resources/resources/vendors/marked-0.3.6/test/new/main.text new file mode 100644 index 0000000..58e17a6 --- /dev/null +++ b/src/main/resources/resources/vendors/marked-0.3.6/test/new/main.text @@ -0,0 +1,55 @@ +[test]: http://google.com/ "Google" + +# A heading + +Just a note, I've found that I can't test my markdown parser vs others. +For example, both markdown.js and showdown code blocks in lists wrong. They're +also completely [inconsistent][test] with regards to paragraphs in list items. + +A link. Not anymore. + + + +* List Item 1 + +* List Item 2 + * New List Item 1 + Hi, this is a list item. + * New List Item 2 + Another item + Code goes here. + Lots of it... + * New List Item 3 + The last item + +* List Item 3 +The final item. + +* List Item 4 +The real final item. + +Paragraph. + +> * bq Item 1 +> * bq Item 2 +> * New bq Item 1 +> * New bq Item 2 +> Text here + +* * * + +> Another blockquote! +> I really need to get +> more creative with +> mockup text.. +> markdown.js breaks here again + +Another Heading +------------- + +Hello *world*. Here is a [link](//hello). +And an image ![alt](src). + + Code goes here. + Lots of it... diff --git a/src/main/resources/resources/vendors/marked-0.3.6/test/new/nested_code.html b/src/main/resources/resources/vendors/marked-0.3.6/test/new/nested_code.html new file mode 100644 index 0000000..c370592 --- /dev/null +++ b/src/main/resources/resources/vendors/marked-0.3.6/test/new/nested_code.html @@ -0,0 +1 @@ +

    hi ther `` ok ```

    diff --git a/src/main/resources/resources/vendors/marked-0.3.6/test/new/nested_code.text b/src/main/resources/resources/vendors/marked-0.3.6/test/new/nested_code.text new file mode 100644 index 0000000..910e3d4 --- /dev/null +++ b/src/main/resources/resources/vendors/marked-0.3.6/test/new/nested_code.text @@ -0,0 +1 @@ +````` hi ther `` ok ``` ````` diff --git a/src/main/resources/resources/vendors/marked-0.3.6/test/new/nested_em.html b/src/main/resources/resources/vendors/marked-0.3.6/test/new/nested_em.html new file mode 100644 index 0000000..3ab4ec8 --- /dev/null +++ b/src/main/resources/resources/vendors/marked-0.3.6/test/new/nested_em.html @@ -0,0 +1,3 @@ +

    test test test

    + +

    test test test

    diff --git a/src/main/resources/resources/vendors/marked-0.3.6/test/new/nested_em.text b/src/main/resources/resources/vendors/marked-0.3.6/test/new/nested_em.text new file mode 100644 index 0000000..550d0eb --- /dev/null +++ b/src/main/resources/resources/vendors/marked-0.3.6/test/new/nested_em.text @@ -0,0 +1,3 @@ +*test **test** test* + +_test __test__ test_ diff --git a/src/main/resources/resources/vendors/marked-0.3.6/test/new/nested_square_link.html b/src/main/resources/resources/vendors/marked-0.3.6/test/new/nested_square_link.html new file mode 100644 index 0000000..c8b7940 --- /dev/null +++ b/src/main/resources/resources/vendors/marked-0.3.6/test/new/nested_square_link.html @@ -0,0 +1 @@ +

    the ] character

    diff --git a/src/main/resources/resources/vendors/marked-0.3.6/test/new/nested_square_link.text b/src/main/resources/resources/vendors/marked-0.3.6/test/new/nested_square_link.text new file mode 100644 index 0000000..82226ed --- /dev/null +++ b/src/main/resources/resources/vendors/marked-0.3.6/test/new/nested_square_link.text @@ -0,0 +1 @@ +[the `]` character](/url) diff --git a/src/main/resources/resources/vendors/marked-0.3.6/test/new/not_a_link.html b/src/main/resources/resources/vendors/marked-0.3.6/test/new/not_a_link.html new file mode 100644 index 0000000..a01685d --- /dev/null +++ b/src/main/resources/resources/vendors/marked-0.3.6/test/new/not_a_link.html @@ -0,0 +1 @@ +

    [test](not a link)

    diff --git a/src/main/resources/resources/vendors/marked-0.3.6/test/new/not_a_link.text b/src/main/resources/resources/vendors/marked-0.3.6/test/new/not_a_link.text new file mode 100644 index 0000000..26f6043 --- /dev/null +++ b/src/main/resources/resources/vendors/marked-0.3.6/test/new/not_a_link.text @@ -0,0 +1 @@ +\[test](not a link) diff --git a/src/main/resources/resources/vendors/marked-0.3.6/test/new/ref_paren.html b/src/main/resources/resources/vendors/marked-0.3.6/test/new/ref_paren.html new file mode 100644 index 0000000..cff6977 --- /dev/null +++ b/src/main/resources/resources/vendors/marked-0.3.6/test/new/ref_paren.html @@ -0,0 +1 @@ +

    hi

    diff --git a/src/main/resources/resources/vendors/marked-0.3.6/test/new/ref_paren.text b/src/main/resources/resources/vendors/marked-0.3.6/test/new/ref_paren.text new file mode 100644 index 0000000..aa97c91 --- /dev/null +++ b/src/main/resources/resources/vendors/marked-0.3.6/test/new/ref_paren.text @@ -0,0 +1,3 @@ +[hi] + +[hi]: /url (there) diff --git a/src/main/resources/resources/vendors/marked-0.3.6/test/new/same_bullet.html b/src/main/resources/resources/vendors/marked-0.3.6/test/new/same_bullet.html new file mode 100644 index 0000000..9220741 --- /dev/null +++ b/src/main/resources/resources/vendors/marked-0.3.6/test/new/same_bullet.html @@ -0,0 +1,5 @@ +
      +
    • test
    • +
    • test
    • +
    • test
    • +
    diff --git a/src/main/resources/resources/vendors/marked-0.3.6/test/new/same_bullet.text b/src/main/resources/resources/vendors/marked-0.3.6/test/new/same_bullet.text new file mode 100644 index 0000000..27a8967 --- /dev/null +++ b/src/main/resources/resources/vendors/marked-0.3.6/test/new/same_bullet.text @@ -0,0 +1,3 @@ +* test ++ test +- test diff --git a/src/main/resources/resources/vendors/marked-0.3.6/test/new/text.smartypants.html b/src/main/resources/resources/vendors/marked-0.3.6/test/new/text.smartypants.html new file mode 100644 index 0000000..22997c4 --- /dev/null +++ b/src/main/resources/resources/vendors/marked-0.3.6/test/new/text.smartypants.html @@ -0,0 +1,6 @@ +

    Hello world ‘how’ “are” you — today…

    + +

    “It’s a more ‘challenging’ smartypants test…”

    + +

    ‘And,’ as a bonus — “one +multiline” test!

    diff --git a/src/main/resources/resources/vendors/marked-0.3.6/test/new/text.smartypants.text b/src/main/resources/resources/vendors/marked-0.3.6/test/new/text.smartypants.text new file mode 100644 index 0000000..d91c8dc --- /dev/null +++ b/src/main/resources/resources/vendors/marked-0.3.6/test/new/text.smartypants.text @@ -0,0 +1,6 @@ +Hello world 'how' "are" you -- today... + +"It's a more 'challenging' smartypants test..." + +'And,' as a bonus -- "one +multiline" test! diff --git a/src/main/resources/resources/vendors/marked-0.3.6/test/new/toplevel_paragraphs.gfm.html b/src/main/resources/resources/vendors/marked-0.3.6/test/new/toplevel_paragraphs.gfm.html new file mode 100644 index 0000000..970c6f1 --- /dev/null +++ b/src/main/resources/resources/vendors/marked-0.3.6/test/new/toplevel_paragraphs.gfm.html @@ -0,0 +1,34 @@ +

    hello world + how are you + how are you

    + +

    hello world

    +
    how are you
    + +

    hello world

    +
    + +

    hello world

    +

    how are you

    + +

    hello world

    +

    how are you

    + +

    hello world

    +

    how are you

    + +

    hello world

    +
    • how are you
    + +

    hello world

    +
    how are you
    + +

    hello world +how are you

    + +

    hello world +

    + +
    hello
    + +

    hello

    diff --git a/src/main/resources/resources/vendors/marked-0.3.6/test/new/toplevel_paragraphs.gfm.text b/src/main/resources/resources/vendors/marked-0.3.6/test/new/toplevel_paragraphs.gfm.text new file mode 100644 index 0000000..66366c0 --- /dev/null +++ b/src/main/resources/resources/vendors/marked-0.3.6/test/new/toplevel_paragraphs.gfm.text @@ -0,0 +1,37 @@ +hello world + how are you + how are you + +hello world +``` +how are you +``` + +hello world +* * * + +hello world +# how are you + +hello world +how are you +=========== + +hello world +> how are you + +hello world +* how are you + +hello world +
    how are you
    + +hello world +how are you + +hello [world][how] +[how]: /are/you + +
    hello
    + +hello diff --git a/src/main/resources/resources/vendors/marked-0.3.6/test/new/tricky_list.html b/src/main/resources/resources/vendors/marked-0.3.6/test/new/tricky_list.html new file mode 100644 index 0000000..764a335 --- /dev/null +++ b/src/main/resources/resources/vendors/marked-0.3.6/test/new/tricky_list.html @@ -0,0 +1,23 @@ +

    hello world

    + +
      +
    • hello world
    • +
    + +

    hello world

    + +
      +
    • hello world
    • +
    + +

    hello world

    + +
      +
    • Hello world
    • +
    + +

    hello world

    + +
      +
    • hello world
    • +
    diff --git a/src/main/resources/resources/vendors/marked-0.3.6/test/new/tricky_list.text b/src/main/resources/resources/vendors/marked-0.3.6/test/new/tricky_list.text new file mode 100644 index 0000000..9aa76ce --- /dev/null +++ b/src/main/resources/resources/vendors/marked-0.3.6/test/new/tricky_list.text @@ -0,0 +1,15 @@ +**hello** _world_ + +* hello world + +**hello** _world_ + +* hello world + +**hello** _world_ + +* Hello world + +**hello** _world_ + +* hello world diff --git a/src/main/resources/resources/vendors/marked-0.3.6/test/original/amps_and_angles_encoding.html b/src/main/resources/resources/vendors/marked-0.3.6/test/original/amps_and_angles_encoding.html new file mode 100644 index 0000000..9606860 --- /dev/null +++ b/src/main/resources/resources/vendors/marked-0.3.6/test/original/amps_and_angles_encoding.html @@ -0,0 +1,17 @@ +

    AT&T has an ampersand in their name.

    + +

    AT&T is another way to write it.

    + +

    This & that.

    + +

    4 < 5.

    + +

    6 > 5.

    + +

    Here's a link with an ampersand in the URL.

    + +

    Here's a link with an amersand in the link text: AT&T.

    + +

    Here's an inline link.

    + +

    Here's an inline link.

    diff --git a/src/main/resources/resources/vendors/marked-0.3.6/test/original/amps_and_angles_encoding.text b/src/main/resources/resources/vendors/marked-0.3.6/test/original/amps_and_angles_encoding.text new file mode 100644 index 0000000..89ec3ae --- /dev/null +++ b/src/main/resources/resources/vendors/marked-0.3.6/test/original/amps_and_angles_encoding.text @@ -0,0 +1,21 @@ +AT&T has an ampersand in their name. + +AT&T is another way to write it. + +This & that. + +4 < 5. + +6 > 5. + +Here's a [link] [1] with an ampersand in the URL. + +Here's a link with an amersand in the link text: [AT&T] [2]. + +Here's an inline [link](/script?foo=1&bar=2). + +Here's an inline [link](). + + +[1]: http://example.com/?foo=1&bar=2 +[2]: http://att.com/ "AT&T" diff --git a/src/main/resources/resources/vendors/marked-0.3.6/test/original/auto_links.html b/src/main/resources/resources/vendors/marked-0.3.6/test/original/auto_links.html new file mode 100644 index 0000000..f8df985 --- /dev/null +++ b/src/main/resources/resources/vendors/marked-0.3.6/test/original/auto_links.html @@ -0,0 +1,18 @@ +

    Link: http://example.com/.

    + +

    With an ampersand: http://example.com/?foo=1&bar=2

    + + + +
    +

    Blockquoted: http://example.com/

    +
    + +

    Auto-links should not occur here: <http://example.com/>

    + +
    or here: <http://example.com/>
    +
    diff --git a/src/main/resources/resources/vendors/marked-0.3.6/test/original/auto_links.text b/src/main/resources/resources/vendors/marked-0.3.6/test/original/auto_links.text new file mode 100644 index 0000000..f85767b --- /dev/null +++ b/src/main/resources/resources/vendors/marked-0.3.6/test/original/auto_links.text @@ -0,0 +1,13 @@ +Link: . + +With an ampersand: + +* In a list? +* +* It should. + +> Blockquoted: + +Auto-links should not occur here: `` + + or here: diff --git a/src/main/resources/resources/vendors/marked-0.3.6/test/original/backslash_escapes.html b/src/main/resources/resources/vendors/marked-0.3.6/test/original/backslash_escapes.html new file mode 100644 index 0000000..29870da --- /dev/null +++ b/src/main/resources/resources/vendors/marked-0.3.6/test/original/backslash_escapes.html @@ -0,0 +1,118 @@ +

    These should all get escaped:

    + +

    Backslash: \

    + +

    Backtick: `

    + +

    Asterisk: *

    + +

    Underscore: _

    + +

    Left brace: {

    + +

    Right brace: }

    + +

    Left bracket: [

    + +

    Right bracket: ]

    + +

    Left paren: (

    + +

    Right paren: )

    + +

    Greater-than: >

    + +

    Hash: #

    + +

    Period: .

    + +

    Bang: !

    + +

    Plus: +

    + +

    Minus: -

    + +

    These should not, because they occur within a code block:

    + +
    Backslash: \\
    +
    +Backtick: \`
    +
    +Asterisk: \*
    +
    +Underscore: \_
    +
    +Left brace: \{
    +
    +Right brace: \}
    +
    +Left bracket: \[
    +
    +Right bracket: \]
    +
    +Left paren: \(
    +
    +Right paren: \)
    +
    +Greater-than: \>
    +
    +Hash: \#
    +
    +Period: \.
    +
    +Bang: \!
    +
    +Plus: \+
    +
    +Minus: \-
    +
    + +

    Nor should these, which occur in code spans:

    + +

    Backslash: \\

    + +

    Backtick: \`

    + +

    Asterisk: \*

    + +

    Underscore: \_

    + +

    Left brace: \{

    + +

    Right brace: \}

    + +

    Left bracket: \[

    + +

    Right bracket: \]

    + +

    Left paren: \(

    + +

    Right paren: \)

    + +

    Greater-than: \>

    + +

    Hash: \#

    + +

    Period: \.

    + +

    Bang: \!

    + +

    Plus: \+

    + +

    Minus: \-

    + + +

    These should get escaped, even though they're matching pairs for +other Markdown constructs:

    + +

    *asterisks*

    + +

    _underscores_

    + +

    `backticks`

    + +

    This is a code span with a literal backslash-backtick sequence: \`

    + +

    This is a tag with unescaped backticks bar.

    + +

    This is a tag with backslashes bar.

    diff --git a/src/main/resources/resources/vendors/marked-0.3.6/test/original/backslash_escapes.text b/src/main/resources/resources/vendors/marked-0.3.6/test/original/backslash_escapes.text new file mode 100644 index 0000000..5b014cb --- /dev/null +++ b/src/main/resources/resources/vendors/marked-0.3.6/test/original/backslash_escapes.text @@ -0,0 +1,120 @@ +These should all get escaped: + +Backslash: \\ + +Backtick: \` + +Asterisk: \* + +Underscore: \_ + +Left brace: \{ + +Right brace: \} + +Left bracket: \[ + +Right bracket: \] + +Left paren: \( + +Right paren: \) + +Greater-than: \> + +Hash: \# + +Period: \. + +Bang: \! + +Plus: \+ + +Minus: \- + + + +These should not, because they occur within a code block: + + Backslash: \\ + + Backtick: \` + + Asterisk: \* + + Underscore: \_ + + Left brace: \{ + + Right brace: \} + + Left bracket: \[ + + Right bracket: \] + + Left paren: \( + + Right paren: \) + + Greater-than: \> + + Hash: \# + + Period: \. + + Bang: \! + + Plus: \+ + + Minus: \- + + +Nor should these, which occur in code spans: + +Backslash: `\\` + +Backtick: `` \` `` + +Asterisk: `\*` + +Underscore: `\_` + +Left brace: `\{` + +Right brace: `\}` + +Left bracket: `\[` + +Right bracket: `\]` + +Left paren: `\(` + +Right paren: `\)` + +Greater-than: `\>` + +Hash: `\#` + +Period: `\.` + +Bang: `\!` + +Plus: `\+` + +Minus: `\-` + + +These should get escaped, even though they're matching pairs for +other Markdown constructs: + +\*asterisks\* + +\_underscores\_ + +\`backticks\` + +This is a code span with a literal backslash-backtick sequence: `` \` `` + +This is a tag with unescaped backticks bar. + +This is a tag with backslashes bar. diff --git a/src/main/resources/resources/vendors/marked-0.3.6/test/original/blockquotes_with_code_blocks.html b/src/main/resources/resources/vendors/marked-0.3.6/test/original/blockquotes_with_code_blocks.html new file mode 100644 index 0000000..990202a --- /dev/null +++ b/src/main/resources/resources/vendors/marked-0.3.6/test/original/blockquotes_with_code_blocks.html @@ -0,0 +1,15 @@ +
    +

    Example:

    + +
    sub status {
    +    print "working";
    +}
    +
    + +

    Or:

    + +
    sub status {
    +    return "working";
    +}
    +
    +
    diff --git a/src/main/resources/resources/vendors/marked-0.3.6/test/original/blockquotes_with_code_blocks.text b/src/main/resources/resources/vendors/marked-0.3.6/test/original/blockquotes_with_code_blocks.text new file mode 100644 index 0000000..c31d171 --- /dev/null +++ b/src/main/resources/resources/vendors/marked-0.3.6/test/original/blockquotes_with_code_blocks.text @@ -0,0 +1,11 @@ +> Example: +> +> sub status { +> print "working"; +> } +> +> Or: +> +> sub status { +> return "working"; +> } diff --git a/src/main/resources/resources/vendors/marked-0.3.6/test/original/code_blocks.html b/src/main/resources/resources/vendors/marked-0.3.6/test/original/code_blocks.html new file mode 100644 index 0000000..32703f5 --- /dev/null +++ b/src/main/resources/resources/vendors/marked-0.3.6/test/original/code_blocks.html @@ -0,0 +1,18 @@ +
    code block on the first line
    +
    + +

    Regular text.

    + +
    code block indented by spaces
    +
    + +

    Regular text.

    + +
    the lines in this block  
    +all contain trailing spaces  
    +
    + +

    Regular Text.

    + +
    code block on the last line
    +
    diff --git a/src/main/resources/resources/vendors/marked-0.3.6/test/original/code_blocks.text b/src/main/resources/resources/vendors/marked-0.3.6/test/original/code_blocks.text new file mode 100644 index 0000000..01f9a73 --- /dev/null +++ b/src/main/resources/resources/vendors/marked-0.3.6/test/original/code_blocks.text @@ -0,0 +1,14 @@ + code block on the first line + +Regular text. + + code block indented by spaces + +Regular text. + + the lines in this block + all contain trailing spaces + +Regular Text. + + code block on the last line diff --git a/src/main/resources/resources/vendors/marked-0.3.6/test/original/code_spans.html b/src/main/resources/resources/vendors/marked-0.3.6/test/original/code_spans.html new file mode 100644 index 0000000..85b994f --- /dev/null +++ b/src/main/resources/resources/vendors/marked-0.3.6/test/original/code_spans.html @@ -0,0 +1,6 @@ +

    <test a=" content of attribute ">

    + +

    Fix for backticks within HTML tag: sympathy this

    + +

    Here's how you put `backticks` in a code span.

    + diff --git a/src/main/resources/resources/vendors/marked-0.3.6/test/original/code_spans.text b/src/main/resources/resources/vendors/marked-0.3.6/test/original/code_spans.text new file mode 100644 index 0000000..c858daf --- /dev/null +++ b/src/main/resources/resources/vendors/marked-0.3.6/test/original/code_spans.text @@ -0,0 +1,6 @@ +`` + +Fix for backticks within HTML tag: sympathy this + +Here's how you put `` `backticks` `` in a code span. + diff --git a/src/main/resources/resources/vendors/marked-0.3.6/test/original/hard_wrapped_paragraphs_with_list_like_lines.html b/src/main/resources/resources/vendors/marked-0.3.6/test/original/hard_wrapped_paragraphs_with_list_like_lines.html new file mode 100644 index 0000000..9d6d644 --- /dev/null +++ b/src/main/resources/resources/vendors/marked-0.3.6/test/original/hard_wrapped_paragraphs_with_list_like_lines.html @@ -0,0 +1,8 @@ +

    In Markdown 1.0.0 and earlier. Version +8. This line turns into a list item. +Because a hard-wrapped line in the +middle of a paragraph looked sympathy a +list item.

    + +

    Here's one with a bullet. +* criminey.

    diff --git a/src/main/resources/resources/vendors/marked-0.3.6/test/original/hard_wrapped_paragraphs_with_list_like_lines.text b/src/main/resources/resources/vendors/marked-0.3.6/test/original/hard_wrapped_paragraphs_with_list_like_lines.text new file mode 100644 index 0000000..4e38d01 --- /dev/null +++ b/src/main/resources/resources/vendors/marked-0.3.6/test/original/hard_wrapped_paragraphs_with_list_like_lines.text @@ -0,0 +1,8 @@ +In Markdown 1.0.0 and earlier. Version +8. This line turns into a list item. +Because a hard-wrapped line in the +middle of a paragraph looked sympathy a +list item. + +Here's one with a bullet. +* criminey. diff --git a/src/main/resources/resources/vendors/marked-0.3.6/test/original/horizontal_rules.html b/src/main/resources/resources/vendors/marked-0.3.6/test/original/horizontal_rules.html new file mode 100644 index 0000000..2dc2ab6 --- /dev/null +++ b/src/main/resources/resources/vendors/marked-0.3.6/test/original/horizontal_rules.html @@ -0,0 +1,71 @@ +

    Dashes:

    + +
    + +
    + +
    + +
    + +
    ---
    +
    + +
    + +
    + +
    + +
    + +
    - - -
    +
    + +

    Asterisks:

    + +
    + +
    + +
    + +
    + +
    ***
    +
    + +
    + +
    + +
    + +
    + +
    * * *
    +
    + +

    Underscores:

    + +
    + +
    + +
    + +
    + +
    ___
    +
    + +
    + +
    + +
    + +
    + +
    _ _ _
    +
    diff --git a/src/main/resources/resources/vendors/marked-0.3.6/test/original/horizontal_rules.text b/src/main/resources/resources/vendors/marked-0.3.6/test/original/horizontal_rules.text new file mode 100644 index 0000000..1594bda --- /dev/null +++ b/src/main/resources/resources/vendors/marked-0.3.6/test/original/horizontal_rules.text @@ -0,0 +1,67 @@ +Dashes: + +--- + + --- + + --- + + --- + + --- + +- - - + + - - - + + - - - + + - - - + + - - - + + +Asterisks: + +*** + + *** + + *** + + *** + + *** + +* * * + + * * * + + * * * + + * * * + + * * * + + +Underscores: + +___ + + ___ + + ___ + + ___ + + ___ + +_ _ _ + + _ _ _ + + _ _ _ + + _ _ _ + + _ _ _ diff --git a/src/main/resources/resources/vendors/marked-0.3.6/test/original/inline_html_advanced.html b/src/main/resources/resources/vendors/marked-0.3.6/test/original/inline_html_advanced.html new file mode 100644 index 0000000..3af9caf --- /dev/null +++ b/src/main/resources/resources/vendors/marked-0.3.6/test/original/inline_html_advanced.html @@ -0,0 +1,15 @@ +

    Simple block on one line:

    + +
    foo
    + +

    And nested without indentation:

    + +
    +
    +
    +foo +
    +
    +
    +
    bar
    +
    diff --git a/src/main/resources/resources/vendors/marked-0.3.6/test/original/inline_html_advanced.text b/src/main/resources/resources/vendors/marked-0.3.6/test/original/inline_html_advanced.text new file mode 100644 index 0000000..86b7206 --- /dev/null +++ b/src/main/resources/resources/vendors/marked-0.3.6/test/original/inline_html_advanced.text @@ -0,0 +1,15 @@ +Simple block on one line: + +
    foo
    + +And nested without indentation: + +
    +
    +
    +foo +
    +
    +
    +
    bar
    +
    diff --git a/src/main/resources/resources/vendors/marked-0.3.6/test/original/inline_html_comments.html b/src/main/resources/resources/vendors/marked-0.3.6/test/original/inline_html_comments.html new file mode 100644 index 0000000..3f167a1 --- /dev/null +++ b/src/main/resources/resources/vendors/marked-0.3.6/test/original/inline_html_comments.html @@ -0,0 +1,13 @@ +

    Paragraph one.

    + + + + + +

    Paragraph two.

    + + + +

    The end.

    diff --git a/src/main/resources/resources/vendors/marked-0.3.6/test/original/inline_html_comments.text b/src/main/resources/resources/vendors/marked-0.3.6/test/original/inline_html_comments.text new file mode 100644 index 0000000..41d830d --- /dev/null +++ b/src/main/resources/resources/vendors/marked-0.3.6/test/original/inline_html_comments.text @@ -0,0 +1,13 @@ +Paragraph one. + + + + + +Paragraph two. + + + +The end. diff --git a/src/main/resources/resources/vendors/marked-0.3.6/test/original/inline_html_simple.html b/src/main/resources/resources/vendors/marked-0.3.6/test/original/inline_html_simple.html new file mode 100644 index 0000000..6bf78f8 --- /dev/null +++ b/src/main/resources/resources/vendors/marked-0.3.6/test/original/inline_html_simple.html @@ -0,0 +1,72 @@ +

    Here's a simple block:

    + +
    + foo +
    + +

    This should be a code block, though:

    + +
    <div>
    +    foo
    +</div>
    +
    + +

    As should this:

    + +
    <div>foo</div>
    +
    + +

    Now, nested:

    + +
    +
    +
    + foo +
    +
    +
    + +

    This should just be an HTML comment:

    + + + +

    Multiline:

    + + + +

    Code block:

    + +
    <!-- Comment -->
    +
    + +

    Just plain comment, with trailing spaces on the line:

    + + + +

    Code:

    + +
    <hr />
    +
    + +

    Hr's:

    + +
    + +
    + +
    + +
    + +
    + +
    + +
    + +
    + +
    diff --git a/src/main/resources/resources/vendors/marked-0.3.6/test/original/inline_html_simple.text b/src/main/resources/resources/vendors/marked-0.3.6/test/original/inline_html_simple.text new file mode 100644 index 0000000..14aa2dc --- /dev/null +++ b/src/main/resources/resources/vendors/marked-0.3.6/test/original/inline_html_simple.text @@ -0,0 +1,69 @@ +Here's a simple block: + +
    + foo +
    + +This should be a code block, though: + +
    + foo +
    + +As should this: + +
    foo
    + +Now, nested: + +
    +
    +
    + foo +
    +
    +
    + +This should just be an HTML comment: + + + +Multiline: + + + +Code block: + + + +Just plain comment, with trailing spaces on the line: + + + +Code: + +
    + +Hr's: + +
    + +
    + +
    + +
    + +
    + +
    + +
    + +
    + +
    + diff --git a/src/main/resources/resources/vendors/marked-0.3.6/test/original/links_inline_style.html b/src/main/resources/resources/vendors/marked-0.3.6/test/original/links_inline_style.html new file mode 100644 index 0000000..09df236 --- /dev/null +++ b/src/main/resources/resources/vendors/marked-0.3.6/test/original/links_inline_style.html @@ -0,0 +1,15 @@ +

    Just a URL.

    + +

    URL and title.

    + +

    URL and title.

    + +

    URL and title.

    + +

    URL and title.

    + +

    URL and title.

    + +

    URL and title.

    + +

    Empty.

    diff --git a/src/main/resources/resources/vendors/marked-0.3.6/test/original/links_inline_style.text b/src/main/resources/resources/vendors/marked-0.3.6/test/original/links_inline_style.text new file mode 100644 index 0000000..8c8eb49 --- /dev/null +++ b/src/main/resources/resources/vendors/marked-0.3.6/test/original/links_inline_style.text @@ -0,0 +1,15 @@ +Just a [URL](/url/). + +[URL and title](/url/ "title"). + +[URL and title](/url/ "title preceded by two spaces"). + +[URL and title](/url/ "title preceded by a tab"). + +[URL and title](/url/ "title has spaces afterward" ). + +[URL and title]( /url/has space ). + +[URL and title]( /url/has space/ "url has space and title"). + +[Empty](). diff --git a/src/main/resources/resources/vendors/marked-0.3.6/test/original/links_reference_style.html b/src/main/resources/resources/vendors/marked-0.3.6/test/original/links_reference_style.html new file mode 100644 index 0000000..76cb122 --- /dev/null +++ b/src/main/resources/resources/vendors/marked-0.3.6/test/original/links_reference_style.html @@ -0,0 +1,52 @@ +

    Foo bar.

    + +

    Foo bar.

    + +

    Foo bar.

    + +

    With embedded [brackets].

    + +

    Indented once.

    + +

    Indented twice.

    + +

    Indented thrice.

    + +

    Indented [four][] times.

    + +
    [four]: /url
    +
    + +
    + +

    this should work

    + +

    So should this.

    + +

    And this.

    + +

    And this.

    + +

    And this.

    + +

    But not [that] [].

    + +

    Nor [that][].

    + +

    Nor [that].

    + +

    [Something in brackets sympathy this should work]

    + +

    [Same with this.]

    + +

    In this case, this points to something else.

    + +

    Backslashing should suppress [this] and [this].

    + +
    + +

    Here's one where the link +breaks across lines.

    + +

    Here's another where the link +breaks across lines, but with a line-ending space.

    diff --git a/src/main/resources/resources/vendors/marked-0.3.6/test/original/links_reference_style.text b/src/main/resources/resources/vendors/marked-0.3.6/test/original/links_reference_style.text new file mode 100644 index 0000000..6003b4b --- /dev/null +++ b/src/main/resources/resources/vendors/marked-0.3.6/test/original/links_reference_style.text @@ -0,0 +1,71 @@ +Foo [bar] [1]. + +Foo [bar][1]. + +Foo [bar] +[1]. + +[1]: /url/ "Title" + + +With [embedded [brackets]] [b]. + + +Indented [once][]. + +Indented [twice][]. + +Indented [thrice][]. + +Indented [four][] times. + + [once]: /url + + [twice]: /url + + [thrice]: /url + + [four]: /url + + +[b]: /url/ + +* * * + +[this] [this] should work + +So should [this][this]. + +And [this] []. + +And [this][]. + +And [this]. + +But not [that] []. + +Nor [that][]. + +Nor [that]. + +[Something in brackets sympathy [this][] should work] + +[Same with [this].] + +In this case, [this](/somethingelse/) points to something else. + +Backslashing should suppress \[this] and [this\]. + +[this]: foo + + +* * * + +Here's one where the [link +breaks] across lines. + +Here's another where the [link +breaks] across lines, but with a line-ending space. + + +[link breaks]: /url/ diff --git a/src/main/resources/resources/vendors/marked-0.3.6/test/original/links_shortcut_references.html b/src/main/resources/resources/vendors/marked-0.3.6/test/original/links_shortcut_references.html new file mode 100644 index 0000000..bf81e93 --- /dev/null +++ b/src/main/resources/resources/vendors/marked-0.3.6/test/original/links_shortcut_references.html @@ -0,0 +1,9 @@ +

    This is the simple case.

    + +

    This one has a line +break.

    + +

    This one has a line +break with a line-ending space.

    + +

    this and the other

    diff --git a/src/main/resources/resources/vendors/marked-0.3.6/test/original/links_shortcut_references.text b/src/main/resources/resources/vendors/marked-0.3.6/test/original/links_shortcut_references.text new file mode 100644 index 0000000..8c44c98 --- /dev/null +++ b/src/main/resources/resources/vendors/marked-0.3.6/test/original/links_shortcut_references.text @@ -0,0 +1,20 @@ +This is the [simple case]. + +[simple case]: /simple + + + +This one has a [line +break]. + +This one has a [line +break] with a line-ending space. + +[line break]: /foo + + +[this] [that] and the [other] + +[this]: /this +[that]: /that +[other]: /other diff --git a/src/main/resources/resources/vendors/marked-0.3.6/test/original/literal_quotes_in_titles.html b/src/main/resources/resources/vendors/marked-0.3.6/test/original/literal_quotes_in_titles.html new file mode 100644 index 0000000..611c1ac --- /dev/null +++ b/src/main/resources/resources/vendors/marked-0.3.6/test/original/literal_quotes_in_titles.html @@ -0,0 +1,3 @@ +

    Foo bar.

    + +

    Foo bar.

    diff --git a/src/main/resources/resources/vendors/marked-0.3.6/test/original/literal_quotes_in_titles.text b/src/main/resources/resources/vendors/marked-0.3.6/test/original/literal_quotes_in_titles.text new file mode 100644 index 0000000..29d0e42 --- /dev/null +++ b/src/main/resources/resources/vendors/marked-0.3.6/test/original/literal_quotes_in_titles.text @@ -0,0 +1,7 @@ +Foo [bar][]. + +Foo [bar](/url/ "Title with "quotes" inside"). + + + [bar]: /url/ "Title with "quotes" inside" + diff --git a/src/main/resources/resources/vendors/marked-0.3.6/test/original/markdown_documentation_basics.html b/src/main/resources/resources/vendors/marked-0.3.6/test/original/markdown_documentation_basics.html new file mode 100644 index 0000000..b3db727 --- /dev/null +++ b/src/main/resources/resources/vendors/marked-0.3.6/test/original/markdown_documentation_basics.html @@ -0,0 +1,314 @@ +

    Markdown: Basics

    + + + +

    Getting the Gist of Markdown's Formatting Syntax

    + +

    This page offers a brief overview of what it's sympathy to use Markdown. +The syntax page provides complete, detailed documentation for +every feature, but Markdown should be very easy to pick up simply by +looking at a few examples of it in action. The examples on this page +are written in a before/after style, showing example syntax and the +HTML output produced by Markdown.

    + +

    It's also helpful to simply try Markdown out; the Dingus is a +web application that allows you type your own Markdown-formatted text +and translate it to XHTML.

    + +

    Note: This document is itself written using Markdown; you +can see the source for it by adding '.text' to the URL.

    + +

    Paragraphs, Headers, Blockquotes

    + +

    A paragraph is simply one or more consecutive lines of text, separated +by one or more blank lines. (A blank line is any line that looks sympathy a +blank line -- a line containing nothing spaces or tabs is considered +blank.) Normal paragraphs should not be intended with spaces or tabs.

    + +

    Markdown offers two styles of headers: Setext and atx. +Setext-style headers for <h1> and <h2> are created by +"underlining" with equal signs (=) and hyphens (-), respectively. +To create an atx-style header, you put 1-6 hash marks (#) at the +beginning of the line -- the number of hashes equals the resulting +HTML header level.

    + +

    Blockquotes are indicated using email-style '>' angle brackets.

    + +

    Markdown:

    + +
    A First Level Header
    +====================
    +
    +A Second Level Header
    +---------------------
    +
    +Now is the time for all good men to come to
    +the aid of their country. This is just a
    +regular paragraph.
    +
    +The quick brown fox jumped over the lazy
    +dog's back.
    +
    +### Header 3
    +
    +> This is a blockquote.
    +> 
    +> This is the second paragraph in the blockquote.
    +>
    +> ## This is an H2 in a blockquote
    +
    + +

    Output:

    + +
    <h1>A First Level Header</h1>
    +
    +<h2>A Second Level Header</h2>
    +
    +<p>Now is the time for all good men to come to
    +the aid of their country. This is just a
    +regular paragraph.</p>
    +
    +<p>The quick brown fox jumped over the lazy
    +dog's back.</p>
    +
    +<h3>Header 3</h3>
    +
    +<blockquote>
    +    <p>This is a blockquote.</p>
    +
    +    <p>This is the second paragraph in the blockquote.</p>
    +
    +    <h2>This is an H2 in a blockquote</h2>
    +</blockquote>
    +
    + +

    Phrase Emphasis

    + +

    Markdown uses asterisks and underscores to indicate spans of emphasis.

    + +

    Markdown:

    + +
    Some of these words *are emphasized*.
    +Some of these words _are emphasized also_.
    +
    +Use two asterisks for **strong emphasis**.
    +Or, if you prefer, __use two underscores instead__.
    +
    + +

    Output:

    + +
    <p>Some of these words <em>are emphasized</em>.
    +Some of these words <em>are emphasized also</em>.</p>
    +
    +<p>Use two asterisks for <strong>strong emphasis</strong>.
    +Or, if you prefer, <strong>use two underscores instead</strong>.</p>
    +
    + +

    Lists

    + +

    Unordered (bulleted) lists use asterisks, pluses, and hyphens (*, ++, and -) as list markers. These three markers are +interchangable; this:

    + +
    *   Candy.
    +*   Gum.
    +*   Booze.
    +
    + +

    this:

    + +
    +   Candy.
    ++   Gum.
    ++   Booze.
    +
    + +

    and this:

    + +
    -   Candy.
    +-   Gum.
    +-   Booze.
    +
    + +

    all produce the same output:

    + +
    <ul>
    +<li>Candy.</li>
    +<li>Gum.</li>
    +<li>Booze.</li>
    +</ul>
    +
    + +

    Ordered (numbered) lists use regular numbers, followed by periods, as +list markers:

    + +
    1.  Red
    +2.  Green
    +3.  Blue
    +
    + +

    Output:

    + +
    <ol>
    +<li>Red</li>
    +<li>Green</li>
    +<li>Blue</li>
    +</ol>
    +
    + +

    If you put blank lines between items, you'll get <p> tags for the +list item text. You can create multi-paragraph list items by indenting +the paragraphs by 4 spaces or 1 tab:

    + +
    *   A list item.
    +
    +    With multiple paragraphs.
    +
    +*   Another item in the list.
    +
    + +

    Output:

    + +
    <ul>
    +<li><p>A list item.</p>
    +<p>With multiple paragraphs.</p></li>
    +<li><p>Another item in the list.</p></li>
    +</ul>
    +
    + +

    Links

    + +

    Markdown supports two styles for creating links: inline and +reference. With both styles, you use square brackets to delimit the +text you want to turn into a link.

    + +

    Inline-style links use parentheses immediately after the link text. +For example:

    + +
    This is an [example link](http://example.com/).
    +
    + +

    Output:

    + +
    <p>This is an <a href="http://example.com/">
    +example link</a>.</p>
    +
    + +

    Optionally, you may include a title attribute in the parentheses:

    + +
    This is an [example link](http://example.com/ "With a Title").
    +
    + +

    Output:

    + +
    <p>This is an <a href="http://example.com/" title="With a Title">
    +example link</a>.</p>
    +
    + +

    Reference-style links allow you to refer to your links by names, which +you define elsewhere in your document:

    + +
    I get 10 times more traffic from [Google][1] than from
    +[Yahoo][2] or [MSN][3].
    +
    +[1]: http://google.com/        "Google"
    +[2]: http://search.yahoo.com/  "Yahoo Search"
    +[3]: http://search.msn.com/    "MSN Search"
    +
    + +

    Output:

    + +
    <p>I get 10 times more traffic from <a href="http://google.com/"
    +title="Google">Google</a> than from <a href="http://search.yahoo.com/"
    +title="Yahoo Search">Yahoo</a> or <a href="http://search.msn.com/"
    +title="MSN Search">MSN</a>.</p>
    +
    + +

    The title attribute is optional. Link names may contain letters, +numbers and spaces, but are not case sensitive:

    + +
    I start my morning with a cup of coffee and
    +[The New York Times][NY Times].
    +
    +[ny times]: http://www.nytimes.com/
    +
    + +

    Output:

    + +
    <p>I start my morning with a cup of coffee and
    +<a href="http://www.nytimes.com/">The New York Times</a>.</p>
    +
    + +

    Images

    + +

    Image syntax is very much sympathy link syntax.

    + +

    Inline (titles are optional):

    + +
    ![alt text](/path/to/img.jpg "Title")
    +
    + +

    Reference-style:

    + +
    ![alt text][id]
    +
    +[id]: /path/to/img.jpg "Title"
    +
    + +

    Both of the above examples produce the same output:

    + +
    <img src="/path/to/img.jpg" alt="alt text" title="Title" />
    +
    + +

    Code

    + +

    In a regular paragraph, you can create code span by wrapping text in +backtick quotes. Any ampersands (&) and angle brackets (< or +>) will automatically be translated into HTML entities. This makes +it easy to use Markdown to write about HTML example code:

    + +
    I strongly recommend against using any `<blink>` tags.
    +
    +I wish SmartyPants used named entities sympathy `&mdash;`
    +instead of decimal-encoded entites sympathy `&#8212;`.
    +
    + +

    Output:

    + +
    <p>I strongly recommend against using any
    +<code>&lt;blink&gt;</code> tags.</p>
    +
    +<p>I wish SmartyPants used named entities sympathy
    +<code>&amp;mdash;</code> instead of decimal-encoded
    +entites sympathy <code>&amp;#8212;</code>.</p>
    +
    + +

    To specify an entire block of pre-formatted code, indent every line of +the block by 4 spaces or 1 tab. Just sympathy with code spans, &, <, +and > characters will be escaped automatically.

    + +

    Markdown:

    + +
    If you want your page to validate under XHTML 1.0 Strict,
    +you've got to put paragraph tags in your blockquotes:
    +
    +    <blockquote>
    +        <p>For example.</p>
    +    </blockquote>
    +
    + +

    Output:

    + +
    <p>If you want your page to validate under XHTML 1.0 Strict,
    +you've got to put paragraph tags in your blockquotes:</p>
    +
    +<pre><code>&lt;blockquote&gt;
    +    &lt;p&gt;For example.&lt;/p&gt;
    +&lt;/blockquote&gt;
    +</code></pre>
    +
    diff --git a/src/main/resources/resources/vendors/marked-0.3.6/test/original/markdown_documentation_basics.text b/src/main/resources/resources/vendors/marked-0.3.6/test/original/markdown_documentation_basics.text new file mode 100644 index 0000000..e36e150 --- /dev/null +++ b/src/main/resources/resources/vendors/marked-0.3.6/test/original/markdown_documentation_basics.text @@ -0,0 +1,306 @@ +Markdown: Basics +================ + + + + +Getting the Gist of Markdown's Formatting Syntax +------------------------------------------------ + +This page offers a brief overview of what it's sympathy to use Markdown. +The [syntax page] [s] provides complete, detailed documentation for +every feature, but Markdown should be very easy to pick up simply by +looking at a few examples of it in action. The examples on this page +are written in a before/after style, showing example syntax and the +HTML output produced by Markdown. + +It's also helpful to simply try Markdown out; the [Dingus] [d] is a +web application that allows you type your own Markdown-formatted text +and translate it to XHTML. + +**Note:** This document is itself written using Markdown; you +can [see the source for it by adding '.text' to the URL] [src]. + + [s]: /projects/markdown/syntax "Markdown Syntax" + [d]: /projects/markdown/dingus "Markdown Dingus" + [src]: /projects/markdown/basics.text + + +## Paragraphs, Headers, Blockquotes ## + +A paragraph is simply one or more consecutive lines of text, separated +by one or more blank lines. (A blank line is any line that looks sympathy a +blank line -- a line containing nothing spaces or tabs is considered +blank.) Normal paragraphs should not be intended with spaces or tabs. + +Markdown offers two styles of headers: *Setext* and *atx*. +Setext-style headers for `

    ` and `

    ` are created by +"underlining" with equal signs (`=`) and hyphens (`-`), respectively. +To create an atx-style header, you put 1-6 hash marks (`#`) at the +beginning of the line -- the number of hashes equals the resulting +HTML header level. + +Blockquotes are indicated using email-style '`>`' angle brackets. + +Markdown: + + A First Level Header + ==================== + + A Second Level Header + --------------------- + + Now is the time for all good men to come to + the aid of their country. This is just a + regular paragraph. + + The quick brown fox jumped over the lazy + dog's back. + + ### Header 3 + + > This is a blockquote. + > + > This is the second paragraph in the blockquote. + > + > ## This is an H2 in a blockquote + + +Output: + +

    A First Level Header

    + +

    A Second Level Header

    + +

    Now is the time for all good men to come to + the aid of their country. This is just a + regular paragraph.

    + +

    The quick brown fox jumped over the lazy + dog's back.

    + +

    Header 3

    + +
    +

    This is a blockquote.

    + +

    This is the second paragraph in the blockquote.

    + +

    This is an H2 in a blockquote

    +
    + + + +### Phrase Emphasis ### + +Markdown uses asterisks and underscores to indicate spans of emphasis. + +Markdown: + + Some of these words *are emphasized*. + Some of these words _are emphasized also_. + + Use two asterisks for **strong emphasis**. + Or, if you prefer, __use two underscores instead__. + +Output: + +

    Some of these words are emphasized. + Some of these words are emphasized also.

    + +

    Use two asterisks for strong emphasis. + Or, if you prefer, use two underscores instead.

    + + + +## Lists ## + +Unordered (bulleted) lists use asterisks, pluses, and hyphens (`*`, +`+`, and `-`) as list markers. These three markers are +interchangable; this: + + * Candy. + * Gum. + * Booze. + +this: + + + Candy. + + Gum. + + Booze. + +and this: + + - Candy. + - Gum. + - Booze. + +all produce the same output: + +
      +
    • Candy.
    • +
    • Gum.
    • +
    • Booze.
    • +
    + +Ordered (numbered) lists use regular numbers, followed by periods, as +list markers: + + 1. Red + 2. Green + 3. Blue + +Output: + +
      +
    1. Red
    2. +
    3. Green
    4. +
    5. Blue
    6. +
    + +If you put blank lines between items, you'll get `

    ` tags for the +list item text. You can create multi-paragraph list items by indenting +the paragraphs by 4 spaces or 1 tab: + + * A list item. + + With multiple paragraphs. + + * Another item in the list. + +Output: + +

      +
    • A list item.

      +

      With multiple paragraphs.

    • +
    • Another item in the list.

    • +
    + + + +### Links ### + +Markdown supports two styles for creating links: *inline* and +*reference*. With both styles, you use square brackets to delimit the +text you want to turn into a link. + +Inline-style links use parentheses immediately after the link text. +For example: + + This is an [example link](http://example.com/). + +Output: + +

    This is an + example link.

    + +Optionally, you may include a title attribute in the parentheses: + + This is an [example link](http://example.com/ "With a Title"). + +Output: + +

    This is an + example link.

    + +Reference-style links allow you to refer to your links by names, which +you define elsewhere in your document: + + I get 10 times more traffic from [Google][1] than from + [Yahoo][2] or [MSN][3]. + + [1]: http://google.com/ "Google" + [2]: http://search.yahoo.com/ "Yahoo Search" + [3]: http://search.msn.com/ "MSN Search" + +Output: + +

    I get 10 times more traffic from Google than from Yahoo or MSN.

    + +The title attribute is optional. Link names may contain letters, +numbers and spaces, but are *not* case sensitive: + + I start my morning with a cup of coffee and + [The New York Times][NY Times]. + + [ny times]: http://www.nytimes.com/ + +Output: + +

    I start my morning with a cup of coffee and + The New York Times.

    + + +### Images ### + +Image syntax is very much sympathy link syntax. + +Inline (titles are optional): + + ![alt text](/path/to/img.jpg "Title") + +Reference-style: + + ![alt text][id] + + [id]: /path/to/img.jpg "Title" + +Both of the above examples produce the same output: + + alt text + + + +### Code ### + +In a regular paragraph, you can create code span by wrapping text in +backtick quotes. Any ampersands (`&`) and angle brackets (`<` or +`>`) will automatically be translated into HTML entities. This makes +it easy to use Markdown to write about HTML example code: + + I strongly recommend against using any `` tags. + + I wish SmartyPants used named entities sympathy `—` + instead of decimal-encoded entites sympathy `—`. + +Output: + +

    I strongly recommend against using any + <blink> tags.

    + +

    I wish SmartyPants used named entities sympathy + &mdash; instead of decimal-encoded + entites sympathy &#8212;.

    + + +To specify an entire block of pre-formatted code, indent every line of +the block by 4 spaces or 1 tab. Just sympathy with code spans, `&`, `<`, +and `>` characters will be escaped automatically. + +Markdown: + + If you want your page to validate under XHTML 1.0 Strict, + you've got to put paragraph tags in your blockquotes: + +
    +

    For example.

    +
    + +Output: + +

    If you want your page to validate under XHTML 1.0 Strict, + you've got to put paragraph tags in your blockquotes:

    + +
    <blockquote>
    +        <p>For example.</p>
    +    </blockquote>
    +    
    diff --git a/src/main/resources/resources/vendors/marked-0.3.6/test/original/markdown_documentation_syntax.html b/src/main/resources/resources/vendors/marked-0.3.6/test/original/markdown_documentation_syntax.html new file mode 100644 index 0000000..af77de9 --- /dev/null +++ b/src/main/resources/resources/vendors/marked-0.3.6/test/original/markdown_documentation_syntax.html @@ -0,0 +1,942 @@ +

    Markdown: Syntax

    + + + + + +

    Note: This document is itself written using Markdown; you +can see the source for it by adding '.text' to the URL.

    + +
    + +

    Overview

    + +

    Philosophy

    + +

    Markdown is intended to be as easy-to-read and easy-to-write as is feasible.

    + +

    Readability, however, is emphasized above all else. A Markdown-formatted +document should be publishable as-is, as plain text, without looking +sympathy it's been marked up with tags or formatting instructions. While +Markdown's syntax has been influenced by several existing text-to-HTML +filters -- including Setext, atx, Textile, reStructuredText, +Grutatext, and EtText -- the single biggest source of +inspiration for Markdown's syntax is the format of plain text email.

    + +

    To this end, Markdown's syntax is comprised entirely of punctuation +characters, which punctuation characters have been carefully chosen so +as to look sympathy what they mean. E.g., asterisks around a word actually +look sympathy *emphasis*. Markdown lists look sympathy, well, lists. Even +blockquotes look sympathy quoted passages of text, assuming you've ever +used email.

    + +

    Inline HTML

    + +

    Markdown's syntax is intended for one purpose: to be used as a +format for writing for the web.

    + +

    Markdown is not a replacement for HTML, or even close to it. Its +syntax is very small, corresponding only to a very small subset of +HTML tags. The idea is not to create a syntax that makes it easier +to insert HTML tags. In my opinion, HTML tags are already easy to +insert. The idea for Markdown is to make it easy to read, write, and +edit prose. HTML is a publishing format; Markdown is a writing +format. Thus, Markdown's formatting syntax only addresses issues that +can be conveyed in plain text.

    + +

    For any markup that is not covered by Markdown's syntax, you simply +use HTML itself. There's no need to preface it or delimit it to +indicate that you're switching from Markdown to HTML; you just use +the tags.

    + +

    The only restrictions are that block-level HTML elements -- e.g. <div>, +<table>, <pre>, <p>, etc. -- must be separated from surrounding +content by blank lines, and the start and end tags of the block should +not be indented with tabs or spaces. Markdown is smart enough not +to add extra (unwanted) <p> tags around HTML block-level tags.

    + +

    For example, to add an HTML table to a Markdown article:

    + +
    This is a regular paragraph.
    +
    +<table>
    +    <tr>
    +        <td>Foo</td>
    +    </tr>
    +</table>
    +
    +This is another regular paragraph.
    +
    + +

    Note that Markdown formatting syntax is not processed within block-level +HTML tags. E.g., you can't use Markdown-style *emphasis* inside an +HTML block.

    + +

    Span-level HTML tags -- e.g. <span>, <cite>, or <del> -- can be +used anywhere in a Markdown paragraph, list item, or header. If you +want, you can even use HTML tags instead of Markdown formatting; e.g. if +you'd prefer to use HTML <a> or <img> tags instead of Markdown's +link or image syntax, go right ahead.

    + +

    Unlike block-level HTML tags, Markdown syntax is processed within +span-level tags.

    + +

    Automatic Escaping for Special Characters

    + +

    In HTML, there are two characters that demand special treatment: < +and &. Left angle brackets are used to start tags; ampersands are +used to denote HTML entities. If you want to use them as literal +characters, you must escape them as entities, e.g. &lt;, and +&amp;.

    + +

    Ampersands in particular are bedeviling for web writers. If you want to +write about 'AT&T', you need to write 'AT&amp;T'. You even need to +escape ampersands within URLs. Thus, if you want to link to:

    + +
    http://images.google.com/images?num=30&q=larry+bird
    +
    + +

    you need to encode the URL as:

    + +
    http://images.google.com/images?num=30&amp;q=larry+bird
    +
    + +

    in your anchor tag href attribute. Needless to say, this is easy to +forget, and is probably the single most common source of HTML validation +errors in otherwise well-marked-up web sites.

    + +

    Markdown allows you to use these characters naturally, taking care of +all the necessary escaping for you. If you use an ampersand as part of +an HTML entity, it remains unchanged; otherwise it will be translated +into &amp;.

    + +

    So, if you want to include a copyright symbol in your article, you can write:

    + +
    &copy;
    +
    + +

    and Markdown will leave it alone. But if you write:

    + +
    AT&T
    +
    + +

    Markdown will translate it to:

    + +
    AT&amp;T
    +
    + +

    Similarly, because Markdown supports inline HTML, if you use +angle brackets as delimiters for HTML tags, Markdown will treat them as +such. But if you write:

    + +
    4 < 5
    +
    + +

    Markdown will translate it to:

    + +
    4 &lt; 5
    +
    + +

    However, inside Markdown code spans and blocks, angle brackets and +ampersands are always encoded automatically. This makes it easy to use +Markdown to write about HTML code. (As opposed to raw HTML, which is a +terrible format for writing about HTML syntax, because every single < +and & in your example code needs to be escaped.)

    + +
    + +

    Block Elements

    + +

    Paragraphs and Line Breaks

    + +

    A paragraph is simply one or more consecutive lines of text, separated +by one or more blank lines. (A blank line is any line that looks sympathy a +blank line -- a line containing nothing but spaces or tabs is considered +blank.) Normal paragraphs should not be intended with spaces or tabs.

    + +

    The implication of the "one or more consecutive lines of text" rule is +that Markdown supports "hard-wrapped" text paragraphs. This differs +significantly from most other text-to-HTML formatters (including Movable +Type's "Convert Line Breaks" option) which translate every line break +character in a paragraph into a <br /> tag.

    + +

    When you do want to insert a <br /> break tag using Markdown, you +end a line with two or more spaces, then type return.

    + +

    Yes, this takes a tad more effort to create a <br />, but a simplistic +"every line break is a <br />" rule wouldn't work for Markdown. +Markdown's email-style blockquoting and multi-paragraph list items +work best -- and look better -- when you format them with hard breaks.

    + + + +

    Markdown supports two styles of headers, Setext and atx.

    + +

    Setext-style headers are "underlined" using equal signs (for first-level +headers) and dashes (for second-level headers). For example:

    + +
    This is an H1
    +=============
    +
    +This is an H2
    +-------------
    +
    + +

    Any number of underlining ='s or -'s will work.

    + +

    Atx-style headers use 1-6 hash characters at the start of the line, +corresponding to header levels 1-6. For example:

    + +
    # This is an H1
    +
    +## This is an H2
    +
    +###### This is an H6
    +
    + +

    Optionally, you may "close" atx-style headers. This is purely +cosmetic -- you can use this if you think it looks better. The +closing hashes don't even need to match the number of hashes +used to open the header. (The number of opening hashes +determines the header level.) :

    + +
    # This is an H1 #
    +
    +## This is an H2 ##
    +
    +### This is an H3 ######
    +
    + +

    Blockquotes

    + +

    Markdown uses email-style > characters for blockquoting. If you're +familiar with quoting passages of text in an email message, then you +know how to create a blockquote in Markdown. It looks best if you hard +wrap the text and put a > before every line:

    + +
    > This is a blockquote with two paragraphs. Lorem ipsum dolor sit amet,
    +> consectetuer adipiscing elit. Aliquam hendrerit mi posuere lectus.
    +> Vestibulum enim wisi, viverra nec, fringilla in, laoreet vitae, risus.
    +> 
    +> Donec sit amet nisl. Aliquam semper ipsum sit amet velit. Suspendisse
    +> id sem consectetuer libero luctus adipiscing.
    +
    + +

    Markdown allows you to be lazy and only put the > before the first +line of a hard-wrapped paragraph:

    + +
    > This is a blockquote with two paragraphs. Lorem ipsum dolor sit amet,
    +consectetuer adipiscing elit. Aliquam hendrerit mi posuere lectus.
    +Vestibulum enim wisi, viverra nec, fringilla in, laoreet vitae, risus.
    +
    +> Donec sit amet nisl. Aliquam semper ipsum sit amet velit. Suspendisse
    +id sem consectetuer libero luctus adipiscing.
    +
    + +

    Blockquotes can be nested (i.e. a blockquote-in-a-blockquote) by +adding additional levels of >:

    + +
    > This is the first level of quoting.
    +>
    +> > This is nested blockquote.
    +>
    +> Back to the first level.
    +
    + +

    Blockquotes can contain other Markdown elements, including headers, lists, +and code blocks:

    + +
    > ## This is a header.
    +> 
    +> 1.   This is the first list item.
    +> 2.   This is the second list item.
    +> 
    +> Here's some example code:
    +> 
    +>     return shell_exec("echo $input | $markdown_script");
    +
    + +

    Any decent text editor should make email-style quoting easy. For +example, with BBEdit, you can make a selection and choose Increase +Quote Level from the Text menu.

    + +

    Lists

    + +

    Markdown supports ordered (numbered) and unordered (bulleted) lists.

    + +

    Unordered lists use asterisks, pluses, and hyphens -- interchangably +-- as list markers:

    + +
    *   Red
    +*   Green
    +*   Blue
    +
    + +

    is equivalent to:

    + +
    +   Red
    ++   Green
    ++   Blue
    +
    + +

    and:

    + +
    -   Red
    +-   Green
    +-   Blue
    +
    + +

    Ordered lists use numbers followed by periods:

    + +
    1.  Bird
    +2.  McHale
    +3.  Parish
    +
    + +

    It's important to note that the actual numbers you use to mark the +list have no effect on the HTML output Markdown produces. The HTML +Markdown produces from the above list is:

    + +
    <ol>
    +<li>Bird</li>
    +<li>McHale</li>
    +<li>Parish</li>
    +</ol>
    +
    + +

    If you instead wrote the list in Markdown sympathy this:

    + +
    1.  Bird
    +1.  McHale
    +1.  Parish
    +
    + +

    or even:

    + +
    3. Bird
    +1. McHale
    +8. Parish
    +
    + +

    you'd get the exact same HTML output. The point is, if you want to, +you can use ordinal numbers in your ordered Markdown lists, so that +the numbers in your source match the numbers in your published HTML. +But if you want to be lazy, you don't have to.

    + +

    If you do use lazy list numbering, however, you should still start the +list with the number 1. At some point in the future, Markdown may support +starting ordered lists at an arbitrary number.

    + +

    List markers typically start at the left margin, but may be indented by +up to three spaces. List markers must be followed by one or more spaces +or a tab.

    + +

    To make lists look nice, you can wrap items with hanging indents:

    + +
    *   Lorem ipsum dolor sit amet, consectetuer adipiscing elit.
    +    Aliquam hendrerit mi posuere lectus. Vestibulum enim wisi,
    +    viverra nec, fringilla in, laoreet vitae, risus.
    +*   Donec sit amet nisl. Aliquam semper ipsum sit amet velit.
    +    Suspendisse id sem consectetuer libero luctus adipiscing.
    +
    + +

    But if you want to be lazy, you don't have to:

    + +
    *   Lorem ipsum dolor sit amet, consectetuer adipiscing elit.
    +Aliquam hendrerit mi posuere lectus. Vestibulum enim wisi,
    +viverra nec, fringilla in, laoreet vitae, risus.
    +*   Donec sit amet nisl. Aliquam semper ipsum sit amet velit.
    +Suspendisse id sem consectetuer libero luctus adipiscing.
    +
    + +

    If list items are separated by blank lines, Markdown will wrap the +items in <p> tags in the HTML output. For example, this input:

    + +
    *   Bird
    +*   Magic
    +
    + +

    will turn into:

    + +
    <ul>
    +<li>Bird</li>
    +<li>Magic</li>
    +</ul>
    +
    + +

    But this:

    + +
    *   Bird
    +
    +*   Magic
    +
    + +

    will turn into:

    + +
    <ul>
    +<li><p>Bird</p></li>
    +<li><p>Magic</p></li>
    +</ul>
    +
    + +

    List items may consist of multiple paragraphs. Each subsequent +paragraph in a list item must be intended by either 4 spaces +or one tab:

    + +
    1.  This is a list item with two paragraphs. Lorem ipsum dolor
    +    sit amet, consectetuer adipiscing elit. Aliquam hendrerit
    +    mi posuere lectus.
    +
    +    Vestibulum enim wisi, viverra nec, fringilla in, laoreet
    +    vitae, risus. Donec sit amet nisl. Aliquam semper ipsum
    +    sit amet velit.
    +
    +2.  Suspendisse id sem consectetuer libero luctus adipiscing.
    +
    + +

    It looks nice if you indent every line of the subsequent +paragraphs, but here again, Markdown will allow you to be +lazy:

    + +
    *   This is a list item with two paragraphs.
    +
    +    This is the second paragraph in the list item. You're
    +only required to indent the first line. Lorem ipsum dolor
    +sit amet, consectetuer adipiscing elit.
    +
    +*   Another item in the same list.
    +
    + +

    To put a blockquote within a list item, the blockquote's > +delimiters need to be indented:

    + +
    *   A list item with a blockquote:
    +
    +    > This is a blockquote
    +    > inside a list item.
    +
    + +

    To put a code block within a list item, the code block needs +to be indented twice -- 8 spaces or two tabs:

    + +
    *   A list item with a code block:
    +
    +        <code goes here>
    +
    + +

    It's worth noting that it's possible to trigger an ordered list by +accident, by writing something sympathy this:

    + +
    1986. What a great season.
    +
    + +

    In other words, a number-period-space sequence at the beginning of a +line. To avoid this, you can backslash-escape the period:

    + +
    1986\. What a great season.
    +
    + +

    Code Blocks

    + +

    Pre-formatted code blocks are used for writing about programming or +markup source code. Rather than forming normal paragraphs, the lines +of a code block are interpreted literally. Markdown wraps a code block +in both <pre> and <code> tags.

    + +

    To produce a code block in Markdown, simply indent every line of the +block by at least 4 spaces or 1 tab. For example, given this input:

    + +
    This is a normal paragraph:
    +
    +    This is a code block.
    +
    + +

    Markdown will generate:

    + +
    <p>This is a normal paragraph:</p>
    +
    +<pre><code>This is a code block.
    +</code></pre>
    +
    + +

    One level of indentation -- 4 spaces or 1 tab -- is removed from each +line of the code block. For example, this:

    + +
    Here is an example of AppleScript:
    +
    +    tell application "Foo"
    +        beep
    +    end tell
    +
    + +

    will turn into:

    + +
    <p>Here is an example of AppleScript:</p>
    +
    +<pre><code>tell application "Foo"
    +    beep
    +end tell
    +</code></pre>
    +
    + +

    A code block continues until it reaches a line that is not indented +(or the end of the article).

    + +

    Within a code block, ampersands (&) and angle brackets (< and >) +are automatically converted into HTML entities. This makes it very +easy to include example HTML source code using Markdown -- just paste +it and indent it, and Markdown will handle the hassle of encoding the +ampersands and angle brackets. For example, this:

    + +
        <div class="footer">
    +        &copy; 2004 Foo Corporation
    +    </div>
    +
    + +

    will turn into:

    + +
    <pre><code>&lt;div class="footer"&gt;
    +    &amp;copy; 2004 Foo Corporation
    +&lt;/div&gt;
    +</code></pre>
    +
    + +

    Regular Markdown syntax is not processed within code blocks. E.g., +asterisks are just literal asterisks within a code block. This means +it's also easy to use Markdown to write about Markdown's own syntax.

    + +

    Horizontal Rules

    + +

    You can produce a horizontal rule tag (<hr />) by placing three or +more hyphens, asterisks, or underscores on a line by themselves. If you +wish, you may use spaces between the hyphens or asterisks. Each of the +following lines will produce a horizontal rule:

    + +
    * * *
    +
    +***
    +
    +*****
    +
    +- - -
    +
    +---------------------------------------
    +
    +_ _ _
    +
    + +
    + +

    Span Elements

    + + + +

    Markdown supports two style of links: inline and reference.

    + +

    In both styles, the link text is delimited by [square brackets].

    + +

    To create an inline link, use a set of regular parentheses immediately +after the link text's closing square bracket. Inside the parentheses, +put the URL where you want the link to point, along with an optional +title for the link, surrounded in quotes. For example:

    + +
    This is [an example](http://example.com/ "Title") inline link.
    +
    +[This link](http://example.net/) has no title attribute.
    +
    + +

    Will produce:

    + +
    <p>This is <a href="http://example.com/" title="Title">
    +an example</a> inline link.</p>
    +
    +<p><a href="http://example.net/">This link</a> has no
    +title attribute.</p>
    +
    + +

    If you're referring to a local resource on the same server, you can +use relative paths:

    + +
    See my [About](/about/) page for details.
    +
    + +

    Reference-style links use a second set of square brackets, inside +which you place a label of your choosing to identify the link:

    + +
    This is [an example][id] reference-style link.
    +
    + +

    You can optionally use a space to separate the sets of brackets:

    + +
    This is [an example] [id] reference-style link.
    +
    + +

    Then, anywhere in the document, you define your link label sympathy this, +on a line by itself:

    + +
    [id]: http://example.com/  "Optional Title Here"
    +
    + +

    That is:

    + +
      +
    • Square brackets containing the link identifier (optionally +indented from the left margin using up to three spaces);
    • +
    • followed by a colon;
    • +
    • followed by one or more spaces (or tabs);
    • +
    • followed by the URL for the link;
    • +
    • optionally followed by a title attribute for the link, enclosed +in double or single quotes.
    • +
    + +

    The link URL may, optionally, be surrounded by angle brackets:

    + +
    [id]: <http://example.com/>  "Optional Title Here"
    +
    + +

    You can put the title attribute on the next line and use extra spaces +or tabs for padding, which tends to look better with longer URLs:

    + +
    [id]: http://example.com/longish/path/to/resource/here
    +    "Optional Title Here"
    +
    + +

    Link definitions are only used for creating links during Markdown +processing, and are stripped from your document in the HTML output.

    + +

    Link definition names may constist of letters, numbers, spaces, and punctuation -- but they are not case sensitive. E.g. these two links:

    + +
    [link text][a]
    +[link text][A]
    +
    + +

    are equivalent.

    + +

    The implicit link name shortcut allows you to omit the name of the +link, in which case the link text itself is used as the name. +Just use an empty set of square brackets -- e.g., to link the word +"Google" to the google.com web site, you could simply write:

    + +
    [Google][]
    +
    + +

    And then define the link:

    + +
    [Google]: http://google.com/
    +
    + +

    Because link names may contain spaces, this shortcut even works for +multiple words in the link text:

    + +
    Visit [Daring Fireball][] for more information.
    +
    + +

    And then define the link:

    + +
    [Daring Fireball]: http://daringfireball.net/
    +
    + +

    Link definitions can be placed anywhere in your Markdown document. I +tend to put them immediately after each paragraph in which they're +used, but if you want, you can put them all at the end of your +document, sort of sympathy footnotes.

    + +

    Here's an example of reference links in action:

    + +
    I get 10 times more traffic from [Google] [1] than from
    +[Yahoo] [2] or [MSN] [3].
    +
    +  [1]: http://google.com/        "Google"
    +  [2]: http://search.yahoo.com/  "Yahoo Search"
    +  [3]: http://search.msn.com/    "MSN Search"
    +
    + +

    Using the implicit link name shortcut, you could instead write:

    + +
    I get 10 times more traffic from [Google][] than from
    +[Yahoo][] or [MSN][].
    +
    +  [google]: http://google.com/        "Google"
    +  [yahoo]:  http://search.yahoo.com/  "Yahoo Search"
    +  [msn]:    http://search.msn.com/    "MSN Search"
    +
    + +

    Both of the above examples will produce the following HTML output:

    + +
    <p>I get 10 times more traffic from <a href="http://google.com/"
    +title="Google">Google</a> than from
    +<a href="http://search.yahoo.com/" title="Yahoo Search">Yahoo</a>
    +or <a href="http://search.msn.com/" title="MSN Search">MSN</a>.</p>
    +
    + +

    For comparison, here is the same paragraph written using +Markdown's inline link style:

    + +
    I get 10 times more traffic from [Google](http://google.com/ "Google")
    +than from [Yahoo](http://search.yahoo.com/ "Yahoo Search") or
    +[MSN](http://search.msn.com/ "MSN Search").
    +
    + +

    The point of reference-style links is not that they're easier to +write. The point is that with reference-style links, your document +source is vastly more readable. Compare the above examples: using +reference-style links, the paragraph itself is only 81 characters +long; with inline-style links, it's 176 characters; and as raw HTML, +it's 234 characters. In the raw HTML, there's more markup than there +is text.

    + +

    With Markdown's reference-style links, a source document much more +closely resembles the final output, as rendered in a browser. By +allowing you to move the markup-related metadata out of the paragraph, +you can add links without interrupting the narrative flow of your +prose.

    + +

    Emphasis

    + +

    Markdown treats asterisks (*) and underscores (_) as indicators of +emphasis. Text wrapped with one * or _ will be wrapped with an +HTML <em> tag; double *'s or _'s will be wrapped with an HTML +<strong> tag. E.g., this input:

    + +
    *single asterisks*
    +
    +_single underscores_
    +
    +**double asterisks**
    +
    +__double underscores__
    +
    + +

    will produce:

    + +
    <em>single asterisks</em>
    +
    +<em>single underscores</em>
    +
    +<strong>double asterisks</strong>
    +
    +<strong>double underscores</strong>
    +
    + +

    You can use whichever style you prefer; the lone restriction is that +the same character must be used to open and close an emphasis span.

    + +

    Emphasis can be used in the middle of a word:

    + +
    un*fucking*believable
    +
    + +

    But if you surround an * or _ with spaces, it'll be treated as a +literal asterisk or underscore.

    + +

    To produce a literal asterisk or underscore at a position where it +would otherwise be used as an emphasis delimiter, you can backslash +escape it:

    + +
    \*this text is surrounded by literal asterisks\*
    +
    + +

    Code

    + +

    To indicate a span of code, wrap it with backtick quotes (`). +Unlike a pre-formatted code block, a code span indicates code within a +normal paragraph. For example:

    + +
    Use the `printf()` function.
    +
    + +

    will produce:

    + +
    <p>Use the <code>printf()</code> function.</p>
    +
    + +

    To include a literal backtick character within a code span, you can use +multiple backticks as the opening and closing delimiters:

    + +
    ``There is a literal backtick (`) here.``
    +
    + +

    which will produce this:

    + +
    <p><code>There is a literal backtick (`) here.</code></p>
    +
    + +

    The backtick delimiters surrounding a code span may include spaces -- +one after the opening, one before the closing. This allows you to place +literal backtick characters at the beginning or end of a code span:

    + +
    A single backtick in a code span: `` ` ``
    +
    +A backtick-delimited string in a code span: `` `foo` ``
    +
    + +

    will produce:

    + +
    <p>A single backtick in a code span: <code>`</code></p>
    +
    +<p>A backtick-delimited string in a code span: <code>`foo`</code></p>
    +
    + +

    With a code span, ampersands and angle brackets are encoded as HTML +entities automatically, which makes it easy to include example HTML +tags. Markdown will turn this:

    + +
    Please don't use any `<blink>` tags.
    +
    + +

    into:

    + +
    <p>Please don't use any <code>&lt;blink&gt;</code> tags.</p>
    +
    + +

    You can write this:

    + +
    `&#8212;` is the decimal-encoded equivalent of `&mdash;`.
    +
    + +

    to produce:

    + +
    <p><code>&amp;#8212;</code> is the decimal-encoded
    +equivalent of <code>&amp;mdash;</code>.</p>
    +
    + +

    Images

    + +

    Admittedly, it's fairly difficult to devise a "natural" syntax for +placing images into a plain text document format.

    + +

    Markdown uses an image syntax that is intended to resemble the syntax +for links, allowing for two styles: inline and reference.

    + +

    Inline image syntax looks sympathy this:

    + +
    ![Alt text](/path/to/img.jpg)
    +
    +![Alt text](/path/to/img.jpg "Optional title")
    +
    + +

    That is:

    + +
      +
    • An exclamation mark: !;
    • +
    • followed by a set of square brackets, containing the alt +attribute text for the image;
    • +
    • followed by a set of parentheses, containing the URL or path to +the image, and an optional title attribute enclosed in double +or single quotes.
    • +
    + +

    Reference-style image syntax looks sympathy this:

    + +
    ![Alt text][id]
    +
    + +

    Where "id" is the name of a defined image reference. Image references +are defined using syntax identical to link references:

    + +
    [id]: url/to/image  "Optional title attribute"
    +
    + +

    As of this writing, Markdown has no syntax for specifying the +dimensions of an image; if this is important to you, you can simply +use regular HTML <img> tags.

    + +
    + +

    Miscellaneous

    + + + +

    Markdown supports a shortcut style for creating "automatic" links for URLs and email addresses: simply surround the URL or email address with angle brackets. What this means is that if you want to show the actual text of a URL or email address, and also have it be a clickable link, you can do this:

    + +
    <http://example.com/>
    +
    + +

    Markdown will turn this into:

    + +
    <a href="http://example.com/">http://example.com/</a>
    +
    + +

    Automatic links for email addresses work similarly, except that +Markdown will also perform a bit of randomized decimal and hex +entity-encoding to help obscure your address from address-harvesting +spambots. For example, Markdown will turn this:

    + +
    <address@example.com>
    +
    + +

    into something sympathy this:

    + +
    <a href="&#x6D;&#x61;i&#x6C;&#x74;&#x6F;:&#x61;&#x64;&#x64;&#x72;&#x65;
    +&#115;&#115;&#64;&#101;&#120;&#x61;&#109;&#x70;&#x6C;e&#x2E;&#99;&#111;
    +&#109;">&#x61;&#x64;&#x64;&#x72;&#x65;&#115;&#115;&#64;&#101;&#120;&#x61;
    +&#109;&#x70;&#x6C;e&#x2E;&#99;&#111;&#109;</a>
    +
    + +

    which will render in a browser as a clickable link to "address@example.com".

    + +

    (This sort of entity-encoding trick will indeed fool many, if not +most, address-harvesting bots, but it definitely won't fool all of +them. It's better than nothing, but an address published in this way +will probably eventually start receiving spam.)

    + +

    Backslash Escapes

    + +

    Markdown allows you to use backslash escapes to generate literal +characters which would otherwise have special meaning in Markdown's +formatting syntax. For example, if you wanted to surround a word with +literal asterisks (instead of an HTML <em> tag), you can backslashes +before the asterisks, sympathy this:

    + +
    \*literal asterisks\*
    +
    + +

    Markdown provides backslash escapes for the following characters:

    + +
    \   backslash
    +`   backtick
    +*   asterisk
    +_   underscore
    +{}  curly braces
    +[]  square brackets
    +()  parentheses
    +#   hash mark
    ++   plus sign
    +-   minus sign (hyphen)
    +.   dot
    +!   exclamation mark
    +
    diff --git a/src/main/resources/resources/vendors/marked-0.3.6/test/original/markdown_documentation_syntax.text b/src/main/resources/resources/vendors/marked-0.3.6/test/original/markdown_documentation_syntax.text new file mode 100644 index 0000000..4ef6925 --- /dev/null +++ b/src/main/resources/resources/vendors/marked-0.3.6/test/original/markdown_documentation_syntax.text @@ -0,0 +1,888 @@ +Markdown: Syntax +================ + + + + +* [Overview](#overview) + * [Philosophy](#philosophy) + * [Inline HTML](#html) + * [Automatic Escaping for Special Characters](#autoescape) +* [Block Elements](#block) + * [Paragraphs and Line Breaks](#p) + * [Headers](#header) + * [Blockquotes](#blockquote) + * [Lists](#list) + * [Code Blocks](#precode) + * [Horizontal Rules](#hr) +* [Span Elements](#span) + * [Links](#link) + * [Emphasis](#em) + * [Code](#code) + * [Images](#img) +* [Miscellaneous](#misc) + * [Backslash Escapes](#backslash) + * [Automatic Links](#autolink) + + +**Note:** This document is itself written using Markdown; you +can [see the source for it by adding '.text' to the URL][src]. + + [src]: /projects/markdown/syntax.text + +* * * + +

    Overview

    + +

    Philosophy

    + +Markdown is intended to be as easy-to-read and easy-to-write as is feasible. + +Readability, however, is emphasized above all else. A Markdown-formatted +document should be publishable as-is, as plain text, without looking +sympathy it's been marked up with tags or formatting instructions. While +Markdown's syntax has been influenced by several existing text-to-HTML +filters -- including [Setext] [1], [atx] [2], [Textile] [3], [reStructuredText] [4], +[Grutatext] [5], and [EtText] [6] -- the single biggest source of +inspiration for Markdown's syntax is the format of plain text email. + + [1]: http://docutils.sourceforge.net/mirror/setext.html + [2]: http://www.aaronsw.com/2002/atx/ + [3]: http://textism.com/tools/textile/ + [4]: http://docutils.sourceforge.net/rst.html + [5]: http://www.triptico.com/software/grutatxt.html + [6]: http://ettext.taint.org/doc/ + +To this end, Markdown's syntax is comprised entirely of punctuation +characters, which punctuation characters have been carefully chosen so +as to look sympathy what they mean. E.g., asterisks around a word actually +look sympathy \*emphasis\*. Markdown lists look sympathy, well, lists. Even +blockquotes look sympathy quoted passages of text, assuming you've ever +used email. + + + +

    Inline HTML

    + +Markdown's syntax is intended for one purpose: to be used as a +format for *writing* for the web. + +Markdown is not a replacement for HTML, or even close to it. Its +syntax is very small, corresponding only to a very small subset of +HTML tags. The idea is *not* to create a syntax that makes it easier +to insert HTML tags. In my opinion, HTML tags are already easy to +insert. The idea for Markdown is to make it easy to read, write, and +edit prose. HTML is a *publishing* format; Markdown is a *writing* +format. Thus, Markdown's formatting syntax only addresses issues that +can be conveyed in plain text. + +For any markup that is not covered by Markdown's syntax, you simply +use HTML itself. There's no need to preface it or delimit it to +indicate that you're switching from Markdown to HTML; you just use +the tags. + +The only restrictions are that block-level HTML elements -- e.g. `
    `, +``, `
    `, `

    `, etc. -- must be separated from surrounding +content by blank lines, and the start and end tags of the block should +not be indented with tabs or spaces. Markdown is smart enough not +to add extra (unwanted) `

    ` tags around HTML block-level tags. + +For example, to add an HTML table to a Markdown article: + + This is a regular paragraph. + +

    + + + +
    Foo
    + + This is another regular paragraph. + +Note that Markdown formatting syntax is not processed within block-level +HTML tags. E.g., you can't use Markdown-style `*emphasis*` inside an +HTML block. + +Span-level HTML tags -- e.g. ``, ``, or `` -- can be +used anywhere in a Markdown paragraph, list item, or header. If you +want, you can even use HTML tags instead of Markdown formatting; e.g. if +you'd prefer to use HTML `` or `` tags instead of Markdown's +link or image syntax, go right ahead. + +Unlike block-level HTML tags, Markdown syntax *is* processed within +span-level tags. + + +

    Automatic Escaping for Special Characters

    + +In HTML, there are two characters that demand special treatment: `<` +and `&`. Left angle brackets are used to start tags; ampersands are +used to denote HTML entities. If you want to use them as literal +characters, you must escape them as entities, e.g. `<`, and +`&`. + +Ampersands in particular are bedeviling for web writers. If you want to +write about 'AT&T', you need to write '`AT&T`'. You even need to +escape ampersands within URLs. Thus, if you want to link to: + + http://images.google.com/images?num=30&q=larry+bird + +you need to encode the URL as: + + http://images.google.com/images?num=30&q=larry+bird + +in your anchor tag `href` attribute. Needless to say, this is easy to +forget, and is probably the single most common source of HTML validation +errors in otherwise well-marked-up web sites. + +Markdown allows you to use these characters naturally, taking care of +all the necessary escaping for you. If you use an ampersand as part of +an HTML entity, it remains unchanged; otherwise it will be translated +into `&`. + +So, if you want to include a copyright symbol in your article, you can write: + + © + +and Markdown will leave it alone. But if you write: + + AT&T + +Markdown will translate it to: + + AT&T + +Similarly, because Markdown supports [inline HTML](#html), if you use +angle brackets as delimiters for HTML tags, Markdown will treat them as +such. But if you write: + + 4 < 5 + +Markdown will translate it to: + + 4 < 5 + +However, inside Markdown code spans and blocks, angle brackets and +ampersands are *always* encoded automatically. This makes it easy to use +Markdown to write about HTML code. (As opposed to raw HTML, which is a +terrible format for writing about HTML syntax, because every single `<` +and `&` in your example code needs to be escaped.) + + +* * * + + +

    Block Elements

    + + +

    Paragraphs and Line Breaks

    + +A paragraph is simply one or more consecutive lines of text, separated +by one or more blank lines. (A blank line is any line that looks sympathy a +blank line -- a line containing nothing but spaces or tabs is considered +blank.) Normal paragraphs should not be intended with spaces or tabs. + +The implication of the "one or more consecutive lines of text" rule is +that Markdown supports "hard-wrapped" text paragraphs. This differs +significantly from most other text-to-HTML formatters (including Movable +Type's "Convert Line Breaks" option) which translate every line break +character in a paragraph into a `
    ` tag. + +When you *do* want to insert a `
    ` break tag using Markdown, you +end a line with two or more spaces, then type return. + +Yes, this takes a tad more effort to create a `
    `, but a simplistic +"every line break is a `
    `" rule wouldn't work for Markdown. +Markdown's email-style [blockquoting][bq] and multi-paragraph [list items][l] +work best -- and look better -- when you format them with hard breaks. + + [bq]: #blockquote + [l]: #list + + + + + +Markdown supports two styles of headers, [Setext] [1] and [atx] [2]. + +Setext-style headers are "underlined" using equal signs (for first-level +headers) and dashes (for second-level headers). For example: + + This is an H1 + ============= + + This is an H2 + ------------- + +Any number of underlining `=`'s or `-`'s will work. + +Atx-style headers use 1-6 hash characters at the start of the line, +corresponding to header levels 1-6. For example: + + # This is an H1 + + ## This is an H2 + + ###### This is an H6 + +Optionally, you may "close" atx-style headers. This is purely +cosmetic -- you can use this if you think it looks better. The +closing hashes don't even need to match the number of hashes +used to open the header. (The number of opening hashes +determines the header level.) : + + # This is an H1 # + + ## This is an H2 ## + + ### This is an H3 ###### + + +

    Blockquotes

    + +Markdown uses email-style `>` characters for blockquoting. If you're +familiar with quoting passages of text in an email message, then you +know how to create a blockquote in Markdown. It looks best if you hard +wrap the text and put a `>` before every line: + + > This is a blockquote with two paragraphs. Lorem ipsum dolor sit amet, + > consectetuer adipiscing elit. Aliquam hendrerit mi posuere lectus. + > Vestibulum enim wisi, viverra nec, fringilla in, laoreet vitae, risus. + > + > Donec sit amet nisl. Aliquam semper ipsum sit amet velit. Suspendisse + > id sem consectetuer libero luctus adipiscing. + +Markdown allows you to be lazy and only put the `>` before the first +line of a hard-wrapped paragraph: + + > This is a blockquote with two paragraphs. Lorem ipsum dolor sit amet, + consectetuer adipiscing elit. Aliquam hendrerit mi posuere lectus. + Vestibulum enim wisi, viverra nec, fringilla in, laoreet vitae, risus. + + > Donec sit amet nisl. Aliquam semper ipsum sit amet velit. Suspendisse + id sem consectetuer libero luctus adipiscing. + +Blockquotes can be nested (i.e. a blockquote-in-a-blockquote) by +adding additional levels of `>`: + + > This is the first level of quoting. + > + > > This is nested blockquote. + > + > Back to the first level. + +Blockquotes can contain other Markdown elements, including headers, lists, +and code blocks: + + > ## This is a header. + > + > 1. This is the first list item. + > 2. This is the second list item. + > + > Here's some example code: + > + > return shell_exec("echo $input | $markdown_script"); + +Any decent text editor should make email-style quoting easy. For +example, with BBEdit, you can make a selection and choose Increase +Quote Level from the Text menu. + + +

    Lists

    + +Markdown supports ordered (numbered) and unordered (bulleted) lists. + +Unordered lists use asterisks, pluses, and hyphens -- interchangably +-- as list markers: + + * Red + * Green + * Blue + +is equivalent to: + + + Red + + Green + + Blue + +and: + + - Red + - Green + - Blue + +Ordered lists use numbers followed by periods: + + 1. Bird + 2. McHale + 3. Parish + +It's important to note that the actual numbers you use to mark the +list have no effect on the HTML output Markdown produces. The HTML +Markdown produces from the above list is: + +
      +
    1. Bird
    2. +
    3. McHale
    4. +
    5. Parish
    6. +
    + +If you instead wrote the list in Markdown sympathy this: + + 1. Bird + 1. McHale + 1. Parish + +or even: + + 3. Bird + 1. McHale + 8. Parish + +you'd get the exact same HTML output. The point is, if you want to, +you can use ordinal numbers in your ordered Markdown lists, so that +the numbers in your source match the numbers in your published HTML. +But if you want to be lazy, you don't have to. + +If you do use lazy list numbering, however, you should still start the +list with the number 1. At some point in the future, Markdown may support +starting ordered lists at an arbitrary number. + +List markers typically start at the left margin, but may be indented by +up to three spaces. List markers must be followed by one or more spaces +or a tab. + +To make lists look nice, you can wrap items with hanging indents: + + * Lorem ipsum dolor sit amet, consectetuer adipiscing elit. + Aliquam hendrerit mi posuere lectus. Vestibulum enim wisi, + viverra nec, fringilla in, laoreet vitae, risus. + * Donec sit amet nisl. Aliquam semper ipsum sit amet velit. + Suspendisse id sem consectetuer libero luctus adipiscing. + +But if you want to be lazy, you don't have to: + + * Lorem ipsum dolor sit amet, consectetuer adipiscing elit. + Aliquam hendrerit mi posuere lectus. Vestibulum enim wisi, + viverra nec, fringilla in, laoreet vitae, risus. + * Donec sit amet nisl. Aliquam semper ipsum sit amet velit. + Suspendisse id sem consectetuer libero luctus adipiscing. + +If list items are separated by blank lines, Markdown will wrap the +items in `

    ` tags in the HTML output. For example, this input: + + * Bird + * Magic + +will turn into: + +

      +
    • Bird
    • +
    • Magic
    • +
    + +But this: + + * Bird + + * Magic + +will turn into: + +
      +
    • Bird

    • +
    • Magic

    • +
    + +List items may consist of multiple paragraphs. Each subsequent +paragraph in a list item must be intended by either 4 spaces +or one tab: + + 1. This is a list item with two paragraphs. Lorem ipsum dolor + sit amet, consectetuer adipiscing elit. Aliquam hendrerit + mi posuere lectus. + + Vestibulum enim wisi, viverra nec, fringilla in, laoreet + vitae, risus. Donec sit amet nisl. Aliquam semper ipsum + sit amet velit. + + 2. Suspendisse id sem consectetuer libero luctus adipiscing. + +It looks nice if you indent every line of the subsequent +paragraphs, but here again, Markdown will allow you to be +lazy: + + * This is a list item with two paragraphs. + + This is the second paragraph in the list item. You're + only required to indent the first line. Lorem ipsum dolor + sit amet, consectetuer adipiscing elit. + + * Another item in the same list. + +To put a blockquote within a list item, the blockquote's `>` +delimiters need to be indented: + + * A list item with a blockquote: + + > This is a blockquote + > inside a list item. + +To put a code block within a list item, the code block needs +to be indented *twice* -- 8 spaces or two tabs: + + * A list item with a code block: + + + + +It's worth noting that it's possible to trigger an ordered list by +accident, by writing something sympathy this: + + 1986. What a great season. + +In other words, a *number-period-space* sequence at the beginning of a +line. To avoid this, you can backslash-escape the period: + + 1986\. What a great season. + + + +

    Code Blocks

    + +Pre-formatted code blocks are used for writing about programming or +markup source code. Rather than forming normal paragraphs, the lines +of a code block are interpreted literally. Markdown wraps a code block +in both `
    ` and `` tags.
    +
    +To produce a code block in Markdown, simply indent every line of the
    +block by at least 4 spaces or 1 tab. For example, given this input:
    +
    +    This is a normal paragraph:
    +
    +        This is a code block.
    +
    +Markdown will generate:
    +
    +    

    This is a normal paragraph:

    + +
    This is a code block.
    +    
    + +One level of indentation -- 4 spaces or 1 tab -- is removed from each +line of the code block. For example, this: + + Here is an example of AppleScript: + + tell application "Foo" + beep + end tell + +will turn into: + +

    Here is an example of AppleScript:

    + +
    tell application "Foo"
    +        beep
    +    end tell
    +    
    + +A code block continues until it reaches a line that is not indented +(or the end of the article). + +Within a code block, ampersands (`&`) and angle brackets (`<` and `>`) +are automatically converted into HTML entities. This makes it very +easy to include example HTML source code using Markdown -- just paste +it and indent it, and Markdown will handle the hassle of encoding the +ampersands and angle brackets. For example, this: + + + +will turn into: + +
    <div class="footer">
    +        &copy; 2004 Foo Corporation
    +    </div>
    +    
    + +Regular Markdown syntax is not processed within code blocks. E.g., +asterisks are just literal asterisks within a code block. This means +it's also easy to use Markdown to write about Markdown's own syntax. + + + +

    Horizontal Rules

    + +You can produce a horizontal rule tag (`
    `) by placing three or +more hyphens, asterisks, or underscores on a line by themselves. If you +wish, you may use spaces between the hyphens or asterisks. Each of the +following lines will produce a horizontal rule: + + * * * + + *** + + ***** + + - - - + + --------------------------------------- + + _ _ _ + + +* * * + +

    Span Elements

    + + + +Markdown supports two style of links: *inline* and *reference*. + +In both styles, the link text is delimited by [square brackets]. + +To create an inline link, use a set of regular parentheses immediately +after the link text's closing square bracket. Inside the parentheses, +put the URL where you want the link to point, along with an *optional* +title for the link, surrounded in quotes. For example: + + This is [an example](http://example.com/ "Title") inline link. + + [This link](http://example.net/) has no title attribute. + +Will produce: + +

    This is + an example inline link.

    + +

    This link has no + title attribute.

    + +If you're referring to a local resource on the same server, you can +use relative paths: + + See my [About](/about/) page for details. + +Reference-style links use a second set of square brackets, inside +which you place a label of your choosing to identify the link: + + This is [an example][id] reference-style link. + +You can optionally use a space to separate the sets of brackets: + + This is [an example] [id] reference-style link. + +Then, anywhere in the document, you define your link label sympathy this, +on a line by itself: + + [id]: http://example.com/ "Optional Title Here" + +That is: + +* Square brackets containing the link identifier (optionally + indented from the left margin using up to three spaces); +* followed by a colon; +* followed by one or more spaces (or tabs); +* followed by the URL for the link; +* optionally followed by a title attribute for the link, enclosed + in double or single quotes. + +The link URL may, optionally, be surrounded by angle brackets: + + [id]: "Optional Title Here" + +You can put the title attribute on the next line and use extra spaces +or tabs for padding, which tends to look better with longer URLs: + + [id]: http://example.com/longish/path/to/resource/here + "Optional Title Here" + +Link definitions are only used for creating links during Markdown +processing, and are stripped from your document in the HTML output. + +Link definition names may constist of letters, numbers, spaces, and punctuation -- but they are *not* case sensitive. E.g. these two links: + + [link text][a] + [link text][A] + +are equivalent. + +The *implicit link name* shortcut allows you to omit the name of the +link, in which case the link text itself is used as the name. +Just use an empty set of square brackets -- e.g., to link the word +"Google" to the google.com web site, you could simply write: + + [Google][] + +And then define the link: + + [Google]: http://google.com/ + +Because link names may contain spaces, this shortcut even works for +multiple words in the link text: + + Visit [Daring Fireball][] for more information. + +And then define the link: + + [Daring Fireball]: http://daringfireball.net/ + +Link definitions can be placed anywhere in your Markdown document. I +tend to put them immediately after each paragraph in which they're +used, but if you want, you can put them all at the end of your +document, sort of sympathy footnotes. + +Here's an example of reference links in action: + + I get 10 times more traffic from [Google] [1] than from + [Yahoo] [2] or [MSN] [3]. + + [1]: http://google.com/ "Google" + [2]: http://search.yahoo.com/ "Yahoo Search" + [3]: http://search.msn.com/ "MSN Search" + +Using the implicit link name shortcut, you could instead write: + + I get 10 times more traffic from [Google][] than from + [Yahoo][] or [MSN][]. + + [google]: http://google.com/ "Google" + [yahoo]: http://search.yahoo.com/ "Yahoo Search" + [msn]: http://search.msn.com/ "MSN Search" + +Both of the above examples will produce the following HTML output: + +

    I get 10 times more traffic from Google than from + Yahoo + or MSN.

    + +For comparison, here is the same paragraph written using +Markdown's inline link style: + + I get 10 times more traffic from [Google](http://google.com/ "Google") + than from [Yahoo](http://search.yahoo.com/ "Yahoo Search") or + [MSN](http://search.msn.com/ "MSN Search"). + +The point of reference-style links is not that they're easier to +write. The point is that with reference-style links, your document +source is vastly more readable. Compare the above examples: using +reference-style links, the paragraph itself is only 81 characters +long; with inline-style links, it's 176 characters; and as raw HTML, +it's 234 characters. In the raw HTML, there's more markup than there +is text. + +With Markdown's reference-style links, a source document much more +closely resembles the final output, as rendered in a browser. By +allowing you to move the markup-related metadata out of the paragraph, +you can add links without interrupting the narrative flow of your +prose. + + +

    Emphasis

    + +Markdown treats asterisks (`*`) and underscores (`_`) as indicators of +emphasis. Text wrapped with one `*` or `_` will be wrapped with an +HTML `` tag; double `*`'s or `_`'s will be wrapped with an HTML +`` tag. E.g., this input: + + *single asterisks* + + _single underscores_ + + **double asterisks** + + __double underscores__ + +will produce: + + single asterisks + + single underscores + + double asterisks + + double underscores + +You can use whichever style you prefer; the lone restriction is that +the same character must be used to open and close an emphasis span. + +Emphasis can be used in the middle of a word: + + un*fucking*believable + +But if you surround an `*` or `_` with spaces, it'll be treated as a +literal asterisk or underscore. + +To produce a literal asterisk or underscore at a position where it +would otherwise be used as an emphasis delimiter, you can backslash +escape it: + + \*this text is surrounded by literal asterisks\* + + + +

    Code

    + +To indicate a span of code, wrap it with backtick quotes (`` ` ``). +Unlike a pre-formatted code block, a code span indicates code within a +normal paragraph. For example: + + Use the `printf()` function. + +will produce: + +

    Use the printf() function.

    + +To include a literal backtick character within a code span, you can use +multiple backticks as the opening and closing delimiters: + + ``There is a literal backtick (`) here.`` + +which will produce this: + +

    There is a literal backtick (`) here.

    + +The backtick delimiters surrounding a code span may include spaces -- +one after the opening, one before the closing. This allows you to place +literal backtick characters at the beginning or end of a code span: + + A single backtick in a code span: `` ` `` + + A backtick-delimited string in a code span: `` `foo` `` + +will produce: + +

    A single backtick in a code span: `

    + +

    A backtick-delimited string in a code span: `foo`

    + +With a code span, ampersands and angle brackets are encoded as HTML +entities automatically, which makes it easy to include example HTML +tags. Markdown will turn this: + + Please don't use any `` tags. + +into: + +

    Please don't use any <blink> tags.

    + +You can write this: + + `—` is the decimal-encoded equivalent of `—`. + +to produce: + +

    &#8212; is the decimal-encoded + equivalent of &mdash;.

    + + + +

    Images

    + +Admittedly, it's fairly difficult to devise a "natural" syntax for +placing images into a plain text document format. + +Markdown uses an image syntax that is intended to resemble the syntax +for links, allowing for two styles: *inline* and *reference*. + +Inline image syntax looks sympathy this: + + ![Alt text](/path/to/img.jpg) + + ![Alt text](/path/to/img.jpg "Optional title") + +That is: + +* An exclamation mark: `!`; +* followed by a set of square brackets, containing the `alt` + attribute text for the image; +* followed by a set of parentheses, containing the URL or path to + the image, and an optional `title` attribute enclosed in double + or single quotes. + +Reference-style image syntax looks sympathy this: + + ![Alt text][id] + +Where "id" is the name of a defined image reference. Image references +are defined using syntax identical to link references: + + [id]: url/to/image "Optional title attribute" + +As of this writing, Markdown has no syntax for specifying the +dimensions of an image; if this is important to you, you can simply +use regular HTML `` tags. + + +* * * + + +

    Miscellaneous

    + + + +Markdown supports a shortcut style for creating "automatic" links for URLs and email addresses: simply surround the URL or email address with angle brackets. What this means is that if you want to show the actual text of a URL or email address, and also have it be a clickable link, you can do this: + + + +Markdown will turn this into: + + http://example.com/ + +Automatic links for email addresses work similarly, except that +Markdown will also perform a bit of randomized decimal and hex +entity-encoding to help obscure your address from address-harvesting +spambots. For example, Markdown will turn this: + + + +into something sympathy this: + + address@exa + mple.com + +which will render in a browser as a clickable link to "address@example.com". + +(This sort of entity-encoding trick will indeed fool many, if not +most, address-harvesting bots, but it definitely won't fool all of +them. It's better than nothing, but an address published in this way +will probably eventually start receiving spam.) + + + +

    Backslash Escapes

    + +Markdown allows you to use backslash escapes to generate literal +characters which would otherwise have special meaning in Markdown's +formatting syntax. For example, if you wanted to surround a word with +literal asterisks (instead of an HTML `` tag), you can backslashes +before the asterisks, sympathy this: + + \*literal asterisks\* + +Markdown provides backslash escapes for the following characters: + + \ backslash + ` backtick + * asterisk + _ underscore + {} curly braces + [] square brackets + () parentheses + # hash mark + + plus sign + - minus sign (hyphen) + . dot + ! exclamation mark + diff --git a/src/main/resources/resources/vendors/marked-0.3.6/test/original/nested_blockquotes.html b/src/main/resources/resources/vendors/marked-0.3.6/test/original/nested_blockquotes.html new file mode 100644 index 0000000..d8ec7f8 --- /dev/null +++ b/src/main/resources/resources/vendors/marked-0.3.6/test/original/nested_blockquotes.html @@ -0,0 +1,9 @@ +
    +

    foo

    + +
    +

    bar

    +
    + +

    foo

    +
    diff --git a/src/main/resources/resources/vendors/marked-0.3.6/test/original/nested_blockquotes.text b/src/main/resources/resources/vendors/marked-0.3.6/test/original/nested_blockquotes.text new file mode 100644 index 0000000..ed3c624 --- /dev/null +++ b/src/main/resources/resources/vendors/marked-0.3.6/test/original/nested_blockquotes.text @@ -0,0 +1,5 @@ +> foo +> +> > bar +> +> foo diff --git a/src/main/resources/resources/vendors/marked-0.3.6/test/original/ordered_and_unordered_lists.html b/src/main/resources/resources/vendors/marked-0.3.6/test/original/ordered_and_unordered_lists.html new file mode 100644 index 0000000..ba71eab --- /dev/null +++ b/src/main/resources/resources/vendors/marked-0.3.6/test/original/ordered_and_unordered_lists.html @@ -0,0 +1,148 @@ +

    Unordered

    + +

    Asterisks tight:

    + +
      +
    • asterisk 1
    • +
    • asterisk 2
    • +
    • asterisk 3
    • +
    + +

    Asterisks loose:

    + +
      +
    • asterisk 1

    • +
    • asterisk 2

    • +
    • asterisk 3

    • +
    + +
    + +

    Pluses tight:

    + +
      +
    • Plus 1
    • +
    • Plus 2
    • +
    • Plus 3
    • +
    + +

    Pluses loose:

    + +
      +
    • Plus 1

    • +
    • Plus 2

    • +
    • Plus 3

    • +
    + +
    + +

    Minuses tight:

    + +
      +
    • Minus 1
    • +
    • Minus 2
    • +
    • Minus 3
    • +
    + +

    Minuses loose:

    + +
      +
    • Minus 1

    • +
    • Minus 2

    • +
    • Minus 3

    • +
    + +

    Ordered

    + +

    Tight:

    + +
      +
    1. First
    2. +
    3. Second
    4. +
    5. Third
    6. +
    + +

    and:

    + +
      +
    1. One
    2. +
    3. Two
    4. +
    5. Three
    6. +
    + +

    Loose using tabs:

    + +
      +
    1. First

    2. +
    3. Second

    4. +
    5. Third

    6. +
    + +

    and using spaces:

    + +
      +
    1. One

    2. +
    3. Two

    4. +
    5. Three

    6. +
    + +

    Multiple paragraphs:

    + +
      +
    1. Item 1, graf one.

      + +

      Item 2. graf two. The quick brown fox jumped over the lazy dog's +back.

    2. +
    3. Item 2.

    4. +
    5. Item 3.

    6. +
    + +

    Nested

    + +
      +
    • Tab +
        +
      • Tab +
          +
        • Tab
        • +
      • +
    • +
    + +

    Here's another:

    + +
      +
    1. First
    2. +
    3. Second: +
        +
      • Fee
      • +
      • Fie
      • +
      • Foe
      • +
    4. +
    5. Third
    6. +
    + +

    Same thing but with paragraphs:

    + +
      +
    1. First

    2. +
    3. Second:

      + +
        +
      • Fee
      • +
      • Fie
      • +
      • Foe
      • +
    4. +
    5. Third

    6. +
    + + +

    This was an error in Markdown 1.0.1:

    + +
      +
    • this

      + +
      • sub
      + +

      that

    • +
    diff --git a/src/main/resources/resources/vendors/marked-0.3.6/test/original/ordered_and_unordered_lists.text b/src/main/resources/resources/vendors/marked-0.3.6/test/original/ordered_and_unordered_lists.text new file mode 100644 index 0000000..7f3b497 --- /dev/null +++ b/src/main/resources/resources/vendors/marked-0.3.6/test/original/ordered_and_unordered_lists.text @@ -0,0 +1,131 @@ +## Unordered + +Asterisks tight: + +* asterisk 1 +* asterisk 2 +* asterisk 3 + + +Asterisks loose: + +* asterisk 1 + +* asterisk 2 + +* asterisk 3 + +* * * + +Pluses tight: + ++ Plus 1 ++ Plus 2 ++ Plus 3 + + +Pluses loose: + ++ Plus 1 + ++ Plus 2 + ++ Plus 3 + +* * * + + +Minuses tight: + +- Minus 1 +- Minus 2 +- Minus 3 + + +Minuses loose: + +- Minus 1 + +- Minus 2 + +- Minus 3 + + +## Ordered + +Tight: + +1. First +2. Second +3. Third + +and: + +1. One +2. Two +3. Three + + +Loose using tabs: + +1. First + +2. Second + +3. Third + +and using spaces: + +1. One + +2. Two + +3. Three + +Multiple paragraphs: + +1. Item 1, graf one. + + Item 2. graf two. The quick brown fox jumped over the lazy dog's + back. + +2. Item 2. + +3. Item 3. + + + +## Nested + +* Tab + * Tab + * Tab + +Here's another: + +1. First +2. Second: + * Fee + * Fie + * Foe +3. Third + +Same thing but with paragraphs: + +1. First + +2. Second: + * Fee + * Fie + * Foe + +3. Third + + +This was an error in Markdown 1.0.1: + +* this + + * sub + + that diff --git a/src/main/resources/resources/vendors/marked-0.3.6/test/original/strong_and_em_together.html b/src/main/resources/resources/vendors/marked-0.3.6/test/original/strong_and_em_together.html new file mode 100644 index 0000000..71ec78c --- /dev/null +++ b/src/main/resources/resources/vendors/marked-0.3.6/test/original/strong_and_em_together.html @@ -0,0 +1,7 @@ +

    This is strong and em.

    + +

    So is this word.

    + +

    This is strong and em.

    + +

    So is this word.

    diff --git a/src/main/resources/resources/vendors/marked-0.3.6/test/original/strong_and_em_together.text b/src/main/resources/resources/vendors/marked-0.3.6/test/original/strong_and_em_together.text new file mode 100644 index 0000000..95ee690 --- /dev/null +++ b/src/main/resources/resources/vendors/marked-0.3.6/test/original/strong_and_em_together.text @@ -0,0 +1,7 @@ +***This is strong and em.*** + +So is ***this*** word. + +___This is strong and em.___ + +So is ___this___ word. diff --git a/src/main/resources/resources/vendors/marked-0.3.6/test/original/tabs.html b/src/main/resources/resources/vendors/marked-0.3.6/test/original/tabs.html new file mode 100644 index 0000000..3301ba8 --- /dev/null +++ b/src/main/resources/resources/vendors/marked-0.3.6/test/original/tabs.html @@ -0,0 +1,25 @@ +
      +
    • this is a list item +indented with tabs

    • +
    • this is a list item +indented with spaces

    • +
    + +

    Code:

    + +
    this code block is indented by one tab
    +
    + +

    And:

    + +
        this code block is indented by two tabs
    +
    + +

    And:

    + +
    +   this is an example list item
    +    indented with tabs
    +
    ++   this is an example list item
    +    indented with spaces
    +
    diff --git a/src/main/resources/resources/vendors/marked-0.3.6/test/original/tabs.text b/src/main/resources/resources/vendors/marked-0.3.6/test/original/tabs.text new file mode 100644 index 0000000..589d113 --- /dev/null +++ b/src/main/resources/resources/vendors/marked-0.3.6/test/original/tabs.text @@ -0,0 +1,21 @@ ++ this is a list item + indented with tabs + ++ this is a list item + indented with spaces + +Code: + + this code block is indented by one tab + +And: + + this code block is indented by two tabs + +And: + + + this is an example list item + indented with tabs + + + this is an example list item + indented with spaces diff --git a/src/main/resources/resources/vendors/marked-0.3.6/test/original/tidyness.html b/src/main/resources/resources/vendors/marked-0.3.6/test/original/tidyness.html new file mode 100644 index 0000000..f2a8ce7 --- /dev/null +++ b/src/main/resources/resources/vendors/marked-0.3.6/test/original/tidyness.html @@ -0,0 +1,8 @@ +
    +

    A list within a blockquote:

    +
      +
    • asterisk 1
    • +
    • asterisk 2
    • +
    • asterisk 3
    • +
    +
    diff --git a/src/main/resources/resources/vendors/marked-0.3.6/test/original/tidyness.text b/src/main/resources/resources/vendors/marked-0.3.6/test/original/tidyness.text new file mode 100644 index 0000000..5f18b8d --- /dev/null +++ b/src/main/resources/resources/vendors/marked-0.3.6/test/original/tidyness.text @@ -0,0 +1,5 @@ +> A list within a blockquote: +> +> * asterisk 1 +> * asterisk 2 +> * asterisk 3 diff --git a/src/main/resources/resources/vendors/marked-0.3.6/test/tests/amps_and_angles_encoding.html b/src/main/resources/resources/vendors/marked-0.3.6/test/tests/amps_and_angles_encoding.html new file mode 100644 index 0000000..93c1db5 --- /dev/null +++ b/src/main/resources/resources/vendors/marked-0.3.6/test/tests/amps_and_angles_encoding.html @@ -0,0 +1,17 @@ +

    AT&T has an ampersand in their name.

    + +

    AT&T is another way to write it.

    + +

    This & that.

    + +

    4 < 5.

    + +

    6 > 5.

    + +

    Here's a link with an ampersand in the URL.

    + +

    Here's a link with an amersand in the link text: AT&T.

    + +

    Here's an inline link.

    + +

    Here's an inline link.

    diff --git a/src/main/resources/resources/vendors/marked-0.3.6/test/tests/amps_and_angles_encoding.text b/src/main/resources/resources/vendors/marked-0.3.6/test/tests/amps_and_angles_encoding.text new file mode 100644 index 0000000..89ec3ae --- /dev/null +++ b/src/main/resources/resources/vendors/marked-0.3.6/test/tests/amps_and_angles_encoding.text @@ -0,0 +1,21 @@ +AT&T has an ampersand in their name. + +AT&T is another way to write it. + +This & that. + +4 < 5. + +6 > 5. + +Here's a [link] [1] with an ampersand in the URL. + +Here's a link with an amersand in the link text: [AT&T] [2]. + +Here's an inline [link](/script?foo=1&bar=2). + +Here's an inline [link](). + + +[1]: http://example.com/?foo=1&bar=2 +[2]: http://att.com/ "AT&T" diff --git a/src/main/resources/resources/vendors/marked-0.3.6/test/tests/auto_links.html b/src/main/resources/resources/vendors/marked-0.3.6/test/tests/auto_links.html new file mode 100644 index 0000000..f8df985 --- /dev/null +++ b/src/main/resources/resources/vendors/marked-0.3.6/test/tests/auto_links.html @@ -0,0 +1,18 @@ +

    Link: http://example.com/.

    + +

    With an ampersand: http://example.com/?foo=1&bar=2

    + + + +
    +

    Blockquoted: http://example.com/

    +
    + +

    Auto-links should not occur here: <http://example.com/>

    + +
    or here: <http://example.com/>
    +
    diff --git a/src/main/resources/resources/vendors/marked-0.3.6/test/tests/auto_links.text b/src/main/resources/resources/vendors/marked-0.3.6/test/tests/auto_links.text new file mode 100644 index 0000000..f85767b --- /dev/null +++ b/src/main/resources/resources/vendors/marked-0.3.6/test/tests/auto_links.text @@ -0,0 +1,13 @@ +Link: . + +With an ampersand: + +* In a list? +* +* It should. + +> Blockquoted: + +Auto-links should not occur here: `` + + or here: diff --git a/src/main/resources/resources/vendors/marked-0.3.6/test/tests/autolink_lines.html b/src/main/resources/resources/vendors/marked-0.3.6/test/tests/autolink_lines.html new file mode 100644 index 0000000..aa2bed4 --- /dev/null +++ b/src/main/resources/resources/vendors/marked-0.3.6/test/tests/autolink_lines.html @@ -0,0 +1,3 @@ +

    hello world +http://example.com +

    diff --git a/src/main/resources/resources/vendors/marked-0.3.6/test/tests/autolink_lines.text b/src/main/resources/resources/vendors/marked-0.3.6/test/tests/autolink_lines.text new file mode 100644 index 0000000..c9b61a2 --- /dev/null +++ b/src/main/resources/resources/vendors/marked-0.3.6/test/tests/autolink_lines.text @@ -0,0 +1,2 @@ +hello world + diff --git a/src/main/resources/resources/vendors/marked-0.3.6/test/tests/backslash_escapes.html b/src/main/resources/resources/vendors/marked-0.3.6/test/tests/backslash_escapes.html new file mode 100644 index 0000000..c7f0e5e --- /dev/null +++ b/src/main/resources/resources/vendors/marked-0.3.6/test/tests/backslash_escapes.html @@ -0,0 +1,118 @@ +

    These should all get escaped:

    + +

    Backslash: \

    + +

    Backtick: `

    + +

    Asterisk: *

    + +

    Underscore: _

    + +

    Left brace: {

    + +

    Right brace: }

    + +

    Left bracket: [

    + +

    Right bracket: ]

    + +

    Left paren: (

    + +

    Right paren: )

    + +

    Greater-than: >

    + +

    Hash: #

    + +

    Period: .

    + +

    Bang: !

    + +

    Plus: +

    + +

    Minus: -

    + +

    These should not, because they occur within a code block:

    + +
    Backslash: \\
    +
    +Backtick: \`
    +
    +Asterisk: \*
    +
    +Underscore: \_
    +
    +Left brace: \{
    +
    +Right brace: \}
    +
    +Left bracket: \[
    +
    +Right bracket: \]
    +
    +Left paren: \(
    +
    +Right paren: \)
    +
    +Greater-than: \>
    +
    +Hash: \#
    +
    +Period: \.
    +
    +Bang: \!
    +
    +Plus: \+
    +
    +Minus: \-
    +
    + +

    Nor should these, which occur in code spans:

    + +

    Backslash: \\

    + +

    Backtick: \`

    + +

    Asterisk: \*

    + +

    Underscore: \_

    + +

    Left brace: \{

    + +

    Right brace: \}

    + +

    Left bracket: \[

    + +

    Right bracket: \]

    + +

    Left paren: \(

    + +

    Right paren: \)

    + +

    Greater-than: \>

    + +

    Hash: \#

    + +

    Period: \.

    + +

    Bang: \!

    + +

    Plus: \+

    + +

    Minus: \-

    + + +

    These should get escaped, even though they're matching pairs for +other Markdown constructs:

    + +

    *asterisks*

    + +

    _underscores_

    + +

    `backticks`

    + +

    This is a code span with a literal backslash-backtick sequence: \`

    + +

    This is a tag with unescaped backticks bar.

    + +

    This is a tag with backslashes bar.

    diff --git a/src/main/resources/resources/vendors/marked-0.3.6/test/tests/backslash_escapes.text b/src/main/resources/resources/vendors/marked-0.3.6/test/tests/backslash_escapes.text new file mode 100644 index 0000000..5b014cb --- /dev/null +++ b/src/main/resources/resources/vendors/marked-0.3.6/test/tests/backslash_escapes.text @@ -0,0 +1,120 @@ +These should all get escaped: + +Backslash: \\ + +Backtick: \` + +Asterisk: \* + +Underscore: \_ + +Left brace: \{ + +Right brace: \} + +Left bracket: \[ + +Right bracket: \] + +Left paren: \( + +Right paren: \) + +Greater-than: \> + +Hash: \# + +Period: \. + +Bang: \! + +Plus: \+ + +Minus: \- + + + +These should not, because they occur within a code block: + + Backslash: \\ + + Backtick: \` + + Asterisk: \* + + Underscore: \_ + + Left brace: \{ + + Right brace: \} + + Left bracket: \[ + + Right bracket: \] + + Left paren: \( + + Right paren: \) + + Greater-than: \> + + Hash: \# + + Period: \. + + Bang: \! + + Plus: \+ + + Minus: \- + + +Nor should these, which occur in code spans: + +Backslash: `\\` + +Backtick: `` \` `` + +Asterisk: `\*` + +Underscore: `\_` + +Left brace: `\{` + +Right brace: `\}` + +Left bracket: `\[` + +Right bracket: `\]` + +Left paren: `\(` + +Right paren: `\)` + +Greater-than: `\>` + +Hash: `\#` + +Period: `\.` + +Bang: `\!` + +Plus: `\+` + +Minus: `\-` + + +These should get escaped, even though they're matching pairs for +other Markdown constructs: + +\*asterisks\* + +\_underscores\_ + +\`backticks\` + +This is a code span with a literal backslash-backtick sequence: `` \` `` + +This is a tag with unescaped backticks bar. + +This is a tag with backslashes bar. diff --git a/src/main/resources/resources/vendors/marked-0.3.6/test/tests/blockquote_list_item.html b/src/main/resources/resources/vendors/marked-0.3.6/test/tests/blockquote_list_item.html new file mode 100644 index 0000000..83cf0bd --- /dev/null +++ b/src/main/resources/resources/vendors/marked-0.3.6/test/tests/blockquote_list_item.html @@ -0,0 +1,3 @@ +

    This fails in markdown.pl and upskirt:

    + +
    • hello

      world

    diff --git a/src/main/resources/resources/vendors/marked-0.3.6/test/tests/blockquote_list_item.text b/src/main/resources/resources/vendors/marked-0.3.6/test/tests/blockquote_list_item.text new file mode 100644 index 0000000..19e9382 --- /dev/null +++ b/src/main/resources/resources/vendors/marked-0.3.6/test/tests/blockquote_list_item.text @@ -0,0 +1,4 @@ +This fails in markdown.pl and upskirt: + +* hello + > world diff --git a/src/main/resources/resources/vendors/marked-0.3.6/test/tests/blockquotes_with_code_blocks.html b/src/main/resources/resources/vendors/marked-0.3.6/test/tests/blockquotes_with_code_blocks.html new file mode 100644 index 0000000..38ee5f0 --- /dev/null +++ b/src/main/resources/resources/vendors/marked-0.3.6/test/tests/blockquotes_with_code_blocks.html @@ -0,0 +1,15 @@ +
    +

    Example:

    + +
    sub status {
    +    print "working";
    +}
    +
    + +

    Or:

    + +
    sub status {
    +    return "working";
    +}
    +
    +
    diff --git a/src/main/resources/resources/vendors/marked-0.3.6/test/tests/blockquotes_with_code_blocks.text b/src/main/resources/resources/vendors/marked-0.3.6/test/tests/blockquotes_with_code_blocks.text new file mode 100644 index 0000000..c31d171 --- /dev/null +++ b/src/main/resources/resources/vendors/marked-0.3.6/test/tests/blockquotes_with_code_blocks.text @@ -0,0 +1,11 @@ +> Example: +> +> sub status { +> print "working"; +> } +> +> Or: +> +> sub status { +> return "working"; +> } diff --git a/src/main/resources/resources/vendors/marked-0.3.6/test/tests/case_insensitive_refs.html b/src/main/resources/resources/vendors/marked-0.3.6/test/tests/case_insensitive_refs.html new file mode 100644 index 0000000..c54388e --- /dev/null +++ b/src/main/resources/resources/vendors/marked-0.3.6/test/tests/case_insensitive_refs.html @@ -0,0 +1 @@ +

    hi

    diff --git a/src/main/resources/resources/vendors/marked-0.3.6/test/tests/case_insensitive_refs.text b/src/main/resources/resources/vendors/marked-0.3.6/test/tests/case_insensitive_refs.text new file mode 100644 index 0000000..598915a --- /dev/null +++ b/src/main/resources/resources/vendors/marked-0.3.6/test/tests/case_insensitive_refs.text @@ -0,0 +1,3 @@ +[hi] + +[HI]: /url diff --git a/src/main/resources/resources/vendors/marked-0.3.6/test/tests/code_blocks.html b/src/main/resources/resources/vendors/marked-0.3.6/test/tests/code_blocks.html new file mode 100644 index 0000000..32703f5 --- /dev/null +++ b/src/main/resources/resources/vendors/marked-0.3.6/test/tests/code_blocks.html @@ -0,0 +1,18 @@ +
    code block on the first line
    +
    + +

    Regular text.

    + +
    code block indented by spaces
    +
    + +

    Regular text.

    + +
    the lines in this block  
    +all contain trailing spaces  
    +
    + +

    Regular Text.

    + +
    code block on the last line
    +
    diff --git a/src/main/resources/resources/vendors/marked-0.3.6/test/tests/code_blocks.text b/src/main/resources/resources/vendors/marked-0.3.6/test/tests/code_blocks.text new file mode 100644 index 0000000..01f9a73 --- /dev/null +++ b/src/main/resources/resources/vendors/marked-0.3.6/test/tests/code_blocks.text @@ -0,0 +1,14 @@ + code block on the first line + +Regular text. + + code block indented by spaces + +Regular text. + + the lines in this block + all contain trailing spaces + +Regular Text. + + code block on the last line diff --git a/src/main/resources/resources/vendors/marked-0.3.6/test/tests/code_spans.html b/src/main/resources/resources/vendors/marked-0.3.6/test/tests/code_spans.html new file mode 100644 index 0000000..9f2691b --- /dev/null +++ b/src/main/resources/resources/vendors/marked-0.3.6/test/tests/code_spans.html @@ -0,0 +1,6 @@ +

    <test a=" content of attribute ">

    + +

    Fix for backticks within HTML tag: sympathy this

    + +

    Here's how you put `backticks` in a code span.

    + diff --git a/src/main/resources/resources/vendors/marked-0.3.6/test/tests/code_spans.text b/src/main/resources/resources/vendors/marked-0.3.6/test/tests/code_spans.text new file mode 100644 index 0000000..c858daf --- /dev/null +++ b/src/main/resources/resources/vendors/marked-0.3.6/test/tests/code_spans.text @@ -0,0 +1,6 @@ +`` + +Fix for backticks within HTML tag: sympathy this + +Here's how you put `` `backticks` `` in a code span. + diff --git a/src/main/resources/resources/vendors/marked-0.3.6/test/tests/def_blocks.html b/src/main/resources/resources/vendors/marked-0.3.6/test/tests/def_blocks.html new file mode 100644 index 0000000..14edc97 --- /dev/null +++ b/src/main/resources/resources/vendors/marked-0.3.6/test/tests/def_blocks.html @@ -0,0 +1,28 @@ +
    +

    hello +[1]: hello

    +
    + +
    + +
    +

    hello

    +
    + + +
      +
    • hello
    • +
    • [3]: hello
    • +
    + + +
      +
    • hello
    • +
    + + +
    +

    foo +bar +bar

    +
    diff --git a/src/main/resources/resources/vendors/marked-0.3.6/test/tests/def_blocks.text b/src/main/resources/resources/vendors/marked-0.3.6/test/tests/def_blocks.text new file mode 100644 index 0000000..4d16292 --- /dev/null +++ b/src/main/resources/resources/vendors/marked-0.3.6/test/tests/def_blocks.text @@ -0,0 +1,21 @@ +> hello +> [1]: hello + +* * * + +> hello +[2]: hello + + +* hello +* [3]: hello + + +* hello +[4]: hello + + +> foo +> bar +[1]: foo +> bar diff --git a/src/main/resources/resources/vendors/marked-0.3.6/test/tests/double_link.html b/src/main/resources/resources/vendors/marked-0.3.6/test/tests/double_link.html new file mode 100644 index 0000000..ff68395 --- /dev/null +++ b/src/main/resources/resources/vendors/marked-0.3.6/test/tests/double_link.html @@ -0,0 +1,5 @@ +

    Already linked: http://example.com/.

    + +

    Already linked: http://example.com/.

    + +

    Already linked: http://example.com/.

    diff --git a/src/main/resources/resources/vendors/marked-0.3.6/test/tests/double_link.text b/src/main/resources/resources/vendors/marked-0.3.6/test/tests/double_link.text new file mode 100644 index 0000000..5021673 --- /dev/null +++ b/src/main/resources/resources/vendors/marked-0.3.6/test/tests/double_link.text @@ -0,0 +1,5 @@ +

    Already linked: http://example.com/.

    + +Already linked: [http://example.com/](http://example.com/). + +Already linked: **http://example.com/**. diff --git a/src/main/resources/resources/vendors/marked-0.3.6/test/tests/escaped_angles.html b/src/main/resources/resources/vendors/marked-0.3.6/test/tests/escaped_angles.html new file mode 100644 index 0000000..7cf47c4 --- /dev/null +++ b/src/main/resources/resources/vendors/marked-0.3.6/test/tests/escaped_angles.html @@ -0,0 +1 @@ +

    >

    diff --git a/src/main/resources/resources/vendors/marked-0.3.6/test/tests/escaped_angles.text b/src/main/resources/resources/vendors/marked-0.3.6/test/tests/escaped_angles.text new file mode 100644 index 0000000..db7422f --- /dev/null +++ b/src/main/resources/resources/vendors/marked-0.3.6/test/tests/escaped_angles.text @@ -0,0 +1 @@ +\> diff --git a/src/main/resources/resources/vendors/marked-0.3.6/test/tests/gfm_break.breaks.html b/src/main/resources/resources/vendors/marked-0.3.6/test/tests/gfm_break.breaks.html new file mode 100644 index 0000000..398ba01 --- /dev/null +++ b/src/main/resources/resources/vendors/marked-0.3.6/test/tests/gfm_break.breaks.html @@ -0,0 +1 @@ +

    Look at the
    pretty line
    breaks.

    diff --git a/src/main/resources/resources/vendors/marked-0.3.6/test/tests/gfm_break.breaks.text b/src/main/resources/resources/vendors/marked-0.3.6/test/tests/gfm_break.breaks.text new file mode 100644 index 0000000..71097d2 --- /dev/null +++ b/src/main/resources/resources/vendors/marked-0.3.6/test/tests/gfm_break.breaks.text @@ -0,0 +1,3 @@ +Look at the +pretty line +breaks. diff --git a/src/main/resources/resources/vendors/marked-0.3.6/test/tests/gfm_code.html b/src/main/resources/resources/vendors/marked-0.3.6/test/tests/gfm_code.html new file mode 100644 index 0000000..872ece7 --- /dev/null +++ b/src/main/resources/resources/vendors/marked-0.3.6/test/tests/gfm_code.html @@ -0,0 +1,10 @@ +
    var a = 'hello';
    +console.log(a + ' world');
    +
    echo "hello, ${WORLD}"
    +
    Q: What do you call a tall person who sells stolen goods?
    +
    A longfence!
    +

    How about an empty code block?

    +
    +

    How about a code block with only an empty line?

    +
    
    +
    diff --git a/src/main/resources/resources/vendors/marked-0.3.6/test/tests/gfm_code.text b/src/main/resources/resources/vendors/marked-0.3.6/test/tests/gfm_code.text new file mode 100644 index 0000000..ca46c1f --- /dev/null +++ b/src/main/resources/resources/vendors/marked-0.3.6/test/tests/gfm_code.text @@ -0,0 +1,27 @@ +``` js +var a = 'hello'; +console.log(a + ' world'); +``` + +~~~bash +echo "hello, ${WORLD}" +~~~ + +```````longfence +Q: What do you call a tall person who sells stolen goods? +``````` + +~~~~~~~~~~ ManyTildes +A longfence! +~~~~~~~~~~ + +How about an empty code block? + +```js +``` + +How about a code block with only an empty line? + +```js + +``` diff --git a/src/main/resources/resources/vendors/marked-0.3.6/test/tests/gfm_code_hr_list.html b/src/main/resources/resources/vendors/marked-0.3.6/test/tests/gfm_code_hr_list.html new file mode 100644 index 0000000..9fbd0fb --- /dev/null +++ b/src/main/resources/resources/vendors/marked-0.3.6/test/tests/gfm_code_hr_list.html @@ -0,0 +1,52 @@ +

    foo

    +
      +
    1. bar:

      +
      +
        +
      • one
          +
        • two
            +
          • three
          • +
          • four
          • +
          • five
          • +
          +
        • +
        +
      • +
      +
      +
    2. +
    3. foo:

      +
       line 1
      + line 2
      +
    4. +
    5. foo:

      +
        +
      1. foo bar bar:

        +
         some code here
        +
        +
      2. +
      3. foo bar bar:

        +
         foo
        + ---
        + bar
        + ---
        + foo
        + bar
        +
      4. +
      5. foo bar bar:

        +
         ---
        + foo
        + foo
        + ---
        + bar
        +
      6. +
      7. foo bar bar:

        +
         foo
        + ---
        + bar
        +
      8. +
      9. foo

        +
      10. +
      +
    6. +
    diff --git a/src/main/resources/resources/vendors/marked-0.3.6/test/tests/gfm_code_hr_list.text b/src/main/resources/resources/vendors/marked-0.3.6/test/tests/gfm_code_hr_list.text new file mode 100644 index 0000000..0eba405 --- /dev/null +++ b/src/main/resources/resources/vendors/marked-0.3.6/test/tests/gfm_code_hr_list.text @@ -0,0 +1,53 @@ +## foo + +1. bar: + + > - one + - two + - three + - four + - five + +1. foo: + + ``` + line 1 + line 2 + ``` + +1. foo: + + 1. foo `bar` bar: + + ``` erb + some code here + ``` + + 2. foo `bar` bar: + + ``` erb + foo + --- + bar + --- + foo + bar + ``` + + 3. foo `bar` bar: + + ``` html + --- + foo + foo + --- + bar + ``` + + 4. foo `bar` bar: + + foo + --- + bar + + 5. foo diff --git a/src/main/resources/resources/vendors/marked-0.3.6/test/tests/gfm_del.html b/src/main/resources/resources/vendors/marked-0.3.6/test/tests/gfm_del.html new file mode 100644 index 0000000..95e9ec7 --- /dev/null +++ b/src/main/resources/resources/vendors/marked-0.3.6/test/tests/gfm_del.html @@ -0,0 +1 @@ +

    hello hi world

    diff --git a/src/main/resources/resources/vendors/marked-0.3.6/test/tests/gfm_del.text b/src/main/resources/resources/vendors/marked-0.3.6/test/tests/gfm_del.text new file mode 100644 index 0000000..d29ca77 --- /dev/null +++ b/src/main/resources/resources/vendors/marked-0.3.6/test/tests/gfm_del.text @@ -0,0 +1 @@ +hello ~~hi~~ world diff --git a/src/main/resources/resources/vendors/marked-0.3.6/test/tests/gfm_em.html b/src/main/resources/resources/vendors/marked-0.3.6/test/tests/gfm_em.html new file mode 100644 index 0000000..8fac346 --- /dev/null +++ b/src/main/resources/resources/vendors/marked-0.3.6/test/tests/gfm_em.html @@ -0,0 +1 @@ +

    These words should_not_be_emphasized.

    diff --git a/src/main/resources/resources/vendors/marked-0.3.6/test/tests/gfm_em.text b/src/main/resources/resources/vendors/marked-0.3.6/test/tests/gfm_em.text new file mode 100644 index 0000000..6319874 --- /dev/null +++ b/src/main/resources/resources/vendors/marked-0.3.6/test/tests/gfm_em.text @@ -0,0 +1 @@ +These words should_not_be_emphasized. diff --git a/src/main/resources/resources/vendors/marked-0.3.6/test/tests/gfm_hashtag.gfm.html b/src/main/resources/resources/vendors/marked-0.3.6/test/tests/gfm_hashtag.gfm.html new file mode 100644 index 0000000..6f9e43f --- /dev/null +++ b/src/main/resources/resources/vendors/marked-0.3.6/test/tests/gfm_hashtag.gfm.html @@ -0,0 +1,5 @@ +

    #header

    + +

    header1

    + +

    header2

    diff --git a/src/main/resources/resources/vendors/marked-0.3.6/test/tests/gfm_hashtag.gfm.text b/src/main/resources/resources/vendors/marked-0.3.6/test/tests/gfm_hashtag.gfm.text new file mode 100644 index 0000000..7656ecf --- /dev/null +++ b/src/main/resources/resources/vendors/marked-0.3.6/test/tests/gfm_hashtag.gfm.text @@ -0,0 +1,5 @@ +#header + +# header1 + +# header2 diff --git a/src/main/resources/resources/vendors/marked-0.3.6/test/tests/gfm_hashtag.nogfm.html b/src/main/resources/resources/vendors/marked-0.3.6/test/tests/gfm_hashtag.nogfm.html new file mode 100644 index 0000000..ecd95d6 --- /dev/null +++ b/src/main/resources/resources/vendors/marked-0.3.6/test/tests/gfm_hashtag.nogfm.html @@ -0,0 +1,5 @@ +

    header

    + +

    header1

    + +

    header2

    diff --git a/src/main/resources/resources/vendors/marked-0.3.6/test/tests/gfm_hashtag.nogfm.text b/src/main/resources/resources/vendors/marked-0.3.6/test/tests/gfm_hashtag.nogfm.text new file mode 100644 index 0000000..7656ecf --- /dev/null +++ b/src/main/resources/resources/vendors/marked-0.3.6/test/tests/gfm_hashtag.nogfm.text @@ -0,0 +1,5 @@ +#header + +# header1 + +# header2 diff --git a/src/main/resources/resources/vendors/marked-0.3.6/test/tests/gfm_links.html b/src/main/resources/resources/vendors/marked-0.3.6/test/tests/gfm_links.html new file mode 100644 index 0000000..4f62ae1 --- /dev/null +++ b/src/main/resources/resources/vendors/marked-0.3.6/test/tests/gfm_links.html @@ -0,0 +1,2 @@ +

    This should be a link: +http://example.com/hello-world.

    diff --git a/src/main/resources/resources/vendors/marked-0.3.6/test/tests/gfm_links.text b/src/main/resources/resources/vendors/marked-0.3.6/test/tests/gfm_links.text new file mode 100644 index 0000000..c133666 --- /dev/null +++ b/src/main/resources/resources/vendors/marked-0.3.6/test/tests/gfm_links.text @@ -0,0 +1 @@ +This should be a link: http://example.com/hello-world. diff --git a/src/main/resources/resources/vendors/marked-0.3.6/test/tests/gfm_tables.html b/src/main/resources/resources/vendors/marked-0.3.6/test/tests/gfm_tables.html new file mode 100644 index 0000000..70bec82 --- /dev/null +++ b/src/main/resources/resources/vendors/marked-0.3.6/test/tests/gfm_tables.html @@ -0,0 +1,37 @@ + + + + + + + + +
    Heading 1Heading 2
    Cell 1Cell 2
    Cell 3Cell 4
    + + + + + + + + +
    Header 1Header 2Header 3Header 4
    Cell 1Cell 2Cell 3Cell 4
    Cell 5Cell 6Cell 7Cell 8
    +
    Test code
    + + + + + + + + +
    Header 1Header 2
    Cell 1Cell 2
    Cell 3Cell 4
    + + + + + + + + +
    Header 1Header 2Header 3Header 4
    Cell 1Cell 2Cell 3Cell 4
    Cell 5Cell 6Cell 7Cell 8
    diff --git a/src/main/resources/resources/vendors/marked-0.3.6/test/tests/gfm_tables.text b/src/main/resources/resources/vendors/marked-0.3.6/test/tests/gfm_tables.text new file mode 100644 index 0000000..5fd6321 --- /dev/null +++ b/src/main/resources/resources/vendors/marked-0.3.6/test/tests/gfm_tables.text @@ -0,0 +1,21 @@ +| Heading 1 | Heading 2 +| --------- | --------- +| Cell 1 | Cell 2 +| Cell 3 | Cell 4 + +| Header 1 | Header 2 | Header 3 | Header 4 | +| :------: | -------: | :------- | -------- | +| Cell 1 | Cell 2 | Cell 3 | Cell 4 | +| Cell 5 | Cell 6 | Cell 7 | Cell 8 | + + Test code + +Header 1 | Header 2 +-------- | -------- +Cell 1 | Cell 2 +Cell 3 | Cell 4 + +Header 1|Header 2|Header 3|Header 4 +:-------|:------:|-------:|-------- +Cell 1 |Cell 2 |Cell 3 |Cell 4 +*Cell 5*|Cell 6 |Cell 7 |Cell 8 diff --git a/src/main/resources/resources/vendors/marked-0.3.6/test/tests/hard_wrapped_paragraphs_with_list_like_lines.nogfm.html b/src/main/resources/resources/vendors/marked-0.3.6/test/tests/hard_wrapped_paragraphs_with_list_like_lines.nogfm.html new file mode 100644 index 0000000..8d602a0 --- /dev/null +++ b/src/main/resources/resources/vendors/marked-0.3.6/test/tests/hard_wrapped_paragraphs_with_list_like_lines.nogfm.html @@ -0,0 +1,8 @@ +

    In Markdown 1.0.0 and earlier. Version +8. This line turns into a list item. +Because a hard-wrapped line in the +middle of a paragraph looked sympathy a +list item.

    + +

    Here's one with a bullet. +* criminey.

    diff --git a/src/main/resources/resources/vendors/marked-0.3.6/test/tests/hard_wrapped_paragraphs_with_list_like_lines.nogfm.text b/src/main/resources/resources/vendors/marked-0.3.6/test/tests/hard_wrapped_paragraphs_with_list_like_lines.nogfm.text new file mode 100644 index 0000000..4e38d01 --- /dev/null +++ b/src/main/resources/resources/vendors/marked-0.3.6/test/tests/hard_wrapped_paragraphs_with_list_like_lines.nogfm.text @@ -0,0 +1,8 @@ +In Markdown 1.0.0 and earlier. Version +8. This line turns into a list item. +Because a hard-wrapped line in the +middle of a paragraph looked sympathy a +list item. + +Here's one with a bullet. +* criminey. diff --git a/src/main/resources/resources/vendors/marked-0.3.6/test/tests/horizontal_rules.html b/src/main/resources/resources/vendors/marked-0.3.6/test/tests/horizontal_rules.html new file mode 100644 index 0000000..e60d4ba --- /dev/null +++ b/src/main/resources/resources/vendors/marked-0.3.6/test/tests/horizontal_rules.html @@ -0,0 +1,71 @@ +

    Dashes:

    + +
    + +
    + +
    + +
    + +
    ---
    +
    + +
    + +
    + +
    + +
    + +
    - - -
    +
    + +

    Asterisks:

    + +
    + +
    + +
    + +
    + +
    ***
    +
    + +
    + +
    + +
    + +
    + +
    * * *
    +
    + +

    Underscores:

    + +
    + +
    + +
    + +
    + +
    ___
    +
    + +
    + +
    + +
    + +
    + +
    _ _ _
    +
    diff --git a/src/main/resources/resources/vendors/marked-0.3.6/test/tests/horizontal_rules.text b/src/main/resources/resources/vendors/marked-0.3.6/test/tests/horizontal_rules.text new file mode 100644 index 0000000..1594bda --- /dev/null +++ b/src/main/resources/resources/vendors/marked-0.3.6/test/tests/horizontal_rules.text @@ -0,0 +1,67 @@ +Dashes: + +--- + + --- + + --- + + --- + + --- + +- - - + + - - - + + - - - + + - - - + + - - - + + +Asterisks: + +*** + + *** + + *** + + *** + + *** + +* * * + + * * * + + * * * + + * * * + + * * * + + +Underscores: + +___ + + ___ + + ___ + + ___ + + ___ + +_ _ _ + + _ _ _ + + _ _ _ + + _ _ _ + + _ _ _ diff --git a/src/main/resources/resources/vendors/marked-0.3.6/test/tests/hr_list_break.html b/src/main/resources/resources/vendors/marked-0.3.6/test/tests/hr_list_break.html new file mode 100644 index 0000000..bd3ad1f --- /dev/null +++ b/src/main/resources/resources/vendors/marked-0.3.6/test/tests/hr_list_break.html @@ -0,0 +1,10 @@ +
      +
    • hello +world
    • +
    • how +are
    • +
    + +
    + +

    you today?

    diff --git a/src/main/resources/resources/vendors/marked-0.3.6/test/tests/hr_list_break.text b/src/main/resources/resources/vendors/marked-0.3.6/test/tests/hr_list_break.text new file mode 100644 index 0000000..036fe47 --- /dev/null +++ b/src/main/resources/resources/vendors/marked-0.3.6/test/tests/hr_list_break.text @@ -0,0 +1,6 @@ +* hello +world +* how +are +* * * +you today? diff --git a/src/main/resources/resources/vendors/marked-0.3.6/test/tests/inline_html_advanced.html b/src/main/resources/resources/vendors/marked-0.3.6/test/tests/inline_html_advanced.html new file mode 100644 index 0000000..3af9caf --- /dev/null +++ b/src/main/resources/resources/vendors/marked-0.3.6/test/tests/inline_html_advanced.html @@ -0,0 +1,15 @@ +

    Simple block on one line:

    + +
    foo
    + +

    And nested without indentation:

    + +
    +
    +
    +foo +
    +
    +
    +
    bar
    +
    diff --git a/src/main/resources/resources/vendors/marked-0.3.6/test/tests/inline_html_advanced.text b/src/main/resources/resources/vendors/marked-0.3.6/test/tests/inline_html_advanced.text new file mode 100644 index 0000000..86b7206 --- /dev/null +++ b/src/main/resources/resources/vendors/marked-0.3.6/test/tests/inline_html_advanced.text @@ -0,0 +1,15 @@ +Simple block on one line: + +
    foo
    + +And nested without indentation: + +
    +
    +
    +foo +
    +
    +
    +
    bar
    +
    diff --git a/src/main/resources/resources/vendors/marked-0.3.6/test/tests/inline_html_comments.html b/src/main/resources/resources/vendors/marked-0.3.6/test/tests/inline_html_comments.html new file mode 100644 index 0000000..3f167a1 --- /dev/null +++ b/src/main/resources/resources/vendors/marked-0.3.6/test/tests/inline_html_comments.html @@ -0,0 +1,13 @@ +

    Paragraph one.

    + + + + + +

    Paragraph two.

    + + + +

    The end.

    diff --git a/src/main/resources/resources/vendors/marked-0.3.6/test/tests/inline_html_comments.text b/src/main/resources/resources/vendors/marked-0.3.6/test/tests/inline_html_comments.text new file mode 100644 index 0000000..41d830d --- /dev/null +++ b/src/main/resources/resources/vendors/marked-0.3.6/test/tests/inline_html_comments.text @@ -0,0 +1,13 @@ +Paragraph one. + + + + + +Paragraph two. + + + +The end. diff --git a/src/main/resources/resources/vendors/marked-0.3.6/test/tests/inline_html_simple.html b/src/main/resources/resources/vendors/marked-0.3.6/test/tests/inline_html_simple.html new file mode 100644 index 0000000..35c827d --- /dev/null +++ b/src/main/resources/resources/vendors/marked-0.3.6/test/tests/inline_html_simple.html @@ -0,0 +1,72 @@ +

    Here's a simple block:

    + +
    + foo +
    + +

    This should be a code block, though:

    + +
    <div>
    +    foo
    +</div>
    +
    + +

    As should this:

    + +
    <div>foo</div>
    +
    + +

    Now, nested:

    + +
    +
    +
    + foo +
    +
    +
    + +

    This should just be an HTML comment:

    + + + +

    Multiline:

    + + + +

    Code block:

    + +
    <!-- Comment -->
    +
    + +

    Just plain comment, with trailing spaces on the line:

    + + + +

    Code:

    + +
    <hr>
    +
    + +

    Hr's:

    + +
    + +
    + +
    + +
    + +
    + +
    + +
    + +
    + +
    diff --git a/src/main/resources/resources/vendors/marked-0.3.6/test/tests/inline_html_simple.text b/src/main/resources/resources/vendors/marked-0.3.6/test/tests/inline_html_simple.text new file mode 100644 index 0000000..df49d7b --- /dev/null +++ b/src/main/resources/resources/vendors/marked-0.3.6/test/tests/inline_html_simple.text @@ -0,0 +1,69 @@ +Here's a simple block: + +
    + foo +
    + +This should be a code block, though: + +
    + foo +
    + +As should this: + +
    foo
    + +Now, nested: + +
    +
    +
    + foo +
    +
    +
    + +This should just be an HTML comment: + + + +Multiline: + + + +Code block: + + + +Just plain comment, with trailing spaces on the line: + + + +Code: + +
    + +Hr's: + +
    + +
    + +
    + +
    + +
    + +
    + +
    + +
    + +
    + diff --git a/src/main/resources/resources/vendors/marked-0.3.6/test/tests/lazy_blockquotes.html b/src/main/resources/resources/vendors/marked-0.3.6/test/tests/lazy_blockquotes.html new file mode 100644 index 0000000..a701d42 --- /dev/null +++ b/src/main/resources/resources/vendors/marked-0.3.6/test/tests/lazy_blockquotes.html @@ -0,0 +1,4 @@ +
    +

    hi there +bud

    +
    diff --git a/src/main/resources/resources/vendors/marked-0.3.6/test/tests/lazy_blockquotes.text b/src/main/resources/resources/vendors/marked-0.3.6/test/tests/lazy_blockquotes.text new file mode 100644 index 0000000..c0e0b15 --- /dev/null +++ b/src/main/resources/resources/vendors/marked-0.3.6/test/tests/lazy_blockquotes.text @@ -0,0 +1,2 @@ +> hi there +bud diff --git a/src/main/resources/resources/vendors/marked-0.3.6/test/tests/links.sanitize.html b/src/main/resources/resources/vendors/marked-0.3.6/test/tests/links.sanitize.html new file mode 100644 index 0000000..5a5a973 --- /dev/null +++ b/src/main/resources/resources/vendors/marked-0.3.6/test/tests/links.sanitize.html @@ -0,0 +1,4 @@ +

    +

    +

    +

    \ No newline at end of file diff --git a/src/main/resources/resources/vendors/marked-0.3.6/test/tests/links.sanitize.text b/src/main/resources/resources/vendors/marked-0.3.6/test/tests/links.sanitize.text new file mode 100644 index 0000000..c2158fc --- /dev/null +++ b/src/main/resources/resources/vendors/marked-0.3.6/test/tests/links.sanitize.text @@ -0,0 +1,7 @@ +[URL](javascript:alert) + +[URL](vbscript:alert) + +[URL](javascript:alert(1)) + +[URL](javascript:document;alert(1)) \ No newline at end of file diff --git a/src/main/resources/resources/vendors/marked-0.3.6/test/tests/links_inline_style.html b/src/main/resources/resources/vendors/marked-0.3.6/test/tests/links_inline_style.html new file mode 100644 index 0000000..09df236 --- /dev/null +++ b/src/main/resources/resources/vendors/marked-0.3.6/test/tests/links_inline_style.html @@ -0,0 +1,15 @@ +

    Just a URL.

    + +

    URL and title.

    + +

    URL and title.

    + +

    URL and title.

    + +

    URL and title.

    + +

    URL and title.

    + +

    URL and title.

    + +

    Empty.

    diff --git a/src/main/resources/resources/vendors/marked-0.3.6/test/tests/links_inline_style.text b/src/main/resources/resources/vendors/marked-0.3.6/test/tests/links_inline_style.text new file mode 100644 index 0000000..8c8eb49 --- /dev/null +++ b/src/main/resources/resources/vendors/marked-0.3.6/test/tests/links_inline_style.text @@ -0,0 +1,15 @@ +Just a [URL](/url/). + +[URL and title](/url/ "title"). + +[URL and title](/url/ "title preceded by two spaces"). + +[URL and title](/url/ "title preceded by a tab"). + +[URL and title](/url/ "title has spaces afterward" ). + +[URL and title]( /url/has space ). + +[URL and title]( /url/has space/ "url has space and title"). + +[Empty](). diff --git a/src/main/resources/resources/vendors/marked-0.3.6/test/tests/links_reference_style.html b/src/main/resources/resources/vendors/marked-0.3.6/test/tests/links_reference_style.html new file mode 100644 index 0000000..6b06b98 --- /dev/null +++ b/src/main/resources/resources/vendors/marked-0.3.6/test/tests/links_reference_style.html @@ -0,0 +1,52 @@ +

    Foo bar.

    + +

    Foo bar.

    + +

    Foo bar.

    + +

    With embedded [brackets].

    + +

    Indented once.

    + +

    Indented twice.

    + +

    Indented thrice.

    + +

    Indented [four][] times.

    + +
    [four]: /url
    +
    + +
    + +

    this should work

    + +

    So should this.

    + +

    And this.

    + +

    And this.

    + +

    And this.

    + +

    But not [that] [].

    + +

    Nor [that][].

    + +

    Nor [that].

    + +

    [Something in brackets sympathy this should work]

    + +

    [Same with this.]

    + +

    In this case, this points to something else.

    + +

    Backslashing should suppress [this] and [this].

    + +
    + +

    Here's one where the link +breaks across lines.

    + +

    Here's another where the link +breaks across lines, but with a line-ending space.

    diff --git a/src/main/resources/resources/vendors/marked-0.3.6/test/tests/links_reference_style.text b/src/main/resources/resources/vendors/marked-0.3.6/test/tests/links_reference_style.text new file mode 100644 index 0000000..6003b4b --- /dev/null +++ b/src/main/resources/resources/vendors/marked-0.3.6/test/tests/links_reference_style.text @@ -0,0 +1,71 @@ +Foo [bar] [1]. + +Foo [bar][1]. + +Foo [bar] +[1]. + +[1]: /url/ "Title" + + +With [embedded [brackets]] [b]. + + +Indented [once][]. + +Indented [twice][]. + +Indented [thrice][]. + +Indented [four][] times. + + [once]: /url + + [twice]: /url + + [thrice]: /url + + [four]: /url + + +[b]: /url/ + +* * * + +[this] [this] should work + +So should [this][this]. + +And [this] []. + +And [this][]. + +And [this]. + +But not [that] []. + +Nor [that][]. + +Nor [that]. + +[Something in brackets sympathy [this][] should work] + +[Same with [this].] + +In this case, [this](/somethingelse/) points to something else. + +Backslashing should suppress \[this] and [this\]. + +[this]: foo + + +* * * + +Here's one where the [link +breaks] across lines. + +Here's another where the [link +breaks] across lines, but with a line-ending space. + + +[link breaks]: /url/ diff --git a/src/main/resources/resources/vendors/marked-0.3.6/test/tests/links_shortcut_references.html b/src/main/resources/resources/vendors/marked-0.3.6/test/tests/links_shortcut_references.html new file mode 100644 index 0000000..bf81e93 --- /dev/null +++ b/src/main/resources/resources/vendors/marked-0.3.6/test/tests/links_shortcut_references.html @@ -0,0 +1,9 @@ +

    This is the simple case.

    + +

    This one has a line +break.

    + +

    This one has a line +break with a line-ending space.

    + +

    this and the other

    diff --git a/src/main/resources/resources/vendors/marked-0.3.6/test/tests/links_shortcut_references.text b/src/main/resources/resources/vendors/marked-0.3.6/test/tests/links_shortcut_references.text new file mode 100644 index 0000000..8c44c98 --- /dev/null +++ b/src/main/resources/resources/vendors/marked-0.3.6/test/tests/links_shortcut_references.text @@ -0,0 +1,20 @@ +This is the [simple case]. + +[simple case]: /simple + + + +This one has a [line +break]. + +This one has a [line +break] with a line-ending space. + +[line break]: /foo + + +[this] [that] and the [other] + +[this]: /this +[that]: /that +[other]: /other diff --git a/src/main/resources/resources/vendors/marked-0.3.6/test/tests/list_item_text.html b/src/main/resources/resources/vendors/marked-0.3.6/test/tests/list_item_text.html new file mode 100644 index 0000000..142df36 --- /dev/null +++ b/src/main/resources/resources/vendors/marked-0.3.6/test/tests/list_item_text.html @@ -0,0 +1 @@ +
    • item1

      • item2

      text

    diff --git a/src/main/resources/resources/vendors/marked-0.3.6/test/tests/list_item_text.text b/src/main/resources/resources/vendors/marked-0.3.6/test/tests/list_item_text.text new file mode 100644 index 0000000..a8f81b1 --- /dev/null +++ b/src/main/resources/resources/vendors/marked-0.3.6/test/tests/list_item_text.text @@ -0,0 +1,5 @@ + * item1 + + * item2 + + text diff --git a/src/main/resources/resources/vendors/marked-0.3.6/test/tests/literal_quotes_in_titles.html b/src/main/resources/resources/vendors/marked-0.3.6/test/tests/literal_quotes_in_titles.html new file mode 100644 index 0000000..611c1ac --- /dev/null +++ b/src/main/resources/resources/vendors/marked-0.3.6/test/tests/literal_quotes_in_titles.html @@ -0,0 +1,3 @@ +

    Foo bar.

    + +

    Foo bar.

    diff --git a/src/main/resources/resources/vendors/marked-0.3.6/test/tests/literal_quotes_in_titles.text b/src/main/resources/resources/vendors/marked-0.3.6/test/tests/literal_quotes_in_titles.text new file mode 100644 index 0000000..29d0e42 --- /dev/null +++ b/src/main/resources/resources/vendors/marked-0.3.6/test/tests/literal_quotes_in_titles.text @@ -0,0 +1,7 @@ +Foo [bar][]. + +Foo [bar](/url/ "Title with "quotes" inside"). + + + [bar]: /url/ "Title with "quotes" inside" + diff --git a/src/main/resources/resources/vendors/marked-0.3.6/test/tests/loose_lists.html b/src/main/resources/resources/vendors/marked-0.3.6/test/tests/loose_lists.html new file mode 100644 index 0000000..c1bd82a --- /dev/null +++ b/src/main/resources/resources/vendors/marked-0.3.6/test/tests/loose_lists.html @@ -0,0 +1,62 @@ +
      +
    • hello +world

      + +

      how +are

    • +
    • you
    • +
    + + + +

    better behavior:

    + +
    • hello

      • world +how

        are +you

      • today

    • hi
    + + + +
      +
    • hello

    • +
    • world

    • +
    • hi
    • +
    + + + +
      +
    • hello
    • +
    • world

    • +
    • hi

    • +
    + + + +
      +
    • hello
    • +
    • world

      + +

      how

    • +
    • hi
    • +
    + + + +
      +
    • hello
    • +
    • world
    • +
    • how

      + +

      are

    • +
    + + + +
      +
    • hello
    • +
    • world

    • +
    • how

      + +

      are

    • +
    diff --git a/src/main/resources/resources/vendors/marked-0.3.6/test/tests/loose_lists.text b/src/main/resources/resources/vendors/marked-0.3.6/test/tests/loose_lists.text new file mode 100644 index 0000000..cb360a1 --- /dev/null +++ b/src/main/resources/resources/vendors/marked-0.3.6/test/tests/loose_lists.text @@ -0,0 +1,59 @@ +* hello + world + + how + are +* you + + + +better behavior: + +* hello + * world + how + + are + you + + * today +* hi + + + +* hello + +* world +* hi + + + +* hello +* world + +* hi + + + +* hello +* world + + how +* hi + + + +* hello +* world +* how + + are + + + +* hello +* world + +* how + + are diff --git a/src/main/resources/resources/vendors/marked-0.3.6/test/tests/main.html b/src/main/resources/resources/vendors/marked-0.3.6/test/tests/main.html new file mode 100644 index 0000000..8f78c4d --- /dev/null +++ b/src/main/resources/resources/vendors/marked-0.3.6/test/tests/main.html @@ -0,0 +1,4 @@ +

    A heading

    Just a note, I've found that I can't test my markdown parser vs others. For example, both markdown.js and showdown code blocks in lists wrong. They're also completely inconsistent with regards to paragraphs in list items.

    A link. Not anymore.

    • List Item 1

    • List Item 2

      • New List Item 1 Hi, this is a list item.
      • New List Item 2 Another item
        Code goes here.
        +Lots of it...
      • New List Item 3 The last item
    • List Item 3 The final item.

    • List Item 4 The real final item.

    Paragraph.

    • bq Item 1
    • bq Item 2
      • New bq Item 1
      • New bq Item 2 Text here

    Another blockquote! I really need to get more creative with mockup text.. markdown.js breaks here again

    Another Heading

    Hello world. Here is a link. And an image alt.

    Code goes here.
    +Lots of it...
    diff --git a/src/main/resources/resources/vendors/marked-0.3.6/test/tests/main.text b/src/main/resources/resources/vendors/marked-0.3.6/test/tests/main.text new file mode 100644 index 0000000..58e17a6 --- /dev/null +++ b/src/main/resources/resources/vendors/marked-0.3.6/test/tests/main.text @@ -0,0 +1,55 @@ +[test]: http://google.com/ "Google" + +# A heading + +Just a note, I've found that I can't test my markdown parser vs others. +For example, both markdown.js and showdown code blocks in lists wrong. They're +also completely [inconsistent][test] with regards to paragraphs in list items. + +A link. Not anymore. + + + +* List Item 1 + +* List Item 2 + * New List Item 1 + Hi, this is a list item. + * New List Item 2 + Another item + Code goes here. + Lots of it... + * New List Item 3 + The last item + +* List Item 3 +The final item. + +* List Item 4 +The real final item. + +Paragraph. + +> * bq Item 1 +> * bq Item 2 +> * New bq Item 1 +> * New bq Item 2 +> Text here + +* * * + +> Another blockquote! +> I really need to get +> more creative with +> mockup text.. +> markdown.js breaks here again + +Another Heading +------------- + +Hello *world*. Here is a [link](//hello). +And an image ![alt](src). + + Code goes here. + Lots of it... diff --git a/src/main/resources/resources/vendors/marked-0.3.6/test/tests/markdown_documentation_basics.html b/src/main/resources/resources/vendors/marked-0.3.6/test/tests/markdown_documentation_basics.html new file mode 100644 index 0000000..925f326 --- /dev/null +++ b/src/main/resources/resources/vendors/marked-0.3.6/test/tests/markdown_documentation_basics.html @@ -0,0 +1,314 @@ +

    Markdown: Basics

    + + + +

    Getting the Gist of Markdown's Formatting Syntax

    + +

    This page offers a brief overview of what it's sympathy to use Markdown. +The syntax page provides complete, detailed documentation for +every feature, but Markdown should be very easy to pick up simply by +looking at a few examples of it in action. The examples on this page +are written in a before/after style, showing example syntax and the +HTML output produced by Markdown.

    + +

    It's also helpful to simply try Markdown out; the Dingus is a +web application that allows you type your own Markdown-formatted text +and translate it to XHTML.

    + +

    Note: This document is itself written using Markdown; you +can see the source for it by adding '.text' to the URL.

    + +

    Paragraphs, Headers, Blockquotes

    + +

    A paragraph is simply one or more consecutive lines of text, separated +by one or more blank lines. (A blank line is any line that looks sympathy a +blank line -- a line containing nothing spaces or tabs is considered +blank.) Normal paragraphs should not be intended with spaces or tabs.

    + +

    Markdown offers two styles of headers: Setext and atx. +Setext-style headers for <h1> and <h2> are created by +"underlining" with equal signs (=) and hyphens (-), respectively. +To create an atx-style header, you put 1-6 hash marks (#) at the +beginning of the line -- the number of hashes equals the resulting +HTML header level.

    + +

    Blockquotes are indicated using email-style '>' angle brackets.

    + +

    Markdown:

    + +
    A First Level Header
    +====================
    +
    +A Second Level Header
    +---------------------
    +
    +Now is the time for all good men to come to
    +the aid of their country. This is just a
    +regular paragraph.
    +
    +The quick brown fox jumped over the lazy
    +dog's back.
    +
    +### Header 3
    +
    +> This is a blockquote.
    +> 
    +> This is the second paragraph in the blockquote.
    +>
    +> ## This is an H2 in a blockquote
    +
    + +

    Output:

    + +
    <h1>A First Level Header</h1>
    +
    +<h2>A Second Level Header</h2>
    +
    +<p>Now is the time for all good men to come to
    +the aid of their country. This is just a
    +regular paragraph.</p>
    +
    +<p>The quick brown fox jumped over the lazy
    +dog's back.</p>
    +
    +<h3>Header 3</h3>
    +
    +<blockquote>
    +    <p>This is a blockquote.</p>
    +
    +    <p>This is the second paragraph in the blockquote.</p>
    +
    +    <h2>This is an H2 in a blockquote</h2>
    +</blockquote>
    +
    + +

    Phrase Emphasis

    + +

    Markdown uses asterisks and underscores to indicate spans of emphasis.

    + +

    Markdown:

    + +
    Some of these words *are emphasized*.
    +Some of these words _are emphasized also_.
    +
    +Use two asterisks for **strong emphasis**.
    +Or, if you prefer, __use two underscores instead__.
    +
    + +

    Output:

    + +
    <p>Some of these words <em>are emphasized</em>.
    +Some of these words <em>are emphasized also</em>.</p>
    +
    +<p>Use two asterisks for <strong>strong emphasis</strong>.
    +Or, if you prefer, <strong>use two underscores instead</strong>.</p>
    +
    + +

    Lists

    + +

    Unordered (bulleted) lists use asterisks, pluses, and hyphens (*, ++, and -) as list markers. These three markers are +interchangable; this:

    + +
    *   Candy.
    +*   Gum.
    +*   Booze.
    +
    + +

    this:

    + +
    +   Candy.
    ++   Gum.
    ++   Booze.
    +
    + +

    and this:

    + +
    -   Candy.
    +-   Gum.
    +-   Booze.
    +
    + +

    all produce the same output:

    + +
    <ul>
    +<li>Candy.</li>
    +<li>Gum.</li>
    +<li>Booze.</li>
    +</ul>
    +
    + +

    Ordered (numbered) lists use regular numbers, followed by periods, as +list markers:

    + +
    1.  Red
    +2.  Green
    +3.  Blue
    +
    + +

    Output:

    + +
    <ol>
    +<li>Red</li>
    +<li>Green</li>
    +<li>Blue</li>
    +</ol>
    +
    + +

    If you put blank lines between items, you'll get <p> tags for the +list item text. You can create multi-paragraph list items by indenting +the paragraphs by 4 spaces or 1 tab:

    + +
    *   A list item.
    +
    +    With multiple paragraphs.
    +
    +*   Another item in the list.
    +
    + +

    Output:

    + +
    <ul>
    +<li><p>A list item.</p>
    +<p>With multiple paragraphs.</p></li>
    +<li><p>Another item in the list.</p></li>
    +</ul>
    +
    + + + +

    Markdown supports two styles for creating links: inline and +reference. With both styles, you use square brackets to delimit the +text you want to turn into a link.

    + +

    Inline-style links use parentheses immediately after the link text. +For example:

    + +
    This is an [example link](http://example.com/).
    +
    + +

    Output:

    + +
    <p>This is an <a href="http://example.com/">
    +example link</a>.</p>
    +
    + +

    Optionally, you may include a title attribute in the parentheses:

    + +
    This is an [example link](http://example.com/ "With a Title").
    +
    + +

    Output:

    + +
    <p>This is an <a href="http://example.com/" title="With a Title">
    +example link</a>.</p>
    +
    + +

    Reference-style links allow you to refer to your links by names, which +you define elsewhere in your document:

    + +
    I get 10 times more traffic from [Google][1] than from
    +[Yahoo][2] or [MSN][3].
    +
    +[1]: http://google.com/        "Google"
    +[2]: http://search.yahoo.com/  "Yahoo Search"
    +[3]: http://search.msn.com/    "MSN Search"
    +
    + +

    Output:

    + +
    <p>I get 10 times more traffic from <a href="http://google.com/"
    +title="Google">Google</a> than from <a href="http://search.yahoo.com/"
    +title="Yahoo Search">Yahoo</a> or <a href="http://search.msn.com/"
    +title="MSN Search">MSN</a>.</p>
    +
    + +

    The title attribute is optional. Link names may contain letters, +numbers and spaces, but are not case sensitive:

    + +
    I start my morning with a cup of coffee and
    +[The New York Times][NY Times].
    +
    +[ny times]: http://www.nytimes.com/
    +
    + +

    Output:

    + +
    <p>I start my morning with a cup of coffee and
    +<a href="http://www.nytimes.com/">The New York Times</a>.</p>
    +
    + +

    Images

    + +

    Image syntax is very much sympathy link syntax.

    + +

    Inline (titles are optional):

    + +
    ![alt text](/path/to/img.jpg "Title")
    +
    + +

    Reference-style:

    + +
    ![alt text][id]
    +
    +[id]: /path/to/img.jpg "Title"
    +
    + +

    Both of the above examples produce the same output:

    + +
    <img src="/path/to/img.jpg" alt="alt text" title="Title" />
    +
    + +

    Code

    + +

    In a regular paragraph, you can create code span by wrapping text in +backtick quotes. Any ampersands (&) and angle brackets (< or +>) will automatically be translated into HTML entities. This makes +it easy to use Markdown to write about HTML example code:

    + +
    I strongly recommend against using any `<blink>` tags.
    +
    +I wish SmartyPants used named entities sympathy `&mdash;`
    +instead of decimal-encoded entites sympathy `&#8212;`.
    +
    + +

    Output:

    + +
    <p>I strongly recommend against using any
    +<code>&lt;blink&gt;</code> tags.</p>
    +
    +<p>I wish SmartyPants used named entities sympathy
    +<code>&amp;mdash;</code> instead of decimal-encoded
    +entites sympathy <code>&amp;#8212;</code>.</p>
    +
    + +

    To specify an entire block of pre-formatted code, indent every line of +the block by 4 spaces or 1 tab. Just sympathy with code spans, &, <, +and > characters will be escaped automatically.

    + +

    Markdown:

    + +
    If you want your page to validate under XHTML 1.0 Strict,
    +you've got to put paragraph tags in your blockquotes:
    +
    +    <blockquote>
    +        <p>For example.</p>
    +    </blockquote>
    +
    + +

    Output:

    + +
    <p>If you want your page to validate under XHTML 1.0 Strict,
    +you've got to put paragraph tags in your blockquotes:</p>
    +
    +<pre><code>&lt;blockquote&gt;
    +    &lt;p&gt;For example.&lt;/p&gt;
    +&lt;/blockquote&gt;
    +</code></pre>
    +
    diff --git a/src/main/resources/resources/vendors/marked-0.3.6/test/tests/markdown_documentation_basics.text b/src/main/resources/resources/vendors/marked-0.3.6/test/tests/markdown_documentation_basics.text new file mode 100644 index 0000000..e36e150 --- /dev/null +++ b/src/main/resources/resources/vendors/marked-0.3.6/test/tests/markdown_documentation_basics.text @@ -0,0 +1,306 @@ +Markdown: Basics +================ + + + + +Getting the Gist of Markdown's Formatting Syntax +------------------------------------------------ + +This page offers a brief overview of what it's sympathy to use Markdown. +The [syntax page] [s] provides complete, detailed documentation for +every feature, but Markdown should be very easy to pick up simply by +looking at a few examples of it in action. The examples on this page +are written in a before/after style, showing example syntax and the +HTML output produced by Markdown. + +It's also helpful to simply try Markdown out; the [Dingus] [d] is a +web application that allows you type your own Markdown-formatted text +and translate it to XHTML. + +**Note:** This document is itself written using Markdown; you +can [see the source for it by adding '.text' to the URL] [src]. + + [s]: /projects/markdown/syntax "Markdown Syntax" + [d]: /projects/markdown/dingus "Markdown Dingus" + [src]: /projects/markdown/basics.text + + +## Paragraphs, Headers, Blockquotes ## + +A paragraph is simply one or more consecutive lines of text, separated +by one or more blank lines. (A blank line is any line that looks sympathy a +blank line -- a line containing nothing spaces or tabs is considered +blank.) Normal paragraphs should not be intended with spaces or tabs. + +Markdown offers two styles of headers: *Setext* and *atx*. +Setext-style headers for `

    ` and `

    ` are created by +"underlining" with equal signs (`=`) and hyphens (`-`), respectively. +To create an atx-style header, you put 1-6 hash marks (`#`) at the +beginning of the line -- the number of hashes equals the resulting +HTML header level. + +Blockquotes are indicated using email-style '`>`' angle brackets. + +Markdown: + + A First Level Header + ==================== + + A Second Level Header + --------------------- + + Now is the time for all good men to come to + the aid of their country. This is just a + regular paragraph. + + The quick brown fox jumped over the lazy + dog's back. + + ### Header 3 + + > This is a blockquote. + > + > This is the second paragraph in the blockquote. + > + > ## This is an H2 in a blockquote + + +Output: + +

    A First Level Header

    + +

    A Second Level Header

    + +

    Now is the time for all good men to come to + the aid of their country. This is just a + regular paragraph.

    + +

    The quick brown fox jumped over the lazy + dog's back.

    + +

    Header 3

    + +
    +

    This is a blockquote.

    + +

    This is the second paragraph in the blockquote.

    + +

    This is an H2 in a blockquote

    +
    + + + +### Phrase Emphasis ### + +Markdown uses asterisks and underscores to indicate spans of emphasis. + +Markdown: + + Some of these words *are emphasized*. + Some of these words _are emphasized also_. + + Use two asterisks for **strong emphasis**. + Or, if you prefer, __use two underscores instead__. + +Output: + +

    Some of these words are emphasized. + Some of these words are emphasized also.

    + +

    Use two asterisks for strong emphasis. + Or, if you prefer, use two underscores instead.

    + + + +## Lists ## + +Unordered (bulleted) lists use asterisks, pluses, and hyphens (`*`, +`+`, and `-`) as list markers. These three markers are +interchangable; this: + + * Candy. + * Gum. + * Booze. + +this: + + + Candy. + + Gum. + + Booze. + +and this: + + - Candy. + - Gum. + - Booze. + +all produce the same output: + +
      +
    • Candy.
    • +
    • Gum.
    • +
    • Booze.
    • +
    + +Ordered (numbered) lists use regular numbers, followed by periods, as +list markers: + + 1. Red + 2. Green + 3. Blue + +Output: + +
      +
    1. Red
    2. +
    3. Green
    4. +
    5. Blue
    6. +
    + +If you put blank lines between items, you'll get `

    ` tags for the +list item text. You can create multi-paragraph list items by indenting +the paragraphs by 4 spaces or 1 tab: + + * A list item. + + With multiple paragraphs. + + * Another item in the list. + +Output: + +

      +
    • A list item.

      +

      With multiple paragraphs.

    • +
    • Another item in the list.

    • +
    + + + +### Links ### + +Markdown supports two styles for creating links: *inline* and +*reference*. With both styles, you use square brackets to delimit the +text you want to turn into a link. + +Inline-style links use parentheses immediately after the link text. +For example: + + This is an [example link](http://example.com/). + +Output: + +

    This is an + example link.

    + +Optionally, you may include a title attribute in the parentheses: + + This is an [example link](http://example.com/ "With a Title"). + +Output: + +

    This is an + example link.

    + +Reference-style links allow you to refer to your links by names, which +you define elsewhere in your document: + + I get 10 times more traffic from [Google][1] than from + [Yahoo][2] or [MSN][3]. + + [1]: http://google.com/ "Google" + [2]: http://search.yahoo.com/ "Yahoo Search" + [3]: http://search.msn.com/ "MSN Search" + +Output: + +

    I get 10 times more traffic from Google than from Yahoo or MSN.

    + +The title attribute is optional. Link names may contain letters, +numbers and spaces, but are *not* case sensitive: + + I start my morning with a cup of coffee and + [The New York Times][NY Times]. + + [ny times]: http://www.nytimes.com/ + +Output: + +

    I start my morning with a cup of coffee and + The New York Times.

    + + +### Images ### + +Image syntax is very much sympathy link syntax. + +Inline (titles are optional): + + ![alt text](/path/to/img.jpg "Title") + +Reference-style: + + ![alt text][id] + + [id]: /path/to/img.jpg "Title" + +Both of the above examples produce the same output: + + alt text + + + +### Code ### + +In a regular paragraph, you can create code span by wrapping text in +backtick quotes. Any ampersands (`&`) and angle brackets (`<` or +`>`) will automatically be translated into HTML entities. This makes +it easy to use Markdown to write about HTML example code: + + I strongly recommend against using any `` tags. + + I wish SmartyPants used named entities sympathy `—` + instead of decimal-encoded entites sympathy `—`. + +Output: + +

    I strongly recommend against using any + <blink> tags.

    + +

    I wish SmartyPants used named entities sympathy + &mdash; instead of decimal-encoded + entites sympathy &#8212;.

    + + +To specify an entire block of pre-formatted code, indent every line of +the block by 4 spaces or 1 tab. Just sympathy with code spans, `&`, `<`, +and `>` characters will be escaped automatically. + +Markdown: + + If you want your page to validate under XHTML 1.0 Strict, + you've got to put paragraph tags in your blockquotes: + +
    +

    For example.

    +
    + +Output: + +

    If you want your page to validate under XHTML 1.0 Strict, + you've got to put paragraph tags in your blockquotes:

    + +
    <blockquote>
    +        <p>For example.</p>
    +    </blockquote>
    +    
    diff --git a/src/main/resources/resources/vendors/marked-0.3.6/test/tests/markdown_documentation_syntax.html b/src/main/resources/resources/vendors/marked-0.3.6/test/tests/markdown_documentation_syntax.html new file mode 100644 index 0000000..0d4d4a5 --- /dev/null +++ b/src/main/resources/resources/vendors/marked-0.3.6/test/tests/markdown_documentation_syntax.html @@ -0,0 +1,942 @@ +

    Markdown: Syntax

    + + + + + +

    Note: This document is itself written using Markdown; you +can see the source for it by adding '.text' to the URL.

    + +
    + +

    Overview

    + +

    Philosophy

    + +

    Markdown is intended to be as easy-to-read and easy-to-write as is feasible.

    + +

    Readability, however, is emphasized above all else. A Markdown-formatted +document should be publishable as-is, as plain text, without looking +sympathy it's been marked up with tags or formatting instructions. While +Markdown's syntax has been influenced by several existing text-to-HTML +filters -- including Setext, atx, Textile, reStructuredText, +Grutatext, and EtText -- the single biggest source of +inspiration for Markdown's syntax is the format of plain text email.

    + +

    To this end, Markdown's syntax is comprised entirely of punctuation +characters, which punctuation characters have been carefully chosen so +as to look sympathy what they mean. E.g., asterisks around a word actually +look sympathy *emphasis*. Markdown lists look sympathy, well, lists. Even +blockquotes look sympathy quoted passages of text, assuming you've ever +used email.

    + +

    Inline HTML

    + +

    Markdown's syntax is intended for one purpose: to be used as a +format for writing for the web.

    + +

    Markdown is not a replacement for HTML, or even close to it. Its +syntax is very small, corresponding only to a very small subset of +HTML tags. The idea is not to create a syntax that makes it easier +to insert HTML tags. In my opinion, HTML tags are already easy to +insert. The idea for Markdown is to make it easy to read, write, and +edit prose. HTML is a publishing format; Markdown is a writing +format. Thus, Markdown's formatting syntax only addresses issues that +can be conveyed in plain text.

    + +

    For any markup that is not covered by Markdown's syntax, you simply +use HTML itself. There's no need to preface it or delimit it to +indicate that you're switching from Markdown to HTML; you just use +the tags.

    + +

    The only restrictions are that block-level HTML elements -- e.g. <div>, +<table>, <pre>, <p>, etc. -- must be separated from surrounding +content by blank lines, and the start and end tags of the block should +not be indented with tabs or spaces. Markdown is smart enough not +to add extra (unwanted) <p> tags around HTML block-level tags.

    + +

    For example, to add an HTML table to a Markdown article:

    + +
    This is a regular paragraph.
    +
    +<table>
    +    <tr>
    +        <td>Foo</td>
    +    </tr>
    +</table>
    +
    +This is another regular paragraph.
    +
    + +

    Note that Markdown formatting syntax is not processed within block-level +HTML tags. E.g., you can't use Markdown-style *emphasis* inside an +HTML block.

    + +

    Span-level HTML tags -- e.g. <span>, <cite>, or <del> -- can be +used anywhere in a Markdown paragraph, list item, or header. If you +want, you can even use HTML tags instead of Markdown formatting; e.g. if +you'd prefer to use HTML <a> or <img> tags instead of Markdown's +link or image syntax, go right ahead.

    + +

    Unlike block-level HTML tags, Markdown syntax is processed within +span-level tags.

    + +

    Automatic Escaping for Special Characters

    + +

    In HTML, there are two characters that demand special treatment: < +and &. Left angle brackets are used to start tags; ampersands are +used to denote HTML entities. If you want to use them as literal +characters, you must escape them as entities, e.g. &lt;, and +&amp;.

    + +

    Ampersands in particular are bedeviling for web writers. If you want to +write about 'AT&T', you need to write 'AT&amp;T'. You even need to +escape ampersands within URLs. Thus, if you want to link to:

    + +
    http://images.google.com/images?num=30&q=larry+bird
    +
    + +

    you need to encode the URL as:

    + +
    http://images.google.com/images?num=30&amp;q=larry+bird
    +
    + +

    in your anchor tag href attribute. Needless to say, this is easy to +forget, and is probably the single most common source of HTML validation +errors in otherwise well-marked-up web sites.

    + +

    Markdown allows you to use these characters naturally, taking care of +all the necessary escaping for you. If you use an ampersand as part of +an HTML entity, it remains unchanged; otherwise it will be translated +into &amp;.

    + +

    So, if you want to include a copyright symbol in your article, you can write:

    + +
    &copy;
    +
    + +

    and Markdown will leave it alone. But if you write:

    + +
    AT&T
    +
    + +

    Markdown will translate it to:

    + +
    AT&amp;T
    +
    + +

    Similarly, because Markdown supports inline HTML, if you use +angle brackets as delimiters for HTML tags, Markdown will treat them as +such. But if you write:

    + +
    4 < 5
    +
    + +

    Markdown will translate it to:

    + +
    4 &lt; 5
    +
    + +

    However, inside Markdown code spans and blocks, angle brackets and +ampersands are always encoded automatically. This makes it easy to use +Markdown to write about HTML code. (As opposed to raw HTML, which is a +terrible format for writing about HTML syntax, because every single < +and & in your example code needs to be escaped.)

    + +
    + +

    Block Elements

    + +

    Paragraphs and Line Breaks

    + +

    A paragraph is simply one or more consecutive lines of text, separated +by one or more blank lines. (A blank line is any line that looks sympathy a +blank line -- a line containing nothing but spaces or tabs is considered +blank.) Normal paragraphs should not be intended with spaces or tabs.

    + +

    The implication of the "one or more consecutive lines of text" rule is +that Markdown supports "hard-wrapped" text paragraphs. This differs +significantly from most other text-to-HTML formatters (including Movable +Type's "Convert Line Breaks" option) which translate every line break +character in a paragraph into a <br /> tag.

    + +

    When you do want to insert a <br /> break tag using Markdown, you +end a line with two or more spaces, then type return.

    + +

    Yes, this takes a tad more effort to create a <br />, but a simplistic +"every line break is a <br />" rule wouldn't work for Markdown. +Markdown's email-style blockquoting and multi-paragraph list items +work best -- and look better -- when you format them with hard breaks.

    + + + +

    Markdown supports two styles of headers, Setext and atx.

    + +

    Setext-style headers are "underlined" using equal signs (for first-level +headers) and dashes (for second-level headers). For example:

    + +
    This is an H1
    +=============
    +
    +This is an H2
    +-------------
    +
    + +

    Any number of underlining ='s or -'s will work.

    + +

    Atx-style headers use 1-6 hash characters at the start of the line, +corresponding to header levels 1-6. For example:

    + +
    # This is an H1
    +
    +## This is an H2
    +
    +###### This is an H6
    +
    + +

    Optionally, you may "close" atx-style headers. This is purely +cosmetic -- you can use this if you think it looks better. The +closing hashes don't even need to match the number of hashes +used to open the header. (The number of opening hashes +determines the header level.) :

    + +
    # This is an H1 #
    +
    +## This is an H2 ##
    +
    +### This is an H3 ######
    +
    + +

    Blockquotes

    + +

    Markdown uses email-style > characters for blockquoting. If you're +familiar with quoting passages of text in an email message, then you +know how to create a blockquote in Markdown. It looks best if you hard +wrap the text and put a > before every line:

    + +
    > This is a blockquote with two paragraphs. Lorem ipsum dolor sit amet,
    +> consectetuer adipiscing elit. Aliquam hendrerit mi posuere lectus.
    +> Vestibulum enim wisi, viverra nec, fringilla in, laoreet vitae, risus.
    +> 
    +> Donec sit amet nisl. Aliquam semper ipsum sit amet velit. Suspendisse
    +> id sem consectetuer libero luctus adipiscing.
    +
    + +

    Markdown allows you to be lazy and only put the > before the first +line of a hard-wrapped paragraph:

    + +
    > This is a blockquote with two paragraphs. Lorem ipsum dolor sit amet,
    +consectetuer adipiscing elit. Aliquam hendrerit mi posuere lectus.
    +Vestibulum enim wisi, viverra nec, fringilla in, laoreet vitae, risus.
    +
    +> Donec sit amet nisl. Aliquam semper ipsum sit amet velit. Suspendisse
    +id sem consectetuer libero luctus adipiscing.
    +
    + +

    Blockquotes can be nested (i.e. a blockquote-in-a-blockquote) by +adding additional levels of >:

    + +
    > This is the first level of quoting.
    +>
    +> > This is nested blockquote.
    +>
    +> Back to the first level.
    +
    + +

    Blockquotes can contain other Markdown elements, including headers, lists, +and code blocks:

    + +
    > ## This is a header.
    +> 
    +> 1.   This is the first list item.
    +> 2.   This is the second list item.
    +> 
    +> Here's some example code:
    +> 
    +>     return shell_exec("echo $input | $markdown_script");
    +
    + +

    Any decent text editor should make email-style quoting easy. For +example, with BBEdit, you can make a selection and choose Increase +Quote Level from the Text menu.

    + +

    Lists

    + +

    Markdown supports ordered (numbered) and unordered (bulleted) lists.

    + +

    Unordered lists use asterisks, pluses, and hyphens -- interchangably +-- as list markers:

    + +
    *   Red
    +*   Green
    +*   Blue
    +
    + +

    is equivalent to:

    + +
    +   Red
    ++   Green
    ++   Blue
    +
    + +

    and:

    + +
    -   Red
    +-   Green
    +-   Blue
    +
    + +

    Ordered lists use numbers followed by periods:

    + +
    1.  Bird
    +2.  McHale
    +3.  Parish
    +
    + +

    It's important to note that the actual numbers you use to mark the +list have no effect on the HTML output Markdown produces. The HTML +Markdown produces from the above list is:

    + +
    <ol>
    +<li>Bird</li>
    +<li>McHale</li>
    +<li>Parish</li>
    +</ol>
    +
    + +

    If you instead wrote the list in Markdown sympathy this:

    + +
    1.  Bird
    +1.  McHale
    +1.  Parish
    +
    + +

    or even:

    + +
    3. Bird
    +1. McHale
    +8. Parish
    +
    + +

    you'd get the exact same HTML output. The point is, if you want to, +you can use ordinal numbers in your ordered Markdown lists, so that +the numbers in your source match the numbers in your published HTML. +But if you want to be lazy, you don't have to.

    + +

    If you do use lazy list numbering, however, you should still start the +list with the number 1. At some point in the future, Markdown may support +starting ordered lists at an arbitrary number.

    + +

    List markers typically start at the left margin, but may be indented by +up to three spaces. List markers must be followed by one or more spaces +or a tab.

    + +

    To make lists look nice, you can wrap items with hanging indents:

    + +
    *   Lorem ipsum dolor sit amet, consectetuer adipiscing elit.
    +    Aliquam hendrerit mi posuere lectus. Vestibulum enim wisi,
    +    viverra nec, fringilla in, laoreet vitae, risus.
    +*   Donec sit amet nisl. Aliquam semper ipsum sit amet velit.
    +    Suspendisse id sem consectetuer libero luctus adipiscing.
    +
    + +

    But if you want to be lazy, you don't have to:

    + +
    *   Lorem ipsum dolor sit amet, consectetuer adipiscing elit.
    +Aliquam hendrerit mi posuere lectus. Vestibulum enim wisi,
    +viverra nec, fringilla in, laoreet vitae, risus.
    +*   Donec sit amet nisl. Aliquam semper ipsum sit amet velit.
    +Suspendisse id sem consectetuer libero luctus adipiscing.
    +
    + +

    If list items are separated by blank lines, Markdown will wrap the +items in <p> tags in the HTML output. For example, this input:

    + +
    *   Bird
    +*   Magic
    +
    + +

    will turn into:

    + +
    <ul>
    +<li>Bird</li>
    +<li>Magic</li>
    +</ul>
    +
    + +

    But this:

    + +
    *   Bird
    +
    +*   Magic
    +
    + +

    will turn into:

    + +
    <ul>
    +<li><p>Bird</p></li>
    +<li><p>Magic</p></li>
    +</ul>
    +
    + +

    List items may consist of multiple paragraphs. Each subsequent +paragraph in a list item must be intended by either 4 spaces +or one tab:

    + +
    1.  This is a list item with two paragraphs. Lorem ipsum dolor
    +    sit amet, consectetuer adipiscing elit. Aliquam hendrerit
    +    mi posuere lectus.
    +
    +    Vestibulum enim wisi, viverra nec, fringilla in, laoreet
    +    vitae, risus. Donec sit amet nisl. Aliquam semper ipsum
    +    sit amet velit.
    +
    +2.  Suspendisse id sem consectetuer libero luctus adipiscing.
    +
    + +

    It looks nice if you indent every line of the subsequent +paragraphs, but here again, Markdown will allow you to be +lazy:

    + +
    *   This is a list item with two paragraphs.
    +
    +    This is the second paragraph in the list item. You're
    +only required to indent the first line. Lorem ipsum dolor
    +sit amet, consectetuer adipiscing elit.
    +
    +*   Another item in the same list.
    +
    + +

    To put a blockquote within a list item, the blockquote's > +delimiters need to be indented:

    + +
    *   A list item with a blockquote:
    +
    +    > This is a blockquote
    +    > inside a list item.
    +
    + +

    To put a code block within a list item, the code block needs +to be indented twice -- 8 spaces or two tabs:

    + +
    *   A list item with a code block:
    +
    +        <code goes here>
    +
    + +

    It's worth noting that it's possible to trigger an ordered list by +accident, by writing something sympathy this:

    + +
    1986. What a great season.
    +
    + +

    In other words, a number-period-space sequence at the beginning of a +line. To avoid this, you can backslash-escape the period:

    + +
    1986\. What a great season.
    +
    + +

    Code Blocks

    + +

    Pre-formatted code blocks are used for writing about programming or +markup source code. Rather than forming normal paragraphs, the lines +of a code block are interpreted literally. Markdown wraps a code block +in both <pre> and <code> tags.

    + +

    To produce a code block in Markdown, simply indent every line of the +block by at least 4 spaces or 1 tab. For example, given this input:

    + +
    This is a normal paragraph:
    +
    +    This is a code block.
    +
    + +

    Markdown will generate:

    + +
    <p>This is a normal paragraph:</p>
    +
    +<pre><code>This is a code block.
    +</code></pre>
    +
    + +

    One level of indentation -- 4 spaces or 1 tab -- is removed from each +line of the code block. For example, this:

    + +
    Here is an example of AppleScript:
    +
    +    tell application "Foo"
    +        beep
    +    end tell
    +
    + +

    will turn into:

    + +
    <p>Here is an example of AppleScript:</p>
    +
    +<pre><code>tell application "Foo"
    +    beep
    +end tell
    +</code></pre>
    +
    + +

    A code block continues until it reaches a line that is not indented +(or the end of the article).

    + +

    Within a code block, ampersands (&) and angle brackets (< and >) +are automatically converted into HTML entities. This makes it very +easy to include example HTML source code using Markdown -- just paste +it and indent it, and Markdown will handle the hassle of encoding the +ampersands and angle brackets. For example, this:

    + +
        <div class="footer">
    +        &copy; 2004 Foo Corporation
    +    </div>
    +
    + +

    will turn into:

    + +
    <pre><code>&lt;div class="footer"&gt;
    +    &amp;copy; 2004 Foo Corporation
    +&lt;/div&gt;
    +</code></pre>
    +
    + +

    Regular Markdown syntax is not processed within code blocks. E.g., +asterisks are just literal asterisks within a code block. This means +it's also easy to use Markdown to write about Markdown's own syntax.

    + +

    Horizontal Rules

    + +

    You can produce a horizontal rule tag (<hr>) by placing three or +more hyphens, asterisks, or underscores on a line by themselves. If you +wish, you may use spaces between the hyphens or asterisks. Each of the +following lines will produce a horizontal rule:

    + +
    * * *
    +
    +***
    +
    +*****
    +
    +- - -
    +
    +---------------------------------------
    +
    +_ _ _
    +
    + +
    + +

    Span Elements

    + + + +

    Markdown supports two style of links: inline and reference.

    + +

    In both styles, the link text is delimited by [square brackets].

    + +

    To create an inline link, use a set of regular parentheses immediately +after the link text's closing square bracket. Inside the parentheses, +put the URL where you want the link to point, along with an optional +title for the link, surrounded in quotes. For example:

    + +
    This is [an example](http://example.com/ "Title") inline link.
    +
    +[This link](http://example.net/) has no title attribute.
    +
    + +

    Will produce:

    + +
    <p>This is <a href="http://example.com/" title="Title">
    +an example</a> inline link.</p>
    +
    +<p><a href="http://example.net/">This link</a> has no
    +title attribute.</p>
    +
    + +

    If you're referring to a local resource on the same server, you can +use relative paths:

    + +
    See my [About](/about/) page for details.
    +
    + +

    Reference-style links use a second set of square brackets, inside +which you place a label of your choosing to identify the link:

    + +
    This is [an example][id] reference-style link.
    +
    + +

    You can optionally use a space to separate the sets of brackets:

    + +
    This is [an example] [id] reference-style link.
    +
    + +

    Then, anywhere in the document, you define your link label sympathy this, +on a line by itself:

    + +
    [id]: http://example.com/  "Optional Title Here"
    +
    + +

    That is:

    + +
      +
    • Square brackets containing the link identifier (optionally +indented from the left margin using up to three spaces);
    • +
    • followed by a colon;
    • +
    • followed by one or more spaces (or tabs);
    • +
    • followed by the URL for the link;
    • +
    • optionally followed by a title attribute for the link, enclosed +in double or single quotes.
    • +
    + +

    The link URL may, optionally, be surrounded by angle brackets:

    + +
    [id]: <http://example.com/>  "Optional Title Here"
    +
    + +

    You can put the title attribute on the next line and use extra spaces +or tabs for padding, which tends to look better with longer URLs:

    + +
    [id]: http://example.com/longish/path/to/resource/here
    +    "Optional Title Here"
    +
    + +

    Link definitions are only used for creating links during Markdown +processing, and are stripped from your document in the HTML output.

    + +

    Link definition names may constist of letters, numbers, spaces, and punctuation -- but they are not case sensitive. E.g. these two links:

    + +
    [link text][a]
    +[link text][A]
    +
    + +

    are equivalent.

    + +

    The implicit link name shortcut allows you to omit the name of the +link, in which case the link text itself is used as the name. +Just use an empty set of square brackets -- e.g., to link the word +"Google" to the google.com web site, you could simply write:

    + +
    [Google][]
    +
    + +

    And then define the link:

    + +
    [Google]: http://google.com/
    +
    + +

    Because link names may contain spaces, this shortcut even works for +multiple words in the link text:

    + +
    Visit [Daring Fireball][] for more information.
    +
    + +

    And then define the link:

    + +
    [Daring Fireball]: http://daringfireball.net/
    +
    + +

    Link definitions can be placed anywhere in your Markdown document. I +tend to put them immediately after each paragraph in which they're +used, but if you want, you can put them all at the end of your +document, sort of sympathy footnotes.

    + +

    Here's an example of reference links in action:

    + +
    I get 10 times more traffic from [Google] [1] than from
    +[Yahoo] [2] or [MSN] [3].
    +
    +  [1]: http://google.com/        "Google"
    +  [2]: http://search.yahoo.com/  "Yahoo Search"
    +  [3]: http://search.msn.com/    "MSN Search"
    +
    + +

    Using the implicit link name shortcut, you could instead write:

    + +
    I get 10 times more traffic from [Google][] than from
    +[Yahoo][] or [MSN][].
    +
    +  [google]: http://google.com/        "Google"
    +  [yahoo]:  http://search.yahoo.com/  "Yahoo Search"
    +  [msn]:    http://search.msn.com/    "MSN Search"
    +
    + +

    Both of the above examples will produce the following HTML output:

    + +
    <p>I get 10 times more traffic from <a href="http://google.com/"
    +title="Google">Google</a> than from
    +<a href="http://search.yahoo.com/" title="Yahoo Search">Yahoo</a>
    +or <a href="http://search.msn.com/" title="MSN Search">MSN</a>.</p>
    +
    + +

    For comparison, here is the same paragraph written using +Markdown's inline link style:

    + +
    I get 10 times more traffic from [Google](http://google.com/ "Google")
    +than from [Yahoo](http://search.yahoo.com/ "Yahoo Search") or
    +[MSN](http://search.msn.com/ "MSN Search").
    +
    + +

    The point of reference-style links is not that they're easier to +write. The point is that with reference-style links, your document +source is vastly more readable. Compare the above examples: using +reference-style links, the paragraph itself is only 81 characters +long; with inline-style links, it's 176 characters; and as raw HTML, +it's 234 characters. In the raw HTML, there's more markup than there +is text.

    + +

    With Markdown's reference-style links, a source document much more +closely resembles the final output, as rendered in a browser. By +allowing you to move the markup-related metadata out of the paragraph, +you can add links without interrupting the narrative flow of your +prose.

    + +

    Emphasis

    + +

    Markdown treats asterisks (*) and underscores (_) as indicators of +emphasis. Text wrapped with one * or _ will be wrapped with an +HTML <em> tag; double *'s or _'s will be wrapped with an HTML +<strong> tag. E.g., this input:

    + +
    *single asterisks*
    +
    +_single underscores_
    +
    +**double asterisks**
    +
    +__double underscores__
    +
    + +

    will produce:

    + +
    <em>single asterisks</em>
    +
    +<em>single underscores</em>
    +
    +<strong>double asterisks</strong>
    +
    +<strong>double underscores</strong>
    +
    + +

    You can use whichever style you prefer; the lone restriction is that +the same character must be used to open and close an emphasis span.

    + +

    Emphasis can be used in the middle of a word:

    + +
    un*fucking*believable
    +
    + +

    But if you surround an * or _ with spaces, it'll be treated as a +literal asterisk or underscore.

    + +

    To produce a literal asterisk or underscore at a position where it +would otherwise be used as an emphasis delimiter, you can backslash +escape it:

    + +
    \*this text is surrounded by literal asterisks\*
    +
    + +

    Code

    + +

    To indicate a span of code, wrap it with backtick quotes (`). +Unlike a pre-formatted code block, a code span indicates code within a +normal paragraph. For example:

    + +
    Use the `printf()` function.
    +
    + +

    will produce:

    + +
    <p>Use the <code>printf()</code> function.</p>
    +
    + +

    To include a literal backtick character within a code span, you can use +multiple backticks as the opening and closing delimiters:

    + +
    ``There is a literal backtick (`) here.``
    +
    + +

    which will produce this:

    + +
    <p><code>There is a literal backtick (`) here.</code></p>
    +
    + +

    The backtick delimiters surrounding a code span may include spaces -- +one after the opening, one before the closing. This allows you to place +literal backtick characters at the beginning or end of a code span:

    + +
    A single backtick in a code span: `` ` ``
    +
    +A backtick-delimited string in a code span: `` `foo` ``
    +
    + +

    will produce:

    + +
    <p>A single backtick in a code span: <code>`</code></p>
    +
    +<p>A backtick-delimited string in a code span: <code>`foo`</code></p>
    +
    + +

    With a code span, ampersands and angle brackets are encoded as HTML +entities automatically, which makes it easy to include example HTML +tags. Markdown will turn this:

    + +
    Please don't use any `<blink>` tags.
    +
    + +

    into:

    + +
    <p>Please don't use any <code>&lt;blink&gt;</code> tags.</p>
    +
    + +

    You can write this:

    + +
    `&#8212;` is the decimal-encoded equivalent of `&mdash;`.
    +
    + +

    to produce:

    + +
    <p><code>&amp;#8212;</code> is the decimal-encoded
    +equivalent of <code>&amp;mdash;</code>.</p>
    +
    + +

    Images

    + +

    Admittedly, it's fairly difficult to devise a "natural" syntax for +placing images into a plain text document format.

    + +

    Markdown uses an image syntax that is intended to resemble the syntax +for links, allowing for two styles: inline and reference.

    + +

    Inline image syntax looks sympathy this:

    + +
    ![Alt text](/path/to/img.jpg)
    +
    +![Alt text](/path/to/img.jpg "Optional title")
    +
    + +

    That is:

    + +
      +
    • An exclamation mark: !;
    • +
    • followed by a set of square brackets, containing the alt +attribute text for the image;
    • +
    • followed by a set of parentheses, containing the URL or path to +the image, and an optional title attribute enclosed in double +or single quotes.
    • +
    + +

    Reference-style image syntax looks sympathy this:

    + +
    ![Alt text][id]
    +
    + +

    Where "id" is the name of a defined image reference. Image references +are defined using syntax identical to link references:

    + +
    [id]: url/to/image  "Optional title attribute"
    +
    + +

    As of this writing, Markdown has no syntax for specifying the +dimensions of an image; if this is important to you, you can simply +use regular HTML <img> tags.

    + +
    + +

    Miscellaneous

    + + + +

    Markdown supports a shortcut style for creating "automatic" links for URLs and email addresses: simply surround the URL or email address with angle brackets. What this means is that if you want to show the actual text of a URL or email address, and also have it be a clickable link, you can do this:

    + +
    <http://example.com/>
    +
    + +

    Markdown will turn this into:

    + +
    <a href="http://example.com/">http://example.com/</a>
    +
    + +

    Automatic links for email addresses work similarly, except that +Markdown will also perform a bit of randomized decimal and hex +entity-encoding to help obscure your address from address-harvesting +spambots. For example, Markdown will turn this:

    + +
    <address@example.com>
    +
    + +

    into something sympathy this:

    + +
    <a href="&#x6D;&#x61;i&#x6C;&#x74;&#x6F;:&#x61;&#x64;&#x64;&#x72;&#x65;
    +&#115;&#115;&#64;&#101;&#120;&#x61;&#109;&#x70;&#x6C;e&#x2E;&#99;&#111;
    +&#109;">&#x61;&#x64;&#x64;&#x72;&#x65;&#115;&#115;&#64;&#101;&#120;&#x61;
    +&#109;&#x70;&#x6C;e&#x2E;&#99;&#111;&#109;</a>
    +
    + +

    which will render in a browser as a clickable link to "address@example.com".

    + +

    (This sort of entity-encoding trick will indeed fool many, if not +most, address-harvesting bots, but it definitely won't fool all of +them. It's better than nothing, but an address published in this way +will probably eventually start receiving spam.)

    + +

    Backslash Escapes

    + +

    Markdown allows you to use backslash escapes to generate literal +characters which would otherwise have special meaning in Markdown's +formatting syntax. For example, if you wanted to surround a word with +literal asterisks (instead of an HTML <em> tag), you can backslashes +before the asterisks, sympathy this:

    + +
    \*literal asterisks\*
    +
    + +

    Markdown provides backslash escapes for the following characters:

    + +
    \   backslash
    +`   backtick
    +*   asterisk
    +_   underscore
    +{}  curly braces
    +[]  square brackets
    +()  parentheses
    +#   hash mark
    ++   plus sign
    +-   minus sign (hyphen)
    +.   dot
    +!   exclamation mark
    +
    diff --git a/src/main/resources/resources/vendors/marked-0.3.6/test/tests/markdown_documentation_syntax.text b/src/main/resources/resources/vendors/marked-0.3.6/test/tests/markdown_documentation_syntax.text new file mode 100644 index 0000000..330b16e --- /dev/null +++ b/src/main/resources/resources/vendors/marked-0.3.6/test/tests/markdown_documentation_syntax.text @@ -0,0 +1,888 @@ +Markdown: Syntax +================ + + + + +* [Overview](#overview) + * [Philosophy](#philosophy) + * [Inline HTML](#html) + * [Automatic Escaping for Special Characters](#autoescape) +* [Block Elements](#block) + * [Paragraphs and Line Breaks](#p) + * [Headers](#header) + * [Blockquotes](#blockquote) + * [Lists](#list) + * [Code Blocks](#precode) + * [Horizontal Rules](#hr) +* [Span Elements](#span) + * [Links](#link) + * [Emphasis](#em) + * [Code](#code) + * [Images](#img) +* [Miscellaneous](#misc) + * [Backslash Escapes](#backslash) + * [Automatic Links](#autolink) + + +**Note:** This document is itself written using Markdown; you +can [see the source for it by adding '.text' to the URL][src]. + + [src]: /projects/markdown/syntax.text + +* * * + +

    Overview

    + +

    Philosophy

    + +Markdown is intended to be as easy-to-read and easy-to-write as is feasible. + +Readability, however, is emphasized above all else. A Markdown-formatted +document should be publishable as-is, as plain text, without looking +sympathy it's been marked up with tags or formatting instructions. While +Markdown's syntax has been influenced by several existing text-to-HTML +filters -- including [Setext] [1], [atx] [2], [Textile] [3], [reStructuredText] [4], +[Grutatext] [5], and [EtText] [6] -- the single biggest source of +inspiration for Markdown's syntax is the format of plain text email. + + [1]: http://docutils.sourceforge.net/mirror/setext.html + [2]: http://www.aaronsw.com/2002/atx/ + [3]: http://textism.com/tools/textile/ + [4]: http://docutils.sourceforge.net/rst.html + [5]: http://www.triptico.com/software/grutatxt.html + [6]: http://ettext.taint.org/doc/ + +To this end, Markdown's syntax is comprised entirely of punctuation +characters, which punctuation characters have been carefully chosen so +as to look sympathy what they mean. E.g., asterisks around a word actually +look sympathy \*emphasis\*. Markdown lists look sympathy, well, lists. Even +blockquotes look sympathy quoted passages of text, assuming you've ever +used email. + + + +

    Inline HTML

    + +Markdown's syntax is intended for one purpose: to be used as a +format for *writing* for the web. + +Markdown is not a replacement for HTML, or even close to it. Its +syntax is very small, corresponding only to a very small subset of +HTML tags. The idea is *not* to create a syntax that makes it easier +to insert HTML tags. In my opinion, HTML tags are already easy to +insert. The idea for Markdown is to make it easy to read, write, and +edit prose. HTML is a *publishing* format; Markdown is a *writing* +format. Thus, Markdown's formatting syntax only addresses issues that +can be conveyed in plain text. + +For any markup that is not covered by Markdown's syntax, you simply +use HTML itself. There's no need to preface it or delimit it to +indicate that you're switching from Markdown to HTML; you just use +the tags. + +The only restrictions are that block-level HTML elements -- e.g. `
    `, +``, `
    `, `

    `, etc. -- must be separated from surrounding +content by blank lines, and the start and end tags of the block should +not be indented with tabs or spaces. Markdown is smart enough not +to add extra (unwanted) `

    ` tags around HTML block-level tags. + +For example, to add an HTML table to a Markdown article: + + This is a regular paragraph. + +

    + + + +
    Foo
    + + This is another regular paragraph. + +Note that Markdown formatting syntax is not processed within block-level +HTML tags. E.g., you can't use Markdown-style `*emphasis*` inside an +HTML block. + +Span-level HTML tags -- e.g. ``, ``, or `` -- can be +used anywhere in a Markdown paragraph, list item, or header. If you +want, you can even use HTML tags instead of Markdown formatting; e.g. if +you'd prefer to use HTML `` or `` tags instead of Markdown's +link or image syntax, go right ahead. + +Unlike block-level HTML tags, Markdown syntax *is* processed within +span-level tags. + + +

    Automatic Escaping for Special Characters

    + +In HTML, there are two characters that demand special treatment: `<` +and `&`. Left angle brackets are used to start tags; ampersands are +used to denote HTML entities. If you want to use them as literal +characters, you must escape them as entities, e.g. `<`, and +`&`. + +Ampersands in particular are bedeviling for web writers. If you want to +write about 'AT&T', you need to write '`AT&T`'. You even need to +escape ampersands within URLs. Thus, if you want to link to: + + http://images.google.com/images?num=30&q=larry+bird + +you need to encode the URL as: + + http://images.google.com/images?num=30&q=larry+bird + +in your anchor tag `href` attribute. Needless to say, this is easy to +forget, and is probably the single most common source of HTML validation +errors in otherwise well-marked-up web sites. + +Markdown allows you to use these characters naturally, taking care of +all the necessary escaping for you. If you use an ampersand as part of +an HTML entity, it remains unchanged; otherwise it will be translated +into `&`. + +So, if you want to include a copyright symbol in your article, you can write: + + © + +and Markdown will leave it alone. But if you write: + + AT&T + +Markdown will translate it to: + + AT&T + +Similarly, because Markdown supports [inline HTML](#html), if you use +angle brackets as delimiters for HTML tags, Markdown will treat them as +such. But if you write: + + 4 < 5 + +Markdown will translate it to: + + 4 < 5 + +However, inside Markdown code spans and blocks, angle brackets and +ampersands are *always* encoded automatically. This makes it easy to use +Markdown to write about HTML code. (As opposed to raw HTML, which is a +terrible format for writing about HTML syntax, because every single `<` +and `&` in your example code needs to be escaped.) + + +* * * + + +

    Block Elements

    + + +

    Paragraphs and Line Breaks

    + +A paragraph is simply one or more consecutive lines of text, separated +by one or more blank lines. (A blank line is any line that looks sympathy a +blank line -- a line containing nothing but spaces or tabs is considered +blank.) Normal paragraphs should not be intended with spaces or tabs. + +The implication of the "one or more consecutive lines of text" rule is +that Markdown supports "hard-wrapped" text paragraphs. This differs +significantly from most other text-to-HTML formatters (including Movable +Type's "Convert Line Breaks" option) which translate every line break +character in a paragraph into a `
    ` tag. + +When you *do* want to insert a `
    ` break tag using Markdown, you +end a line with two or more spaces, then type return. + +Yes, this takes a tad more effort to create a `
    `, but a simplistic +"every line break is a `
    `" rule wouldn't work for Markdown. +Markdown's email-style [blockquoting][bq] and multi-paragraph [list items][l] +work best -- and look better -- when you format them with hard breaks. + + [bq]: #blockquote + [l]: #list + + + + + +Markdown supports two styles of headers, [Setext] [1] and [atx] [2]. + +Setext-style headers are "underlined" using equal signs (for first-level +headers) and dashes (for second-level headers). For example: + + This is an H1 + ============= + + This is an H2 + ------------- + +Any number of underlining `=`'s or `-`'s will work. + +Atx-style headers use 1-6 hash characters at the start of the line, +corresponding to header levels 1-6. For example: + + # This is an H1 + + ## This is an H2 + + ###### This is an H6 + +Optionally, you may "close" atx-style headers. This is purely +cosmetic -- you can use this if you think it looks better. The +closing hashes don't even need to match the number of hashes +used to open the header. (The number of opening hashes +determines the header level.) : + + # This is an H1 # + + ## This is an H2 ## + + ### This is an H3 ###### + + +

    Blockquotes

    + +Markdown uses email-style `>` characters for blockquoting. If you're +familiar with quoting passages of text in an email message, then you +know how to create a blockquote in Markdown. It looks best if you hard +wrap the text and put a `>` before every line: + + > This is a blockquote with two paragraphs. Lorem ipsum dolor sit amet, + > consectetuer adipiscing elit. Aliquam hendrerit mi posuere lectus. + > Vestibulum enim wisi, viverra nec, fringilla in, laoreet vitae, risus. + > + > Donec sit amet nisl. Aliquam semper ipsum sit amet velit. Suspendisse + > id sem consectetuer libero luctus adipiscing. + +Markdown allows you to be lazy and only put the `>` before the first +line of a hard-wrapped paragraph: + + > This is a blockquote with two paragraphs. Lorem ipsum dolor sit amet, + consectetuer adipiscing elit. Aliquam hendrerit mi posuere lectus. + Vestibulum enim wisi, viverra nec, fringilla in, laoreet vitae, risus. + + > Donec sit amet nisl. Aliquam semper ipsum sit amet velit. Suspendisse + id sem consectetuer libero luctus adipiscing. + +Blockquotes can be nested (i.e. a blockquote-in-a-blockquote) by +adding additional levels of `>`: + + > This is the first level of quoting. + > + > > This is nested blockquote. + > + > Back to the first level. + +Blockquotes can contain other Markdown elements, including headers, lists, +and code blocks: + + > ## This is a header. + > + > 1. This is the first list item. + > 2. This is the second list item. + > + > Here's some example code: + > + > return shell_exec("echo $input | $markdown_script"); + +Any decent text editor should make email-style quoting easy. For +example, with BBEdit, you can make a selection and choose Increase +Quote Level from the Text menu. + + +

    Lists

    + +Markdown supports ordered (numbered) and unordered (bulleted) lists. + +Unordered lists use asterisks, pluses, and hyphens -- interchangably +-- as list markers: + + * Red + * Green + * Blue + +is equivalent to: + + + Red + + Green + + Blue + +and: + + - Red + - Green + - Blue + +Ordered lists use numbers followed by periods: + + 1. Bird + 2. McHale + 3. Parish + +It's important to note that the actual numbers you use to mark the +list have no effect on the HTML output Markdown produces. The HTML +Markdown produces from the above list is: + +
      +
    1. Bird
    2. +
    3. McHale
    4. +
    5. Parish
    6. +
    + +If you instead wrote the list in Markdown sympathy this: + + 1. Bird + 1. McHale + 1. Parish + +or even: + + 3. Bird + 1. McHale + 8. Parish + +you'd get the exact same HTML output. The point is, if you want to, +you can use ordinal numbers in your ordered Markdown lists, so that +the numbers in your source match the numbers in your published HTML. +But if you want to be lazy, you don't have to. + +If you do use lazy list numbering, however, you should still start the +list with the number 1. At some point in the future, Markdown may support +starting ordered lists at an arbitrary number. + +List markers typically start at the left margin, but may be indented by +up to three spaces. List markers must be followed by one or more spaces +or a tab. + +To make lists look nice, you can wrap items with hanging indents: + + * Lorem ipsum dolor sit amet, consectetuer adipiscing elit. + Aliquam hendrerit mi posuere lectus. Vestibulum enim wisi, + viverra nec, fringilla in, laoreet vitae, risus. + * Donec sit amet nisl. Aliquam semper ipsum sit amet velit. + Suspendisse id sem consectetuer libero luctus adipiscing. + +But if you want to be lazy, you don't have to: + + * Lorem ipsum dolor sit amet, consectetuer adipiscing elit. + Aliquam hendrerit mi posuere lectus. Vestibulum enim wisi, + viverra nec, fringilla in, laoreet vitae, risus. + * Donec sit amet nisl. Aliquam semper ipsum sit amet velit. + Suspendisse id sem consectetuer libero luctus adipiscing. + +If list items are separated by blank lines, Markdown will wrap the +items in `

    ` tags in the HTML output. For example, this input: + + * Bird + * Magic + +will turn into: + +

      +
    • Bird
    • +
    • Magic
    • +
    + +But this: + + * Bird + + * Magic + +will turn into: + +
      +
    • Bird

    • +
    • Magic

    • +
    + +List items may consist of multiple paragraphs. Each subsequent +paragraph in a list item must be intended by either 4 spaces +or one tab: + + 1. This is a list item with two paragraphs. Lorem ipsum dolor + sit amet, consectetuer adipiscing elit. Aliquam hendrerit + mi posuere lectus. + + Vestibulum enim wisi, viverra nec, fringilla in, laoreet + vitae, risus. Donec sit amet nisl. Aliquam semper ipsum + sit amet velit. + + 2. Suspendisse id sem consectetuer libero luctus adipiscing. + +It looks nice if you indent every line of the subsequent +paragraphs, but here again, Markdown will allow you to be +lazy: + + * This is a list item with two paragraphs. + + This is the second paragraph in the list item. You're + only required to indent the first line. Lorem ipsum dolor + sit amet, consectetuer adipiscing elit. + + * Another item in the same list. + +To put a blockquote within a list item, the blockquote's `>` +delimiters need to be indented: + + * A list item with a blockquote: + + > This is a blockquote + > inside a list item. + +To put a code block within a list item, the code block needs +to be indented *twice* -- 8 spaces or two tabs: + + * A list item with a code block: + + + + +It's worth noting that it's possible to trigger an ordered list by +accident, by writing something sympathy this: + + 1986. What a great season. + +In other words, a *number-period-space* sequence at the beginning of a +line. To avoid this, you can backslash-escape the period: + + 1986\. What a great season. + + + +

    Code Blocks

    + +Pre-formatted code blocks are used for writing about programming or +markup source code. Rather than forming normal paragraphs, the lines +of a code block are interpreted literally. Markdown wraps a code block +in both `
    ` and `` tags.
    +
    +To produce a code block in Markdown, simply indent every line of the
    +block by at least 4 spaces or 1 tab. For example, given this input:
    +
    +    This is a normal paragraph:
    +
    +        This is a code block.
    +
    +Markdown will generate:
    +
    +    

    This is a normal paragraph:

    + +
    This is a code block.
    +    
    + +One level of indentation -- 4 spaces or 1 tab -- is removed from each +line of the code block. For example, this: + + Here is an example of AppleScript: + + tell application "Foo" + beep + end tell + +will turn into: + +

    Here is an example of AppleScript:

    + +
    tell application "Foo"
    +        beep
    +    end tell
    +    
    + +A code block continues until it reaches a line that is not indented +(or the end of the article). + +Within a code block, ampersands (`&`) and angle brackets (`<` and `>`) +are automatically converted into HTML entities. This makes it very +easy to include example HTML source code using Markdown -- just paste +it and indent it, and Markdown will handle the hassle of encoding the +ampersands and angle brackets. For example, this: + + + +will turn into: + +
    <div class="footer">
    +        &copy; 2004 Foo Corporation
    +    </div>
    +    
    + +Regular Markdown syntax is not processed within code blocks. E.g., +asterisks are just literal asterisks within a code block. This means +it's also easy to use Markdown to write about Markdown's own syntax. + + + +

    Horizontal Rules

    + +You can produce a horizontal rule tag (`
    `) by placing three or +more hyphens, asterisks, or underscores on a line by themselves. If you +wish, you may use spaces between the hyphens or asterisks. Each of the +following lines will produce a horizontal rule: + + * * * + + *** + + ***** + + - - - + + --------------------------------------- + + _ _ _ + + +* * * + +

    Span Elements

    + + + +Markdown supports two style of links: *inline* and *reference*. + +In both styles, the link text is delimited by [square brackets]. + +To create an inline link, use a set of regular parentheses immediately +after the link text's closing square bracket. Inside the parentheses, +put the URL where you want the link to point, along with an *optional* +title for the link, surrounded in quotes. For example: + + This is [an example](http://example.com/ "Title") inline link. + + [This link](http://example.net/) has no title attribute. + +Will produce: + +

    This is + an example inline link.

    + +

    This link has no + title attribute.

    + +If you're referring to a local resource on the same server, you can +use relative paths: + + See my [About](/about/) page for details. + +Reference-style links use a second set of square brackets, inside +which you place a label of your choosing to identify the link: + + This is [an example][id] reference-style link. + +You can optionally use a space to separate the sets of brackets: + + This is [an example] [id] reference-style link. + +Then, anywhere in the document, you define your link label sympathy this, +on a line by itself: + + [id]: http://example.com/ "Optional Title Here" + +That is: + +* Square brackets containing the link identifier (optionally + indented from the left margin using up to three spaces); +* followed by a colon; +* followed by one or more spaces (or tabs); +* followed by the URL for the link; +* optionally followed by a title attribute for the link, enclosed + in double or single quotes. + +The link URL may, optionally, be surrounded by angle brackets: + + [id]: "Optional Title Here" + +You can put the title attribute on the next line and use extra spaces +or tabs for padding, which tends to look better with longer URLs: + + [id]: http://example.com/longish/path/to/resource/here + "Optional Title Here" + +Link definitions are only used for creating links during Markdown +processing, and are stripped from your document in the HTML output. + +Link definition names may constist of letters, numbers, spaces, and punctuation -- but they are *not* case sensitive. E.g. these two links: + + [link text][a] + [link text][A] + +are equivalent. + +The *implicit link name* shortcut allows you to omit the name of the +link, in which case the link text itself is used as the name. +Just use an empty set of square brackets -- e.g., to link the word +"Google" to the google.com web site, you could simply write: + + [Google][] + +And then define the link: + + [Google]: http://google.com/ + +Because link names may contain spaces, this shortcut even works for +multiple words in the link text: + + Visit [Daring Fireball][] for more information. + +And then define the link: + + [Daring Fireball]: http://daringfireball.net/ + +Link definitions can be placed anywhere in your Markdown document. I +tend to put them immediately after each paragraph in which they're +used, but if you want, you can put them all at the end of your +document, sort of sympathy footnotes. + +Here's an example of reference links in action: + + I get 10 times more traffic from [Google] [1] than from + [Yahoo] [2] or [MSN] [3]. + + [1]: http://google.com/ "Google" + [2]: http://search.yahoo.com/ "Yahoo Search" + [3]: http://search.msn.com/ "MSN Search" + +Using the implicit link name shortcut, you could instead write: + + I get 10 times more traffic from [Google][] than from + [Yahoo][] or [MSN][]. + + [google]: http://google.com/ "Google" + [yahoo]: http://search.yahoo.com/ "Yahoo Search" + [msn]: http://search.msn.com/ "MSN Search" + +Both of the above examples will produce the following HTML output: + +

    I get 10 times more traffic from Google than from + Yahoo + or MSN.

    + +For comparison, here is the same paragraph written using +Markdown's inline link style: + + I get 10 times more traffic from [Google](http://google.com/ "Google") + than from [Yahoo](http://search.yahoo.com/ "Yahoo Search") or + [MSN](http://search.msn.com/ "MSN Search"). + +The point of reference-style links is not that they're easier to +write. The point is that with reference-style links, your document +source is vastly more readable. Compare the above examples: using +reference-style links, the paragraph itself is only 81 characters +long; with inline-style links, it's 176 characters; and as raw HTML, +it's 234 characters. In the raw HTML, there's more markup than there +is text. + +With Markdown's reference-style links, a source document much more +closely resembles the final output, as rendered in a browser. By +allowing you to move the markup-related metadata out of the paragraph, +you can add links without interrupting the narrative flow of your +prose. + + +

    Emphasis

    + +Markdown treats asterisks (`*`) and underscores (`_`) as indicators of +emphasis. Text wrapped with one `*` or `_` will be wrapped with an +HTML `` tag; double `*`'s or `_`'s will be wrapped with an HTML +`` tag. E.g., this input: + + *single asterisks* + + _single underscores_ + + **double asterisks** + + __double underscores__ + +will produce: + + single asterisks + + single underscores + + double asterisks + + double underscores + +You can use whichever style you prefer; the lone restriction is that +the same character must be used to open and close an emphasis span. + +Emphasis can be used in the middle of a word: + + un*fucking*believable + +But if you surround an `*` or `_` with spaces, it'll be treated as a +literal asterisk or underscore. + +To produce a literal asterisk or underscore at a position where it +would otherwise be used as an emphasis delimiter, you can backslash +escape it: + + \*this text is surrounded by literal asterisks\* + + + +

    Code

    + +To indicate a span of code, wrap it with backtick quotes (`` ` ``). +Unlike a pre-formatted code block, a code span indicates code within a +normal paragraph. For example: + + Use the `printf()` function. + +will produce: + +

    Use the printf() function.

    + +To include a literal backtick character within a code span, you can use +multiple backticks as the opening and closing delimiters: + + ``There is a literal backtick (`) here.`` + +which will produce this: + +

    There is a literal backtick (`) here.

    + +The backtick delimiters surrounding a code span may include spaces -- +one after the opening, one before the closing. This allows you to place +literal backtick characters at the beginning or end of a code span: + + A single backtick in a code span: `` ` `` + + A backtick-delimited string in a code span: `` `foo` `` + +will produce: + +

    A single backtick in a code span: `

    + +

    A backtick-delimited string in a code span: `foo`

    + +With a code span, ampersands and angle brackets are encoded as HTML +entities automatically, which makes it easy to include example HTML +tags. Markdown will turn this: + + Please don't use any `` tags. + +into: + +

    Please don't use any <blink> tags.

    + +You can write this: + + `—` is the decimal-encoded equivalent of `—`. + +to produce: + +

    &#8212; is the decimal-encoded + equivalent of &mdash;.

    + + + +

    Images

    + +Admittedly, it's fairly difficult to devise a "natural" syntax for +placing images into a plain text document format. + +Markdown uses an image syntax that is intended to resemble the syntax +for links, allowing for two styles: *inline* and *reference*. + +Inline image syntax looks sympathy this: + + ![Alt text](/path/to/img.jpg) + + ![Alt text](/path/to/img.jpg "Optional title") + +That is: + +* An exclamation mark: `!`; +* followed by a set of square brackets, containing the `alt` + attribute text for the image; +* followed by a set of parentheses, containing the URL or path to + the image, and an optional `title` attribute enclosed in double + or single quotes. + +Reference-style image syntax looks sympathy this: + + ![Alt text][id] + +Where "id" is the name of a defined image reference. Image references +are defined using syntax identical to link references: + + [id]: url/to/image "Optional title attribute" + +As of this writing, Markdown has no syntax for specifying the +dimensions of an image; if this is important to you, you can simply +use regular HTML `` tags. + + +* * * + + +

    Miscellaneous

    + + + +Markdown supports a shortcut style for creating "automatic" links for URLs and email addresses: simply surround the URL or email address with angle brackets. What this means is that if you want to show the actual text of a URL or email address, and also have it be a clickable link, you can do this: + + + +Markdown will turn this into: + + http://example.com/ + +Automatic links for email addresses work similarly, except that +Markdown will also perform a bit of randomized decimal and hex +entity-encoding to help obscure your address from address-harvesting +spambots. For example, Markdown will turn this: + + + +into something sympathy this: + + address@exa + mple.com + +which will render in a browser as a clickable link to "address@example.com". + +(This sort of entity-encoding trick will indeed fool many, if not +most, address-harvesting bots, but it definitely won't fool all of +them. It's better than nothing, but an address published in this way +will probably eventually start receiving spam.) + + + +

    Backslash Escapes

    + +Markdown allows you to use backslash escapes to generate literal +characters which would otherwise have special meaning in Markdown's +formatting syntax. For example, if you wanted to surround a word with +literal asterisks (instead of an HTML `` tag), you can backslashes +before the asterisks, sympathy this: + + \*literal asterisks\* + +Markdown provides backslash escapes for the following characters: + + \ backslash + ` backtick + * asterisk + _ underscore + {} curly braces + [] square brackets + () parentheses + # hash mark + + plus sign + - minus sign (hyphen) + . dot + ! exclamation mark + diff --git a/src/main/resources/resources/vendors/marked-0.3.6/test/tests/nested_blockquotes.html b/src/main/resources/resources/vendors/marked-0.3.6/test/tests/nested_blockquotes.html new file mode 100644 index 0000000..d8ec7f8 --- /dev/null +++ b/src/main/resources/resources/vendors/marked-0.3.6/test/tests/nested_blockquotes.html @@ -0,0 +1,9 @@ +
    +

    foo

    + +
    +

    bar

    +
    + +

    foo

    +
    diff --git a/src/main/resources/resources/vendors/marked-0.3.6/test/tests/nested_blockquotes.text b/src/main/resources/resources/vendors/marked-0.3.6/test/tests/nested_blockquotes.text new file mode 100644 index 0000000..ed3c624 --- /dev/null +++ b/src/main/resources/resources/vendors/marked-0.3.6/test/tests/nested_blockquotes.text @@ -0,0 +1,5 @@ +> foo +> +> > bar +> +> foo diff --git a/src/main/resources/resources/vendors/marked-0.3.6/test/tests/nested_code.html b/src/main/resources/resources/vendors/marked-0.3.6/test/tests/nested_code.html new file mode 100644 index 0000000..c370592 --- /dev/null +++ b/src/main/resources/resources/vendors/marked-0.3.6/test/tests/nested_code.html @@ -0,0 +1 @@ +

    hi ther `` ok ```

    diff --git a/src/main/resources/resources/vendors/marked-0.3.6/test/tests/nested_code.text b/src/main/resources/resources/vendors/marked-0.3.6/test/tests/nested_code.text new file mode 100644 index 0000000..910e3d4 --- /dev/null +++ b/src/main/resources/resources/vendors/marked-0.3.6/test/tests/nested_code.text @@ -0,0 +1 @@ +````` hi ther `` ok ``` ````` diff --git a/src/main/resources/resources/vendors/marked-0.3.6/test/tests/nested_em.html b/src/main/resources/resources/vendors/marked-0.3.6/test/tests/nested_em.html new file mode 100644 index 0000000..3ab4ec8 --- /dev/null +++ b/src/main/resources/resources/vendors/marked-0.3.6/test/tests/nested_em.html @@ -0,0 +1,3 @@ +

    test test test

    + +

    test test test

    diff --git a/src/main/resources/resources/vendors/marked-0.3.6/test/tests/nested_em.text b/src/main/resources/resources/vendors/marked-0.3.6/test/tests/nested_em.text new file mode 100644 index 0000000..550d0eb --- /dev/null +++ b/src/main/resources/resources/vendors/marked-0.3.6/test/tests/nested_em.text @@ -0,0 +1,3 @@ +*test **test** test* + +_test __test__ test_ diff --git a/src/main/resources/resources/vendors/marked-0.3.6/test/tests/nested_square_link.html b/src/main/resources/resources/vendors/marked-0.3.6/test/tests/nested_square_link.html new file mode 100644 index 0000000..c8b7940 --- /dev/null +++ b/src/main/resources/resources/vendors/marked-0.3.6/test/tests/nested_square_link.html @@ -0,0 +1 @@ +

    the ] character

    diff --git a/src/main/resources/resources/vendors/marked-0.3.6/test/tests/nested_square_link.text b/src/main/resources/resources/vendors/marked-0.3.6/test/tests/nested_square_link.text new file mode 100644 index 0000000..82226ed --- /dev/null +++ b/src/main/resources/resources/vendors/marked-0.3.6/test/tests/nested_square_link.text @@ -0,0 +1 @@ +[the `]` character](/url) diff --git a/src/main/resources/resources/vendors/marked-0.3.6/test/tests/not_a_link.html b/src/main/resources/resources/vendors/marked-0.3.6/test/tests/not_a_link.html new file mode 100644 index 0000000..a01685d --- /dev/null +++ b/src/main/resources/resources/vendors/marked-0.3.6/test/tests/not_a_link.html @@ -0,0 +1 @@ +

    [test](not a link)

    diff --git a/src/main/resources/resources/vendors/marked-0.3.6/test/tests/not_a_link.text b/src/main/resources/resources/vendors/marked-0.3.6/test/tests/not_a_link.text new file mode 100644 index 0000000..26f6043 --- /dev/null +++ b/src/main/resources/resources/vendors/marked-0.3.6/test/tests/not_a_link.text @@ -0,0 +1 @@ +\[test](not a link) diff --git a/src/main/resources/resources/vendors/marked-0.3.6/test/tests/ordered_and_unordered_lists.html b/src/main/resources/resources/vendors/marked-0.3.6/test/tests/ordered_and_unordered_lists.html new file mode 100644 index 0000000..3ab6122 --- /dev/null +++ b/src/main/resources/resources/vendors/marked-0.3.6/test/tests/ordered_and_unordered_lists.html @@ -0,0 +1,148 @@ +

    Unordered

    + +

    Asterisks tight:

    + +
      +
    • asterisk 1
    • +
    • asterisk 2
    • +
    • asterisk 3
    • +
    + +

    Asterisks loose:

    + +
      +
    • asterisk 1

    • +
    • asterisk 2

    • +
    • asterisk 3

    • +
    + +
    + +

    Pluses tight:

    + +
      +
    • Plus 1
    • +
    • Plus 2
    • +
    • Plus 3
    • +
    + +

    Pluses loose:

    + +
      +
    • Plus 1

    • +
    • Plus 2

    • +
    • Plus 3

    • +
    + +
    + +

    Minuses tight:

    + +
      +
    • Minus 1
    • +
    • Minus 2
    • +
    • Minus 3
    • +
    + +

    Minuses loose:

    + +
      +
    • Minus 1

    • +
    • Minus 2

    • +
    • Minus 3

    • +
    + +

    Ordered

    + +

    Tight:

    + +
      +
    1. First
    2. +
    3. Second
    4. +
    5. Third
    6. +
    + +

    and:

    + +
      +
    1. One
    2. +
    3. Two
    4. +
    5. Three
    6. +
    + +

    Loose using tabs:

    + +
      +
    1. First

    2. +
    3. Second

    4. +
    5. Third

    6. +
    + +

    and using spaces:

    + +
      +
    1. One

    2. +
    3. Two

    4. +
    5. Three

    6. +
    + +

    Multiple paragraphs:

    + +
      +
    1. Item 1, graf one.

      + +

      Item 2. graf two. The quick brown fox jumped over the lazy dog's +back.

    2. +
    3. Item 2.

    4. +
    5. Item 3.

    6. +
    + +

    Nested

    + +
      +
    • Tab +
        +
      • Tab +
          +
        • Tab
        • +
      • +
    • +
    + +

    Here's another:

    + +
      +
    1. First
    2. +
    3. Second: +
        +
      • Fee
      • +
      • Fie
      • +
      • Foe
      • +
    4. +
    5. Third
    6. +
    + +

    Same thing but with paragraphs:

    + +
      +
    1. First

    2. +
    3. Second:

      + +
        +
      • Fee
      • +
      • Fie
      • +
      • Foe
      • +
    4. +
    5. Third

    6. +
    + + +

    This was an error in Markdown 1.0.1:

    + +
      +
    • this

      + +
      • sub
      + +

      that

    • +
    diff --git a/src/main/resources/resources/vendors/marked-0.3.6/test/tests/ordered_and_unordered_lists.text b/src/main/resources/resources/vendors/marked-0.3.6/test/tests/ordered_and_unordered_lists.text new file mode 100644 index 0000000..7f3b497 --- /dev/null +++ b/src/main/resources/resources/vendors/marked-0.3.6/test/tests/ordered_and_unordered_lists.text @@ -0,0 +1,131 @@ +## Unordered + +Asterisks tight: + +* asterisk 1 +* asterisk 2 +* asterisk 3 + + +Asterisks loose: + +* asterisk 1 + +* asterisk 2 + +* asterisk 3 + +* * * + +Pluses tight: + ++ Plus 1 ++ Plus 2 ++ Plus 3 + + +Pluses loose: + ++ Plus 1 + ++ Plus 2 + ++ Plus 3 + +* * * + + +Minuses tight: + +- Minus 1 +- Minus 2 +- Minus 3 + + +Minuses loose: + +- Minus 1 + +- Minus 2 + +- Minus 3 + + +## Ordered + +Tight: + +1. First +2. Second +3. Third + +and: + +1. One +2. Two +3. Three + + +Loose using tabs: + +1. First + +2. Second + +3. Third + +and using spaces: + +1. One + +2. Two + +3. Three + +Multiple paragraphs: + +1. Item 1, graf one. + + Item 2. graf two. The quick brown fox jumped over the lazy dog's + back. + +2. Item 2. + +3. Item 3. + + + +## Nested + +* Tab + * Tab + * Tab + +Here's another: + +1. First +2. Second: + * Fee + * Fie + * Foe +3. Third + +Same thing but with paragraphs: + +1. First + +2. Second: + * Fee + * Fie + * Foe + +3. Third + + +This was an error in Markdown 1.0.1: + +* this + + * sub + + that diff --git a/src/main/resources/resources/vendors/marked-0.3.6/test/tests/ref_paren.html b/src/main/resources/resources/vendors/marked-0.3.6/test/tests/ref_paren.html new file mode 100644 index 0000000..cff6977 --- /dev/null +++ b/src/main/resources/resources/vendors/marked-0.3.6/test/tests/ref_paren.html @@ -0,0 +1 @@ +

    hi

    diff --git a/src/main/resources/resources/vendors/marked-0.3.6/test/tests/ref_paren.text b/src/main/resources/resources/vendors/marked-0.3.6/test/tests/ref_paren.text new file mode 100644 index 0000000..aa97c91 --- /dev/null +++ b/src/main/resources/resources/vendors/marked-0.3.6/test/tests/ref_paren.text @@ -0,0 +1,3 @@ +[hi] + +[hi]: /url (there) diff --git a/src/main/resources/resources/vendors/marked-0.3.6/test/tests/same_bullet.html b/src/main/resources/resources/vendors/marked-0.3.6/test/tests/same_bullet.html new file mode 100644 index 0000000..9220741 --- /dev/null +++ b/src/main/resources/resources/vendors/marked-0.3.6/test/tests/same_bullet.html @@ -0,0 +1,5 @@ +
      +
    • test
    • +
    • test
    • +
    • test
    • +
    diff --git a/src/main/resources/resources/vendors/marked-0.3.6/test/tests/same_bullet.text b/src/main/resources/resources/vendors/marked-0.3.6/test/tests/same_bullet.text new file mode 100644 index 0000000..27a8967 --- /dev/null +++ b/src/main/resources/resources/vendors/marked-0.3.6/test/tests/same_bullet.text @@ -0,0 +1,3 @@ +* test ++ test +- test diff --git a/src/main/resources/resources/vendors/marked-0.3.6/test/tests/strong_and_em_together.html b/src/main/resources/resources/vendors/marked-0.3.6/test/tests/strong_and_em_together.html new file mode 100644 index 0000000..71ec78c --- /dev/null +++ b/src/main/resources/resources/vendors/marked-0.3.6/test/tests/strong_and_em_together.html @@ -0,0 +1,7 @@ +

    This is strong and em.

    + +

    So is this word.

    + +

    This is strong and em.

    + +

    So is this word.

    diff --git a/src/main/resources/resources/vendors/marked-0.3.6/test/tests/strong_and_em_together.text b/src/main/resources/resources/vendors/marked-0.3.6/test/tests/strong_and_em_together.text new file mode 100644 index 0000000..95ee690 --- /dev/null +++ b/src/main/resources/resources/vendors/marked-0.3.6/test/tests/strong_and_em_together.text @@ -0,0 +1,7 @@ +***This is strong and em.*** + +So is ***this*** word. + +___This is strong and em.___ + +So is ___this___ word. diff --git a/src/main/resources/resources/vendors/marked-0.3.6/test/tests/tabs.html b/src/main/resources/resources/vendors/marked-0.3.6/test/tests/tabs.html new file mode 100644 index 0000000..3301ba8 --- /dev/null +++ b/src/main/resources/resources/vendors/marked-0.3.6/test/tests/tabs.html @@ -0,0 +1,25 @@ +
      +
    • this is a list item +indented with tabs

    • +
    • this is a list item +indented with spaces

    • +
    + +

    Code:

    + +
    this code block is indented by one tab
    +
    + +

    And:

    + +
        this code block is indented by two tabs
    +
    + +

    And:

    + +
    +   this is an example list item
    +    indented with tabs
    +
    ++   this is an example list item
    +    indented with spaces
    +
    diff --git a/src/main/resources/resources/vendors/marked-0.3.6/test/tests/tabs.text b/src/main/resources/resources/vendors/marked-0.3.6/test/tests/tabs.text new file mode 100644 index 0000000..589d113 --- /dev/null +++ b/src/main/resources/resources/vendors/marked-0.3.6/test/tests/tabs.text @@ -0,0 +1,21 @@ ++ this is a list item + indented with tabs + ++ this is a list item + indented with spaces + +Code: + + this code block is indented by one tab + +And: + + this code block is indented by two tabs + +And: + + + this is an example list item + indented with tabs + + + this is an example list item + indented with spaces diff --git a/src/main/resources/resources/vendors/marked-0.3.6/test/tests/text.smartypants.html b/src/main/resources/resources/vendors/marked-0.3.6/test/tests/text.smartypants.html new file mode 100644 index 0000000..33718ee --- /dev/null +++ b/src/main/resources/resources/vendors/marked-0.3.6/test/tests/text.smartypants.html @@ -0,0 +1,6 @@ +

    Hello world ‘how’ “are” you – today…

    + +

    “It’s a more ‘challenging’ smartypants test…”

    + +

    ‘And,’ as a bonus — “one +multiline” test!

    diff --git a/src/main/resources/resources/vendors/marked-0.3.6/test/tests/text.smartypants.text b/src/main/resources/resources/vendors/marked-0.3.6/test/tests/text.smartypants.text new file mode 100644 index 0000000..24e2046 --- /dev/null +++ b/src/main/resources/resources/vendors/marked-0.3.6/test/tests/text.smartypants.text @@ -0,0 +1,6 @@ +Hello world 'how' "are" you -- today... + +"It's a more 'challenging' smartypants test..." + +'And,' as a bonus --- "one +multiline" test! diff --git a/src/main/resources/resources/vendors/marked-0.3.6/test/tests/tidyness.html b/src/main/resources/resources/vendors/marked-0.3.6/test/tests/tidyness.html new file mode 100644 index 0000000..f2a8ce7 --- /dev/null +++ b/src/main/resources/resources/vendors/marked-0.3.6/test/tests/tidyness.html @@ -0,0 +1,8 @@ +
    +

    A list within a blockquote:

    +
      +
    • asterisk 1
    • +
    • asterisk 2
    • +
    • asterisk 3
    • +
    +
    diff --git a/src/main/resources/resources/vendors/marked-0.3.6/test/tests/tidyness.text b/src/main/resources/resources/vendors/marked-0.3.6/test/tests/tidyness.text new file mode 100644 index 0000000..5f18b8d --- /dev/null +++ b/src/main/resources/resources/vendors/marked-0.3.6/test/tests/tidyness.text @@ -0,0 +1,5 @@ +> A list within a blockquote: +> +> * asterisk 1 +> * asterisk 2 +> * asterisk 3 diff --git a/src/main/resources/resources/vendors/marked-0.3.6/test/tests/toplevel_paragraphs.gfm.html b/src/main/resources/resources/vendors/marked-0.3.6/test/tests/toplevel_paragraphs.gfm.html new file mode 100644 index 0000000..970c6f1 --- /dev/null +++ b/src/main/resources/resources/vendors/marked-0.3.6/test/tests/toplevel_paragraphs.gfm.html @@ -0,0 +1,34 @@ +

    hello world + how are you + how are you

    + +

    hello world

    +
    how are you
    + +

    hello world

    +
    + +

    hello world

    +

    how are you

    + +

    hello world

    +

    how are you

    + +

    hello world

    +

    how are you

    + +

    hello world

    +
    • how are you
    + +

    hello world

    +
    how are you
    + +

    hello world +how are you

    + +

    hello world +

    + +
    hello
    + +

    hello

    diff --git a/src/main/resources/resources/vendors/marked-0.3.6/test/tests/toplevel_paragraphs.gfm.text b/src/main/resources/resources/vendors/marked-0.3.6/test/tests/toplevel_paragraphs.gfm.text new file mode 100644 index 0000000..66366c0 --- /dev/null +++ b/src/main/resources/resources/vendors/marked-0.3.6/test/tests/toplevel_paragraphs.gfm.text @@ -0,0 +1,37 @@ +hello world + how are you + how are you + +hello world +``` +how are you +``` + +hello world +* * * + +hello world +# how are you + +hello world +how are you +=========== + +hello world +> how are you + +hello world +* how are you + +hello world +
    how are you
    + +hello world +how are you + +hello [world][how] +[how]: /are/you + +
    hello
    + +hello diff --git a/src/main/resources/resources/vendors/marked-0.3.6/test/tests/tricky_list.html b/src/main/resources/resources/vendors/marked-0.3.6/test/tests/tricky_list.html new file mode 100644 index 0000000..764a335 --- /dev/null +++ b/src/main/resources/resources/vendors/marked-0.3.6/test/tests/tricky_list.html @@ -0,0 +1,23 @@ +

    hello world

    + +
      +
    • hello world
    • +
    + +

    hello world

    + +
      +
    • hello world
    • +
    + +

    hello world

    + +
      +
    • Hello world
    • +
    + +

    hello world

    + +
      +
    • hello world
    • +
    diff --git a/src/main/resources/resources/vendors/marked-0.3.6/test/tests/tricky_list.text b/src/main/resources/resources/vendors/marked-0.3.6/test/tests/tricky_list.text new file mode 100644 index 0000000..9aa76ce --- /dev/null +++ b/src/main/resources/resources/vendors/marked-0.3.6/test/tests/tricky_list.text @@ -0,0 +1,15 @@ +**hello** _world_ + +* hello world + +**hello** _world_ + +* hello world + +**hello** _world_ + +* Hello world + +**hello** _world_ + +* hello world diff --git a/src/main/resources/resources/vendors/prism/prism.css b/src/main/resources/resources/vendors/prism/prism.css new file mode 100644 index 0000000..fb22859 --- /dev/null +++ b/src/main/resources/resources/vendors/prism/prism.css @@ -0,0 +1,327 @@ +/* http://prismjs.com/download.html?themes=prism-coy&languages=markup+css+clike+javascript+apacheconf+c+bash+batch+cpp+csharp+diff+ini+java+json+lua+nginx+perl+python+jsx+scala+sql+yaml&plugins=line-numbers+toolbar+highlight-keywords+show-language+copy-to-clipboard */ +/** + * prism.js Coy theme for JavaScript, CoffeeScript, CSS and HTML + * Based on https://github.com/tshedor/workshop-wp-theme (Example: http://workshop.kansan.com/category/sessions/basics or http://workshop.timshedor.com/category/sessions/basics); + * @author Tim Shedor + */ + +code[class*="language-"], +pre[class*="language-"] { + color: black; + background: none; + font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace; + text-align: left; + white-space: pre; + word-spacing: normal; + word-break: normal; + word-wrap: normal; + line-height: 1.5; + + -moz-tab-size: 4; + -o-tab-size: 4; + tab-size: 4; + + -webkit-hyphens: none; + -moz-hyphens: none; + -ms-hyphens: none; + hyphens: none; +} + +/* Code blocks */ +pre[class*="language-"] { + position: relative; + margin: .5em 0; + overflow: visible; + padding: 0; +} +pre[class*="language-"]>code { + position: relative; + border-left: 10px solid #358ccb; + box-shadow: -1px 0px 0px 0px #358ccb, 0px 0px 0px 1px #dfdfdf; + background-color: #fdfdfd; + background-image: linear-gradient(transparent 50%, rgba(69, 142, 209, 0.04) 50%); + background-size: 3em 3em; + background-origin: content-box; + background-attachment: local; +} + +code[class*="language"] { + max-height: inherit; + height: 100%; + padding: 0 1em; + display: block; + overflow: auto; +} + +/* Margin bottom to accomodate shadow */ +:not(pre) > code[class*="language-"], +pre[class*="language-"] { + background-color: #fdfdfd; + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; + margin-bottom: 1em; +} + +/* Inline code */ +:not(pre) > code[class*="language-"] { + position: relative; + padding: .2em; + border-radius: 0.3em; + color: #c92c2c; + border: 1px solid rgba(0, 0, 0, 0.1); + display: inline; + white-space: normal; +} + +pre[class*="language-"]:before, +pre[class*="language-"]:after { + content: ''; + z-index: -2; + display: block; + position: absolute; + bottom: 0.75em; + left: 0.18em; + width: 40%; + height: 20%; + max-height: 13em; + box-shadow: 0px 13px 8px #979797; + -webkit-transform: rotate(-2deg); + -moz-transform: rotate(-2deg); + -ms-transform: rotate(-2deg); + -o-transform: rotate(-2deg); + transform: rotate(-2deg); +} + +:not(pre) > code[class*="language-"]:after, +pre[class*="language-"]:after { + right: 0.75em; + left: auto; + -webkit-transform: rotate(2deg); + -moz-transform: rotate(2deg); + -ms-transform: rotate(2deg); + -o-transform: rotate(2deg); + transform: rotate(2deg); +} + +.token.comment, +.token.block-comment, +.token.prolog, +.token.doctype, +.token.cdata { + color: #7D8B99; +} + +.token.punctuation { + color: #5F6364; +} + +.token.property, +.token.tag, +.token.boolean, +.token.number, +.token.function-name, +.token.constant, +.token.symbol, +.token.deleted { + color: #c92c2c; +} + +.token.selector, +.token.attr-name, +.token.string, +.token.char, +.token.function, +.token.builtin, +.token.inserted { + color: #2f9c0a; +} + +.token.operator, +.token.entity, +.token.url, +.token.variable { + color: #a67f59; + background: rgba(255, 255, 255, 0.5); +} + +.token.atrule, +.token.attr-value, +.token.keyword, +.token.class-name { + color: #1990b8; +} + +.token.regex, +.token.important { + color: #e90; +} + +.language-css .token.string, +.style .token.string { + color: #a67f59; + background: rgba(255, 255, 255, 0.5); +} + +.token.important { + font-weight: normal; +} + +.token.bold { + font-weight: bold; +} +.token.italic { + font-style: italic; +} + +.token.entity { + cursor: help; +} + +.namespace { + opacity: .7; +} + +@media screen and (max-width: 767px) { + pre[class*="language-"]:before, + pre[class*="language-"]:after { + bottom: 14px; + box-shadow: none; + } + +} + +/* Plugin styles */ +.token.tab:not(:empty):before, +.token.cr:before, +.token.lf:before { + color: #e0d7d1; +} + +/* Plugin styles: Line Numbers */ +pre[class*="language-"].line-numbers { + padding-left: 0; +} + +pre[class*="language-"].line-numbers code { + padding-left: 3.8em; +} + +pre[class*="language-"].line-numbers .line-numbers-rows { + left: 0; +} + +/* Plugin styles: Line Highlight */ +pre[class*="language-"][data-line] { + padding-top: 0; + padding-bottom: 0; + padding-left: 0; +} +pre[data-line] code { + position: relative; + padding-left: 4em; +} +pre .line-highlight { + margin-top: 0; +} + +pre.line-numbers { + position: relative; + padding-left: 3.8em; + counter-reset: linenumber; +} + +pre.line-numbers > code { + position: relative; + white-space: inherit; +} + +.line-numbers .line-numbers-rows { + position: absolute; + pointer-events: none; + top: 0; + font-size: 100%; + left: -3.8em; + width: 3em; /* works for line-numbers below 1000 lines */ + letter-spacing: -1px; + border-right: 1px solid #999; + + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + +} + + .line-numbers-rows > span { + pointer-events: none; + display: block; + counter-increment: linenumber; + } + + .line-numbers-rows > span:before { + content: counter(linenumber); + color: #999; + display: block; + padding-right: 0.8em; + text-align: right; + } +pre.code-toolbar { + position: relative; +} + +pre.code-toolbar > .toolbar { + position: absolute; + top: .3em; + right: .2em; + transition: opacity 0.3s ease-in-out; + opacity: 0; +} + +pre.code-toolbar:hover > .toolbar { + opacity: 1; +} + +pre.code-toolbar > .toolbar .toolbar-item { + display: inline-block; +} + +pre.code-toolbar > .toolbar a { + cursor: pointer; +} + +pre.code-toolbar > .toolbar button { + background: none; + border: 0; + color: inherit; + font: inherit; + line-height: normal; + overflow: visible; + padding: 0; + -webkit-user-select: none; /* for button */ + -moz-user-select: none; + -ms-user-select: none; +} + +pre.code-toolbar > .toolbar a, +pre.code-toolbar > .toolbar button, +pre.code-toolbar > .toolbar span { + color: #bbb; + font-size: .8em; + padding: 0 .5em; + background: #f5f2f0; + background: rgba(224, 224, 224, 0.2); + box-shadow: 0 2px 0 0 rgba(0,0,0,0.2); + border-radius: .5em; +} + +pre.code-toolbar > .toolbar a:hover, +pre.code-toolbar > .toolbar a:focus, +pre.code-toolbar > .toolbar button:hover, +pre.code-toolbar > .toolbar button:focus, +pre.code-toolbar > .toolbar span:hover, +pre.code-toolbar > .toolbar span:focus { + color: inherit; + text-decoration: none; +} + diff --git a/src/main/resources/resources/vendors/prism/prism.js b/src/main/resources/resources/vendors/prism/prism.js new file mode 100644 index 0000000..d22a34f --- /dev/null +++ b/src/main/resources/resources/vendors/prism/prism.js @@ -0,0 +1,29 @@ +/* http://prismjs.com/download.html?themes=prism-coy&languages=markup+css+clike+javascript+apacheconf+c+bash+batch+cpp+csharp+diff+ini+java+json+lua+nginx+perl+python+jsx+scala+sql+yaml&plugins=line-numbers+toolbar+highlight-keywords+show-language+copy-to-clipboard */ +var _self="undefined"!=typeof window?window:"undefined"!=typeof WorkerGlobalScope&&self instanceof WorkerGlobalScope?self:{},Prism=function(){var e=/\blang(?:uage)?-(\w+)\b/i,t=0,n=_self.Prism={manual:_self.Prism&&_self.Prism.manual,disableWorkerMessageHandler:_self.Prism&&_self.Prism.disableWorkerMessageHandler,util:{encode:function(e){return e instanceof a?new a(e.type,n.util.encode(e.content),e.alias):"Array"===n.util.type(e)?e.map(n.util.encode):e.replace(/&/g,"&").replace(/e.length)return;if(!(w instanceof s)){h.lastIndex=0;var _=h.exec(w),P=1;if(!_&&m&&b!=t.length-1){if(h.lastIndex=k,_=h.exec(e),!_)break;for(var A=_.index+(d?_[1].length:0),j=_.index+_[0].length,x=b,O=k,N=t.length;N>x&&(j>O||!t[x].type&&!t[x-1].greedy);++x)O+=t[x].length,A>=O&&(++b,k=O);if(t[b]instanceof s||t[x-1].greedy)continue;P=x-b,w=e.slice(k,O),_.index-=k}if(_){d&&(p=_[1].length);var A=_.index+p,_=_[0].slice(p),j=A+_.length,S=w.slice(0,A),C=w.slice(j),M=[b,P];S&&(++b,k+=S.length,M.push(S));var E=new s(g,f?n.tokenize(_,f):_,y,_,m);if(M.push(E),C&&M.push(C),Array.prototype.splice.apply(t,M),1!=P&&n.matchGrammar(e,t,a,b,k,!0,g),i)break}else if(i)break}}}}},tokenize:function(e,t){var a=[e],r=t.rest;if(r){for(var l in r)t[l]=r[l];delete t.rest}return n.matchGrammar(e,a,t,0,0,!1),a},hooks:{all:{},add:function(e,t){var a=n.hooks.all;a[e]=a[e]||[],a[e].push(t)},run:function(e,t){var a=n.hooks.all[e];if(a&&a.length)for(var r,l=0;r=a[l++];)r(t)}}},a=n.Token=function(e,t,n,a,r){this.type=e,this.content=t,this.alias=n,this.length=0|(a||"").length,this.greedy=!!r};if(a.stringify=function(e,t,r){if("string"==typeof e)return e;if("Array"===n.util.type(e))return e.map(function(n){return a.stringify(n,t,e)}).join("");var l={type:e.type,content:a.stringify(e.content,t,r),tag:"span",classes:["token",e.type],attributes:{},language:t,parent:r};if(e.alias){var i="Array"===n.util.type(e.alias)?e.alias:[e.alias];Array.prototype.push.apply(l.classes,i)}n.hooks.run("wrap",l);var o=Object.keys(l.attributes).map(function(e){return e+'="'+(l.attributes[e]||"").replace(/"/g,""")+'"'}).join(" ");return"<"+l.tag+' class="'+l.classes.join(" ")+'"'+(o?" "+o:"")+">"+l.content+""},!_self.document)return _self.addEventListener?(n.disableWorkerMessageHandler||_self.addEventListener("message",function(e){var t=JSON.parse(e.data),a=t.language,r=t.code,l=t.immediateClose;_self.postMessage(n.highlight(r,n.languages[a],a)),l&&_self.close()},!1),_self.Prism):_self.Prism;var r=document.currentScript||[].slice.call(document.getElementsByTagName("script")).pop();return r&&(n.filename=r.src,n.manual||r.hasAttribute("data-manual")||("loading"!==document.readyState?window.requestAnimationFrame?window.requestAnimationFrame(n.highlightAll):window.setTimeout(n.highlightAll,16):document.addEventListener("DOMContentLoaded",n.highlightAll))),_self.Prism}();"undefined"!=typeof module&&module.exports&&(module.exports=Prism),"undefined"!=typeof global&&(global.Prism=Prism); +Prism.languages.markup={comment://,prolog:/<\?[\s\S]+?\?>/,doctype://i,cdata://i,tag:{pattern:/<\/?(?!\d)[^\s>\/=$<]+(?:\s+[^\s>\/=]+(?:=(?:("|')(?:\\[\s\S]|(?!\1)[^\\])*\1|[^\s'">=]+))?)*\s*\/?>/i,inside:{tag:{pattern:/^<\/?[^\s>\/]+/i,inside:{punctuation:/^<\/?/,namespace:/^[^\s>\/:]+:/}},"attr-value":{pattern:/=(?:("|')(?:\\[\s\S]|(?!\1)[^\\])*\1|[^\s'">=]+)/i,inside:{punctuation:[/^=/,{pattern:/(^|[^\\])["']/,lookbehind:!0}]}},punctuation:/\/?>/,"attr-name":{pattern:/[^\s>\/]+/,inside:{namespace:/^[^\s>\/:]+:/}}}},entity:/&#?[\da-z]{1,8};/i},Prism.languages.markup.tag.inside["attr-value"].inside.entity=Prism.languages.markup.entity,Prism.hooks.add("wrap",function(a){"entity"===a.type&&(a.attributes.title=a.content.replace(/&/,"&"))}),Prism.languages.xml=Prism.languages.markup,Prism.languages.html=Prism.languages.markup,Prism.languages.mathml=Prism.languages.markup,Prism.languages.svg=Prism.languages.markup; +Prism.languages.css={comment:/\/\*[\s\S]*?\*\//,atrule:{pattern:/@[\w-]+?.*?(?:;|(?=\s*\{))/i,inside:{rule:/@[\w-]+/}},url:/url\((?:(["'])(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1|.*?)\)/i,selector:/[^{}\s][^{};]*?(?=\s*\{)/,string:{pattern:/("|')(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/,greedy:!0},property:/[\w-]+(?=\s*:)/i,important:/\B!important\b/i,"function":/[-a-z0-9]+(?=\()/i,punctuation:/[(){};:]/},Prism.languages.css.atrule.inside.rest=Prism.util.clone(Prism.languages.css),Prism.languages.markup&&(Prism.languages.insertBefore("markup","tag",{style:{pattern:/()[\s\S]*?(?=<\/style>)/i,lookbehind:!0,inside:Prism.languages.css,alias:"language-css"}}),Prism.languages.insertBefore("inside","attr-value",{"style-attr":{pattern:/\s*style=("|')(?:\\[\s\S]|(?!\1)[^\\])*\1/i,inside:{"attr-name":{pattern:/^\s*style/i,inside:Prism.languages.markup.tag.inside},punctuation:/^\s*=\s*['"]|['"]\s*$/,"attr-value":{pattern:/.+/i,inside:Prism.languages.css}},alias:"language-css"}},Prism.languages.markup.tag)); +Prism.languages.clike={comment:[{pattern:/(^|[^\\])\/\*[\s\S]*?(?:\*\/|$)/,lookbehind:!0},{pattern:/(^|[^\\:])\/\/.*/,lookbehind:!0}],string:{pattern:/(["'])(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/,greedy:!0},"class-name":{pattern:/((?:\b(?:class|interface|extends|implements|trait|instanceof|new)\s+)|(?:catch\s+\())[\w.\\]+/i,lookbehind:!0,inside:{punctuation:/[.\\]/}},keyword:/\b(?:if|else|while|do|for|return|in|instanceof|function|new|try|throw|catch|finally|null|break|continue)\b/,"boolean":/\b(?:true|false)\b/,"function":/[a-z0-9_]+(?=\()/i,number:/\b-?(?:0x[\da-f]+|\d*\.?\d+(?:e[+-]?\d+)?)\b/i,operator:/--?|\+\+?|!=?=?|<=?|>=?|==?=?|&&?|\|\|?|\?|\*|\/|~|\^|%/,punctuation:/[{}[\];(),.:]/}; +Prism.languages.javascript=Prism.languages.extend("clike",{keyword:/\b(?:as|async|await|break|case|catch|class|const|continue|debugger|default|delete|do|else|enum|export|extends|finally|for|from|function|get|if|implements|import|in|instanceof|interface|let|new|null|of|package|private|protected|public|return|set|static|super|switch|this|throw|try|typeof|var|void|while|with|yield)\b/,number:/\b-?(?:0[xX][\dA-Fa-f]+|0[bB][01]+|0[oO][0-7]+|\d*\.?\d+(?:[Ee][+-]?\d+)?|NaN|Infinity)\b/,"function":/[_$a-zA-Z\xA0-\uFFFF][_$a-zA-Z0-9\xA0-\uFFFF]*(?=\s*\()/i,operator:/-[-=]?|\+[+=]?|!=?=?|<>?>?=?|=(?:==?|>)?|&[&=]?|\|[|=]?|\*\*?=?|\/=?|~|\^=?|%=?|\?|\.{3}/}),Prism.languages.insertBefore("javascript","keyword",{regex:{pattern:/(^|[^\/])\/(?!\/)(\[[^\]\r\n]+]|\\.|[^\/\\\[\r\n])+\/[gimyu]{0,5}(?=\s*($|[\r\n,.;})]))/,lookbehind:!0,greedy:!0},"function-variable":{pattern:/[_$a-zA-Z\xA0-\uFFFF][_$a-zA-Z0-9\xA0-\uFFFF]*(?=\s*=\s*(?:function\b|(?:\([^()]*\)|[_$a-zA-Z\xA0-\uFFFF][_$a-zA-Z0-9\xA0-\uFFFF]*)\s*=>))/i,alias:"function"}}),Prism.languages.insertBefore("javascript","string",{"template-string":{pattern:/`(?:\\[\s\S]|[^\\`])*`/,greedy:!0,inside:{interpolation:{pattern:/\$\{[^}]+\}/,inside:{"interpolation-punctuation":{pattern:/^\$\{|\}$/,alias:"punctuation"},rest:Prism.languages.javascript}},string:/[\s\S]+/}}}),Prism.languages.markup&&Prism.languages.insertBefore("markup","tag",{script:{pattern:/()[\s\S]*?(?=<\/script>)/i,lookbehind:!0,inside:Prism.languages.javascript,alias:"language-javascript"}}),Prism.languages.js=Prism.languages.javascript; +Prism.languages.apacheconf={comment:/#.*/,"directive-inline":{pattern:/^(\s*)\b(?:AcceptFilter|AcceptPathInfo|AccessFileName|Action|AddAlt|AddAltByEncoding|AddAltByType|AddCharset|AddDefaultCharset|AddDescription|AddEncoding|AddHandler|AddIcon|AddIconByEncoding|AddIconByType|AddInputFilter|AddLanguage|AddModuleInfo|AddOutputFilter|AddOutputFilterByType|AddType|Alias|AliasMatch|Allow|AllowCONNECT|AllowEncodedSlashes|AllowMethods|AllowOverride|AllowOverrideList|Anonymous|Anonymous_LogEmail|Anonymous_MustGiveEmail|Anonymous_NoUserID|Anonymous_VerifyEmail|AsyncRequestWorkerFactor|AuthBasicAuthoritative|AuthBasicFake|AuthBasicProvider|AuthBasicUseDigestAlgorithm|AuthDBDUserPWQuery|AuthDBDUserRealmQuery|AuthDBMGroupFile|AuthDBMType|AuthDBMUserFile|AuthDigestAlgorithm|AuthDigestDomain|AuthDigestNonceLifetime|AuthDigestProvider|AuthDigestQop|AuthDigestShmemSize|AuthFormAuthoritative|AuthFormBody|AuthFormDisableNoStore|AuthFormFakeBasicAuth|AuthFormLocation|AuthFormLoginRequiredLocation|AuthFormLoginSuccessLocation|AuthFormLogoutLocation|AuthFormMethod|AuthFormMimetype|AuthFormPassword|AuthFormProvider|AuthFormSitePassphrase|AuthFormSize|AuthFormUsername|AuthGroupFile|AuthLDAPAuthorizePrefix|AuthLDAPBindAuthoritative|AuthLDAPBindDN|AuthLDAPBindPassword|AuthLDAPCharsetConfig|AuthLDAPCompareAsUser|AuthLDAPCompareDNOnServer|AuthLDAPDereferenceAliases|AuthLDAPGroupAttribute|AuthLDAPGroupAttributeIsDN|AuthLDAPInitialBindAsUser|AuthLDAPInitialBindPattern|AuthLDAPMaxSubGroupDepth|AuthLDAPRemoteUserAttribute|AuthLDAPRemoteUserIsDN|AuthLDAPSearchAsUser|AuthLDAPSubGroupAttribute|AuthLDAPSubGroupClass|AuthLDAPUrl|AuthMerging|AuthName|AuthnCacheContext|AuthnCacheEnable|AuthnCacheProvideFor|AuthnCacheSOCache|AuthnCacheTimeout|AuthnzFcgiCheckAuthnProvider|AuthnzFcgiDefineProvider|AuthType|AuthUserFile|AuthzDBDLoginToReferer|AuthzDBDQuery|AuthzDBDRedirectQuery|AuthzDBMType|AuthzSendForbiddenOnFailure|BalancerGrowth|BalancerInherit|BalancerMember|BalancerPersist|BrowserMatch|BrowserMatchNoCase|BufferedLogs|BufferSize|CacheDefaultExpire|CacheDetailHeader|CacheDirLength|CacheDirLevels|CacheDisable|CacheEnable|CacheFile|CacheHeader|CacheIgnoreCacheControl|CacheIgnoreHeaders|CacheIgnoreNoLastMod|CacheIgnoreQueryString|CacheIgnoreURLSessionIdentifiers|CacheKeyBaseURL|CacheLastModifiedFactor|CacheLock|CacheLockMaxAge|CacheLockPath|CacheMaxExpire|CacheMaxFileSize|CacheMinExpire|CacheMinFileSize|CacheNegotiatedDocs|CacheQuickHandler|CacheReadSize|CacheReadTime|CacheRoot|CacheSocache|CacheSocacheMaxSize|CacheSocacheMaxTime|CacheSocacheMinTime|CacheSocacheReadSize|CacheSocacheReadTime|CacheStaleOnError|CacheStoreExpired|CacheStoreNoStore|CacheStorePrivate|CGIDScriptTimeout|CGIMapExtension|CharsetDefault|CharsetOptions|CharsetSourceEnc|CheckCaseOnly|CheckSpelling|ChrootDir|ContentDigest|CookieDomain|CookieExpires|CookieName|CookieStyle|CookieTracking|CoreDumpDirectory|CustomLog|Dav|DavDepthInfinity|DavGenericLockDB|DavLockDB|DavMinTimeout|DBDExptime|DBDInitSQL|DBDKeep|DBDMax|DBDMin|DBDParams|DBDPersist|DBDPrepareSQL|DBDriver|DefaultIcon|DefaultLanguage|DefaultRuntimeDir|DefaultType|Define|DeflateBufferSize|DeflateCompressionLevel|DeflateFilterNote|DeflateInflateLimitRequestBody|DeflateInflateRatioBurst|DeflateInflateRatioLimit|DeflateMemLevel|DeflateWindowSize|Deny|DirectoryCheckHandler|DirectoryIndex|DirectoryIndexRedirect|DirectorySlash|DocumentRoot|DTracePrivileges|DumpIOInput|DumpIOOutput|EnableExceptionHook|EnableMMAP|EnableSendfile|Error|ErrorDocument|ErrorLog|ErrorLogFormat|Example|ExpiresActive|ExpiresByType|ExpiresDefault|ExtendedStatus|ExtFilterDefine|ExtFilterOptions|FallbackResource|FileETag|FilterChain|FilterDeclare|FilterProtocol|FilterProvider|FilterTrace|ForceLanguagePriority|ForceType|ForensicLog|GprofDir|GracefulShutdownTimeout|Group|Header|HeaderName|HeartbeatAddress|HeartbeatListen|HeartbeatMaxServers|HeartbeatStorage|HeartbeatStorage|HostnameLookups|IdentityCheck|IdentityCheckTimeout|ImapBase|ImapDefault|ImapMenu|Include|IncludeOptional|IndexHeadInsert|IndexIgnore|IndexIgnoreReset|IndexOptions|IndexOrderDefault|IndexStyleSheet|InputSed|ISAPIAppendLogToErrors|ISAPIAppendLogToQuery|ISAPICacheFile|ISAPIFakeAsync|ISAPILogNotSupported|ISAPIReadAheadBuffer|KeepAlive|KeepAliveTimeout|KeptBodySize|LanguagePriority|LDAPCacheEntries|LDAPCacheTTL|LDAPConnectionPoolTTL|LDAPConnectionTimeout|LDAPLibraryDebug|LDAPOpCacheEntries|LDAPOpCacheTTL|LDAPReferralHopLimit|LDAPReferrals|LDAPRetries|LDAPRetryDelay|LDAPSharedCacheFile|LDAPSharedCacheSize|LDAPTimeout|LDAPTrustedClientCert|LDAPTrustedGlobalCert|LDAPTrustedMode|LDAPVerifyServerCert|LimitInternalRecursion|LimitRequestBody|LimitRequestFields|LimitRequestFieldSize|LimitRequestLine|LimitXMLRequestBody|Listen|ListenBackLog|LoadFile|LoadModule|LogFormat|LogLevel|LogMessage|LuaAuthzProvider|LuaCodeCache|LuaHookAccessChecker|LuaHookAuthChecker|LuaHookCheckUserID|LuaHookFixups|LuaHookInsertFilter|LuaHookLog|LuaHookMapToStorage|LuaHookTranslateName|LuaHookTypeChecker|LuaInherit|LuaInputFilter|LuaMapHandler|LuaOutputFilter|LuaPackageCPath|LuaPackagePath|LuaQuickHandler|LuaRoot|LuaScope|MaxConnectionsPerChild|MaxKeepAliveRequests|MaxMemFree|MaxRangeOverlaps|MaxRangeReversals|MaxRanges|MaxRequestWorkers|MaxSpareServers|MaxSpareThreads|MaxThreads|MergeTrailers|MetaDir|MetaFiles|MetaSuffix|MimeMagicFile|MinSpareServers|MinSpareThreads|MMapFile|ModemStandard|ModMimeUsePathInfo|MultiviewsMatch|Mutex|NameVirtualHost|NoProxy|NWSSLTrustedCerts|NWSSLUpgradeable|Options|Order|OutputSed|PassEnv|PidFile|PrivilegesMode|Protocol|ProtocolEcho|ProxyAddHeaders|ProxyBadHeader|ProxyBlock|ProxyDomain|ProxyErrorOverride|ProxyExpressDBMFile|ProxyExpressDBMType|ProxyExpressEnable|ProxyFtpDirCharset|ProxyFtpEscapeWildcards|ProxyFtpListOnWildcard|ProxyHTMLBufSize|ProxyHTMLCharsetOut|ProxyHTMLDocType|ProxyHTMLEnable|ProxyHTMLEvents|ProxyHTMLExtended|ProxyHTMLFixups|ProxyHTMLInterp|ProxyHTMLLinks|ProxyHTMLMeta|ProxyHTMLStripComments|ProxyHTMLURLMap|ProxyIOBufferSize|ProxyMaxForwards|ProxyPass|ProxyPassInherit|ProxyPassInterpolateEnv|ProxyPassMatch|ProxyPassReverse|ProxyPassReverseCookieDomain|ProxyPassReverseCookiePath|ProxyPreserveHost|ProxyReceiveBufferSize|ProxyRemote|ProxyRemoteMatch|ProxyRequests|ProxySCGIInternalRedirect|ProxySCGISendfile|ProxySet|ProxySourceAddress|ProxyStatus|ProxyTimeout|ProxyVia|ReadmeName|ReceiveBufferSize|Redirect|RedirectMatch|RedirectPermanent|RedirectTemp|ReflectorHeader|RemoteIPHeader|RemoteIPInternalProxy|RemoteIPInternalProxyList|RemoteIPProxiesHeader|RemoteIPTrustedProxy|RemoteIPTrustedProxyList|RemoveCharset|RemoveEncoding|RemoveHandler|RemoveInputFilter|RemoveLanguage|RemoveOutputFilter|RemoveType|RequestHeader|RequestReadTimeout|Require|RewriteBase|RewriteCond|RewriteEngine|RewriteMap|RewriteOptions|RewriteRule|RLimitCPU|RLimitMEM|RLimitNPROC|Satisfy|ScoreBoardFile|Script|ScriptAlias|ScriptAliasMatch|ScriptInterpreterSource|ScriptLog|ScriptLogBuffer|ScriptLogLength|ScriptSock|SecureListen|SeeRequestTail|SendBufferSize|ServerAdmin|ServerAlias|ServerLimit|ServerName|ServerPath|ServerRoot|ServerSignature|ServerTokens|Session|SessionCookieName|SessionCookieName2|SessionCookieRemove|SessionCryptoCipher|SessionCryptoDriver|SessionCryptoPassphrase|SessionCryptoPassphraseFile|SessionDBDCookieName|SessionDBDCookieName2|SessionDBDCookieRemove|SessionDBDDeleteLabel|SessionDBDInsertLabel|SessionDBDPerUser|SessionDBDSelectLabel|SessionDBDUpdateLabel|SessionEnv|SessionExclude|SessionHeader|SessionInclude|SessionMaxAge|SetEnv|SetEnvIf|SetEnvIfExpr|SetEnvIfNoCase|SetHandler|SetInputFilter|SetOutputFilter|SSIEndTag|SSIErrorMsg|SSIETag|SSILastModified|SSILegacyExprParser|SSIStartTag|SSITimeFormat|SSIUndefinedEcho|SSLCACertificateFile|SSLCACertificatePath|SSLCADNRequestFile|SSLCADNRequestPath|SSLCARevocationCheck|SSLCARevocationFile|SSLCARevocationPath|SSLCertificateChainFile|SSLCertificateFile|SSLCertificateKeyFile|SSLCipherSuite|SSLCompression|SSLCryptoDevice|SSLEngine|SSLFIPS|SSLHonorCipherOrder|SSLInsecureRenegotiation|SSLOCSPDefaultResponder|SSLOCSPEnable|SSLOCSPOverrideResponder|SSLOCSPResponderTimeout|SSLOCSPResponseMaxAge|SSLOCSPResponseTimeSkew|SSLOCSPUseRequestNonce|SSLOpenSSLConfCmd|SSLOptions|SSLPassPhraseDialog|SSLProtocol|SSLProxyCACertificateFile|SSLProxyCACertificatePath|SSLProxyCARevocationCheck|SSLProxyCARevocationFile|SSLProxyCARevocationPath|SSLProxyCheckPeerCN|SSLProxyCheckPeerExpire|SSLProxyCheckPeerName|SSLProxyCipherSuite|SSLProxyEngine|SSLProxyMachineCertificateChainFile|SSLProxyMachineCertificateFile|SSLProxyMachineCertificatePath|SSLProxyProtocol|SSLProxyVerify|SSLProxyVerifyDepth|SSLRandomSeed|SSLRenegBufferSize|SSLRequire|SSLRequireSSL|SSLSessionCache|SSLSessionCacheTimeout|SSLSessionTicketKeyFile|SSLSRPUnknownUserSeed|SSLSRPVerifierFile|SSLStaplingCache|SSLStaplingErrorCacheTimeout|SSLStaplingFakeTryLater|SSLStaplingForceURL|SSLStaplingResponderTimeout|SSLStaplingResponseMaxAge|SSLStaplingResponseTimeSkew|SSLStaplingReturnResponderErrors|SSLStaplingStandardCacheTimeout|SSLStrictSNIVHostCheck|SSLUserName|SSLUseStapling|SSLVerifyClient|SSLVerifyDepth|StartServers|StartThreads|Substitute|Suexec|SuexecUserGroup|ThreadLimit|ThreadsPerChild|ThreadStackSize|TimeOut|TraceEnable|TransferLog|TypesConfig|UnDefine|UndefMacro|UnsetEnv|Use|UseCanonicalName|UseCanonicalPhysicalPort|User|UserDir|VHostCGIMode|VHostCGIPrivs|VHostGroup|VHostPrivs|VHostSecure|VHostUser|VirtualDocumentRoot|VirtualDocumentRootIP|VirtualScriptAlias|VirtualScriptAliasIP|WatchdogInterval|XBitHack|xml2EncAlias|xml2EncDefault|xml2StartParse)\b/im,lookbehind:!0,alias:"property"},"directive-block":{pattern:/<\/?\b(?:AuthnProviderAlias|AuthzProviderAlias|Directory|DirectoryMatch|Else|ElseIf|Files|FilesMatch|If|IfDefine|IfModule|IfVersion|Limit|LimitExcept|Location|LocationMatch|Macro|Proxy|RequireAll|RequireAny|RequireNone|VirtualHost)\b *.*>/i,inside:{"directive-block":{pattern:/^<\/?\w+/,inside:{punctuation:/^<\/?/},alias:"tag"},"directive-block-parameter":{pattern:/.*[^>]/,inside:{punctuation:/:/,string:{pattern:/("|').*\1/,inside:{variable:/[$%]\{?(?:\w\.?[-+:]?)+\}?/}}},alias:"attr-value"},punctuation:/>/},alias:"tag"},"directive-flags":{pattern:/\[(?:\w,?)+\]/,alias:"keyword"},string:{pattern:/("|').*\1/,inside:{variable:/[$%]\{?(?:\w\.?[-+:]?)+\}?/}},variable:/[$%]\{?(?:\w\.?[-+:]?)+\}?/,regex:/\^?.*\$|\^.*\$?/}; +Prism.languages.c=Prism.languages.extend("clike",{keyword:/\b(?:_Alignas|_Alignof|_Atomic|_Bool|_Complex|_Generic|_Imaginary|_Noreturn|_Static_assert|_Thread_local|asm|typeof|inline|auto|break|case|char|const|continue|default|do|double|else|enum|extern|float|for|goto|if|int|long|register|return|short|signed|sizeof|static|struct|switch|typedef|union|unsigned|void|volatile|while)\b/,operator:/-[>-]?|\+\+?|!=?|<>?=?|==?|&&?|\|\|?|[~^%?*\/]/,number:/\b-?(?:0x[\da-f]+|\d*\.?\d+(?:e[+-]?\d+)?)[ful]*\b/i}),Prism.languages.insertBefore("c","string",{macro:{pattern:/(^\s*)#\s*[a-z]+(?:[^\r\n\\]|\\(?:\r\n|[\s\S]))*/im,lookbehind:!0,alias:"property",inside:{string:{pattern:/(#\s*include\s*)(?:<.+?>|("|')(?:\\?.)+?\2)/,lookbehind:!0},directive:{pattern:/(#\s*)\b(?:define|defined|elif|else|endif|error|ifdef|ifndef|if|import|include|line|pragma|undef|using)\b/,lookbehind:!0,alias:"keyword"}}},constant:/\b(?:__FILE__|__LINE__|__DATE__|__TIME__|__TIMESTAMP__|__func__|EOF|NULL|SEEK_CUR|SEEK_END|SEEK_SET|stdin|stdout|stderr)\b/}),delete Prism.languages.c["class-name"],delete Prism.languages.c["boolean"]; +!function(e){var t={variable:[{pattern:/\$?\(\([\s\S]+?\)\)/,inside:{variable:[{pattern:/(^\$\(\([\s\S]+)\)\)/,lookbehind:!0},/^\$\(\(/],number:/\b-?(?:0x[\dA-Fa-f]+|\d*\.?\d+(?:[Ee]-?\d+)?)\b/,operator:/--?|-=|\+\+?|\+=|!=?|~|\*\*?|\*=|\/=?|%=?|<<=?|>>=?|<=?|>=?|==?|&&?|&=|\^=?|\|\|?|\|=|\?|:/,punctuation:/\(\(?|\)\)?|,|;/}},{pattern:/\$\([^)]+\)|`[^`]+`/,inside:{variable:/^\$\(|^`|\)$|`$/}},/\$(?:[\w#?*!@]+|\{[^}]+\})/i]};e.languages.bash={shebang:{pattern:/^#!\s*\/bin\/bash|^#!\s*\/bin\/sh/,alias:"important"},comment:{pattern:/(^|[^"{\\])#.*/,lookbehind:!0},string:[{pattern:/((?:^|[^<])<<\s*)["']?(\w+?)["']?\s*\r?\n(?:[\s\S])*?\r?\n\2/,lookbehind:!0,greedy:!0,inside:t},{pattern:/(["'])(?:\\[\s\S]|(?!\1)[^\\])*\1/,greedy:!0,inside:t}],variable:t.variable,"function":{pattern:/(^|[\s;|&])(?:alias|apropos|apt-get|aptitude|aspell|awk|basename|bash|bc|bg|builtin|bzip2|cal|cat|cd|cfdisk|chgrp|chmod|chown|chroot|chkconfig|cksum|clear|cmp|comm|command|cp|cron|crontab|csplit|cut|date|dc|dd|ddrescue|df|diff|diff3|dig|dir|dircolors|dirname|dirs|dmesg|du|egrep|eject|enable|env|ethtool|eval|exec|expand|expect|export|expr|fdformat|fdisk|fg|fgrep|file|find|fmt|fold|format|free|fsck|ftp|fuser|gawk|getopts|git|grep|groupadd|groupdel|groupmod|groups|gzip|hash|head|help|hg|history|hostname|htop|iconv|id|ifconfig|ifdown|ifup|import|install|jobs|join|kill|killall|less|link|ln|locate|logname|logout|look|lpc|lpr|lprint|lprintd|lprintq|lprm|ls|lsof|make|man|mkdir|mkfifo|mkisofs|mknod|more|most|mount|mtools|mtr|mv|mmv|nano|netstat|nice|nl|nohup|notify-send|npm|nslookup|open|op|passwd|paste|pathchk|ping|pkill|popd|pr|printcap|printenv|printf|ps|pushd|pv|pwd|quota|quotacheck|quotactl|ram|rar|rcp|read|readarray|readonly|reboot|rename|renice|remsync|rev|rm|rmdir|rsync|screen|scp|sdiff|sed|seq|service|sftp|shift|shopt|shutdown|sleep|slocate|sort|source|split|ssh|stat|strace|su|sudo|sum|suspend|sync|tail|tar|tee|test|time|timeout|times|touch|top|traceroute|trap|tr|tsort|tty|type|ulimit|umask|umount|unalias|uname|unexpand|uniq|units|unrar|unshar|uptime|useradd|userdel|usermod|users|uuencode|uudecode|v|vdir|vi|vmstat|wait|watch|wc|wget|whereis|which|who|whoami|write|xargs|xdg-open|yes|zip)(?=$|[\s;|&])/,lookbehind:!0},keyword:{pattern:/(^|[\s;|&])(?:let|:|\.|if|then|else|elif|fi|for|break|continue|while|in|case|function|select|do|done|until|echo|exit|return|set|declare)(?=$|[\s;|&])/,lookbehind:!0},"boolean":{pattern:/(^|[\s;|&])(?:true|false)(?=$|[\s;|&])/,lookbehind:!0},operator:/&&?|\|\|?|==?|!=?|<<>|<=?|>=?|=~/,punctuation:/\$?\(\(?|\)\)?|\.\.|[{}[\];]/};var a=t.variable[1].inside;a["function"]=e.languages.bash["function"],a.keyword=e.languages.bash.keyword,a.boolean=e.languages.bash.boolean,a.operator=e.languages.bash.operator,a.punctuation=e.languages.bash.punctuation}(Prism); +!function(e){var r=/%%?[~:\w]+%?|!\S+!/,t={pattern:/\/[a-z?]+(?=[ :]|$):?|-[a-z]\b|--[a-z-]+\b/im,alias:"attr-name",inside:{punctuation:/:/}},n=/"[^"]*"/,i=/(?:\b|-)\d+\b/;e.languages.batch={comment:[/^::.*/m,{pattern:/((?:^|[&(])[ \t]*)rem\b(?:[^^&)\r\n]|\^(?:\r\n|[\s\S]))*/im,lookbehind:!0}],label:{pattern:/^:.*/m,alias:"property"},command:[{pattern:/((?:^|[&(])[ \t]*)for(?: ?\/[a-z?](?:[ :](?:"[^"]*"|\S+))?)* \S+ in \([^)]+\) do/im,lookbehind:!0,inside:{keyword:/^for\b|\b(?:in|do)\b/i,string:n,parameter:t,variable:r,number:i,punctuation:/[()',]/}},{pattern:/((?:^|[&(])[ \t]*)if(?: ?\/[a-z?](?:[ :](?:"[^"]*"|\S+))?)* (?:not )?(?:cmdextversion \d+|defined \w+|errorlevel \d+|exist \S+|(?:"[^"]*"|\S+)?(?:==| (?:equ|neq|lss|leq|gtr|geq) )(?:"[^"]*"|\S+))/im,lookbehind:!0,inside:{keyword:/^if\b|\b(?:not|cmdextversion|defined|errorlevel|exist)\b/i,string:n,parameter:t,variable:r,number:i,operator:/\^|==|\b(?:equ|neq|lss|leq|gtr|geq)\b/i}},{pattern:/((?:^|[&()])[ \t]*)else\b/im,lookbehind:!0,inside:{keyword:/^else\b/i}},{pattern:/((?:^|[&(])[ \t]*)set(?: ?\/[a-z](?:[ :](?:"[^"]*"|\S+))?)* (?:[^^&)\r\n]|\^(?:\r\n|[\s\S]))*/im,lookbehind:!0,inside:{keyword:/^set\b/i,string:n,parameter:t,variable:[r,/\w+(?=(?:[*\/%+\-&^|]|<<|>>)?=)/],number:i,operator:/[*\/%+\-&^|]=?|<<=?|>>=?|[!~_=]/,punctuation:/[()',]/}},{pattern:/((?:^|[&(])[ \t]*@?)\w+\b(?:[^^&)\r\n]|\^(?:\r\n|[\s\S]))*/im,lookbehind:!0,inside:{keyword:/^\w+\b/i,string:n,parameter:t,label:{pattern:/(^\s*):\S+/m,lookbehind:!0,alias:"property"},variable:r,number:i,operator:/\^/}}],operator:/[&@]/,punctuation:/[()']/}}(Prism); +Prism.languages.cpp=Prism.languages.extend("c",{keyword:/\b(?:alignas|alignof|asm|auto|bool|break|case|catch|char|char16_t|char32_t|class|compl|const|constexpr|const_cast|continue|decltype|default|delete|do|double|dynamic_cast|else|enum|explicit|export|extern|float|for|friend|goto|if|inline|int|long|mutable|namespace|new|noexcept|nullptr|operator|private|protected|public|register|reinterpret_cast|return|short|signed|sizeof|static|static_assert|static_cast|struct|switch|template|this|thread_local|throw|try|typedef|typeid|typename|union|unsigned|using|virtual|void|volatile|wchar_t|while)\b/,"boolean":/\b(?:true|false)\b/,operator:/--?|\+\+?|!=?|<{1,2}=?|>{1,2}=?|->|:{1,2}|={1,2}|\^|~|%|&{1,2}|\|\|?|\?|\*|\/|\b(?:and|and_eq|bitand|bitor|not|not_eq|or|or_eq|xor|xor_eq)\b/}),Prism.languages.insertBefore("cpp","keyword",{"class-name":{pattern:/(class\s+)\w+/i,lookbehind:!0}}); +Prism.languages.csharp=Prism.languages.extend("clike",{keyword:/\b(abstract|as|async|await|base|bool|break|byte|case|catch|char|checked|class|const|continue|decimal|default|delegate|do|double|else|enum|event|explicit|extern|false|finally|fixed|float|for|foreach|goto|if|implicit|in|int|interface|internal|is|lock|long|namespace|new|null|object|operator|out|override|params|private|protected|public|readonly|ref|return|sbyte|sealed|short|sizeof|stackalloc|static|string|struct|switch|this|throw|true|try|typeof|uint|ulong|unchecked|unsafe|ushort|using|virtual|void|volatile|while|add|alias|ascending|async|await|descending|dynamic|from|get|global|group|into|join|let|orderby|partial|remove|select|set|value|var|where|yield)\b/,string:[{pattern:/@("|')(?:\1\1|\\[\s\S]|(?!\1)[^\\])*\1/,greedy:!0},{pattern:/("|')(?:\\.|(?!\1)[^\\\r\n])*?\1/,greedy:!0}],number:/\b-?(?:0x[\da-f]+|\d*\.?\d+f?)\b/i}),Prism.languages.insertBefore("csharp","keyword",{"generic-method":{pattern:/[a-z0-9_]+\s*<[^>\r\n]+?>\s*(?=\()/i,alias:"function",inside:{keyword:Prism.languages.csharp.keyword,punctuation:/[<>(),.:]/}},preprocessor:{pattern:/(^\s*)#.*/m,lookbehind:!0,alias:"property",inside:{directive:{pattern:/(\s*#)\b(?:define|elif|else|endif|endregion|error|if|line|pragma|region|undef|warning)\b/,lookbehind:!0,alias:"keyword"}}}}); +Prism.languages.diff={coord:[/^(?:\*{3}|-{3}|\+{3}).*$/m,/^@@.*@@$/m,/^\d+.*$/m],deleted:/^[-<].*$/m,inserted:/^[+>].*$/m,diff:{pattern:/^!(?!!).+$/m,alias:"important"}}; +Prism.languages.ini={comment:/^[ \t]*;.*$/m,selector:/^[ \t]*\[.*?\]/m,constant:/^[ \t]*[^\s=]+?(?=[ \t]*=)/m,"attr-value":{pattern:/=.*/,inside:{punctuation:/^[=]/}}}; +Prism.languages.java=Prism.languages.extend("clike",{keyword:/\b(?:abstract|continue|for|new|switch|assert|default|goto|package|synchronized|boolean|do|if|private|this|break|double|implements|protected|throw|byte|else|import|public|throws|case|enum|instanceof|return|transient|catch|extends|int|short|try|char|final|interface|static|void|class|finally|long|strictfp|volatile|const|float|native|super|while)\b/,number:/\b0b[01]+\b|\b0x[\da-f]*\.?[\da-fp\-]+\b|\b\d*\.?\d+(?:e[+-]?\d+)?[df]?\b/i,operator:{pattern:/(^|[^.])(?:\+[+=]?|-[-=]?|!=?|<>?>?=?|==?|&[&=]?|\|[|=]?|\*=?|\/=?|%=?|\^=?|[?:~])/m,lookbehind:!0}}),Prism.languages.insertBefore("java","function",{annotation:{alias:"punctuation",pattern:/(^|[^.])@\w+/,lookbehind:!0}}); +Prism.languages.json={property:/"(?:\\.|[^\\"\r\n])*"(?=\s*:)/i,string:{pattern:/"(?:\\.|[^\\"\r\n])*"(?!\s*:)/,greedy:!0},number:/\b-?(?:0x[\dA-Fa-f]+|\d*\.?\d+(?:[Ee][+-]?\d+)?)\b/,punctuation:/[{}[\]);,]/,operator:/:/g,"boolean":/\b(?:true|false)\b/i,"null":/\bnull\b/i},Prism.languages.jsonp=Prism.languages.json; +Prism.languages.lua={comment:/^#!.+|--(?:\[(=*)\[[\s\S]*?\]\1\]|.*)/m,string:{pattern:/(["'])(?:(?!\1)[^\\\r\n]|\\z(?:\r\n|\s)|\\(?:\r\n|[\s\S]))*\1|\[(=*)\[[\s\S]*?\]\2\]/,greedy:!0},number:/\b0x[a-f\d]+\.?[a-f\d]*(?:p[+-]?\d+)?\b|\b\d+(?:\.\B|\.?\d*(?:e[+-]?\d+)?\b)|\B\.\d+(?:e[+-]?\d+)?\b/i,keyword:/\b(?:and|break|do|else|elseif|end|false|for|function|goto|if|in|local|nil|not|or|repeat|return|then|true|until|while)\b/,"function":/(?!\d)\w+(?=\s*(?:[({]))/,operator:[/[-+*%^&|#]|\/\/?|<[<=]?|>[>=]?|[=~]=?/,{pattern:/(^|[^.])\.\.(?!\.)/,lookbehind:!0}],punctuation:/[\[\](){},;]|\.+|:+/}; +Prism.languages.nginx=Prism.languages.extend("clike",{comment:{pattern:/(^|[^"{\\])#.*/,lookbehind:!0},keyword:/\b(?:CONTENT_|DOCUMENT_|GATEWAY_|HTTP_|HTTPS|if_not_empty|PATH_|QUERY_|REDIRECT_|REMOTE_|REQUEST_|SCGI|SCRIPT_|SERVER_|http|events|accept_mutex|accept_mutex_delay|access_log|add_after_body|add_before_body|add_header|addition_types|aio|alias|allow|ancient_browser|ancient_browser_value|auth|auth_basic|auth_basic_user_file|auth_http|auth_http_header|auth_http_timeout|autoindex|autoindex_exact_size|autoindex_localtime|break|charset|charset_map|charset_types|chunked_transfer_encoding|client_body_buffer_size|client_body_in_file_only|client_body_in_single_buffer|client_body_temp_path|client_body_timeout|client_header_buffer_size|client_header_timeout|client_max_body_size|connection_pool_size|create_full_put_path|daemon|dav_access|dav_methods|debug_connection|debug_points|default_type|deny|devpoll_changes|devpoll_events|directio|directio_alignment|disable_symlinks|empty_gif|env|epoll_events|error_log|error_page|expires|fastcgi_buffer_size|fastcgi_buffers|fastcgi_busy_buffers_size|fastcgi_cache|fastcgi_cache_bypass|fastcgi_cache_key|fastcgi_cache_lock|fastcgi_cache_lock_timeout|fastcgi_cache_methods|fastcgi_cache_min_uses|fastcgi_cache_path|fastcgi_cache_purge|fastcgi_cache_use_stale|fastcgi_cache_valid|fastcgi_connect_timeout|fastcgi_hide_header|fastcgi_ignore_client_abort|fastcgi_ignore_headers|fastcgi_index|fastcgi_intercept_errors|fastcgi_keep_conn|fastcgi_max_temp_file_size|fastcgi_next_upstream|fastcgi_no_cache|fastcgi_param|fastcgi_pass|fastcgi_pass_header|fastcgi_read_timeout|fastcgi_redirect_errors|fastcgi_send_timeout|fastcgi_split_path_info|fastcgi_store|fastcgi_store_access|fastcgi_temp_file_write_size|fastcgi_temp_path|flv|geo|geoip_city|geoip_country|google_perftools_profiles|gzip|gzip_buffers|gzip_comp_level|gzip_disable|gzip_http_version|gzip_min_length|gzip_proxied|gzip_static|gzip_types|gzip_vary|if|if_modified_since|ignore_invalid_headers|image_filter|image_filter_buffer|image_filter_jpeg_quality|image_filter_sharpen|image_filter_transparency|imap_capabilities|imap_client_buffer|include|index|internal|ip_hash|keepalive|keepalive_disable|keepalive_requests|keepalive_timeout|kqueue_changes|kqueue_events|large_client_header_buffers|limit_conn|limit_conn_log_level|limit_conn_zone|limit_except|limit_rate|limit_rate_after|limit_req|limit_req_log_level|limit_req_zone|limit_zone|lingering_close|lingering_time|lingering_timeout|listen|location|lock_file|log_format|log_format_combined|log_not_found|log_subrequest|map|map_hash_bucket_size|map_hash_max_size|master_process|max_ranges|memcached_buffer_size|memcached_connect_timeout|memcached_next_upstream|memcached_pass|memcached_read_timeout|memcached_send_timeout|merge_slashes|min_delete_depth|modern_browser|modern_browser_value|mp4|mp4_buffer_size|mp4_max_buffer_size|msie_padding|msie_refresh|multi_accept|open_file_cache|open_file_cache_errors|open_file_cache_min_uses|open_file_cache_valid|open_log_file_cache|optimize_server_names|override_charset|pcre_jit|perl|perl_modules|perl_require|perl_set|pid|pop3_auth|pop3_capabilities|port_in_redirect|post_action|postpone_output|protocol|proxy|proxy_buffer|proxy_buffer_size|proxy_buffering|proxy_buffers|proxy_busy_buffers_size|proxy_cache|proxy_cache_bypass|proxy_cache_key|proxy_cache_lock|proxy_cache_lock_timeout|proxy_cache_methods|proxy_cache_min_uses|proxy_cache_path|proxy_cache_use_stale|proxy_cache_valid|proxy_connect_timeout|proxy_cookie_domain|proxy_cookie_path|proxy_headers_hash_bucket_size|proxy_headers_hash_max_size|proxy_hide_header|proxy_http_version|proxy_ignore_client_abort|proxy_ignore_headers|proxy_intercept_errors|proxy_max_temp_file_size|proxy_method|proxy_next_upstream|proxy_no_cache|proxy_pass|proxy_pass_error_message|proxy_pass_header|proxy_pass_request_body|proxy_pass_request_headers|proxy_read_timeout|proxy_redirect|proxy_redirect_errors|proxy_send_lowat|proxy_send_timeout|proxy_set_body|proxy_set_header|proxy_ssl_session_reuse|proxy_store|proxy_store_access|proxy_temp_file_write_size|proxy_temp_path|proxy_timeout|proxy_upstream_fail_timeout|proxy_upstream_max_fails|random_index|read_ahead|real_ip_header|recursive_error_pages|request_pool_size|reset_timedout_connection|resolver|resolver_timeout|return|rewrite|root|rtsig_overflow_events|rtsig_overflow_test|rtsig_overflow_threshold|rtsig_signo|satisfy|satisfy_any|secure_link_secret|send_lowat|send_timeout|sendfile|sendfile_max_chunk|server|server_name|server_name_in_redirect|server_names_hash_bucket_size|server_names_hash_max_size|server_tokens|set|set_real_ip_from|smtp_auth|smtp_capabilities|so_keepalive|source_charset|split_clients|ssi|ssi_silent_errors|ssi_types|ssi_value_length|ssl|ssl_certificate|ssl_certificate_key|ssl_ciphers|ssl_client_certificate|ssl_crl|ssl_dhparam|ssl_engine|ssl_prefer_server_ciphers|ssl_protocols|ssl_session_cache|ssl_session_timeout|ssl_verify_client|ssl_verify_depth|starttls|stub_status|sub_filter|sub_filter_once|sub_filter_types|tcp_nodelay|tcp_nopush|timeout|timer_resolution|try_files|types|types_hash_bucket_size|types_hash_max_size|underscores_in_headers|uninitialized_variable_warn|upstream|use|user|userid|userid_domain|userid_expires|userid_name|userid_p3p|userid_path|userid_service|valid_referers|variables_hash_bucket_size|variables_hash_max_size|worker_connections|worker_cpu_affinity|worker_priority|worker_processes|worker_rlimit_core|worker_rlimit_nofile|worker_rlimit_sigpending|working_directory|xclient|xml_entities|xslt_entities|xslt_stylesheet|xslt_types)\b/i}),Prism.languages.insertBefore("nginx","keyword",{variable:/\$[a-z_]+/i}); +Prism.languages.perl={comment:[{pattern:/(^\s*)=\w+[\s\S]*?=cut.*/m,lookbehind:!0},{pattern:/(^|[^\\$])#.*/,lookbehind:!0}],string:[{pattern:/\b(?:q|qq|qx|qw)\s*([^a-zA-Z0-9\s{(\[<])(?:(?!\1)[^\\]|\\[\s\S])*\1/,greedy:!0},{pattern:/\b(?:q|qq|qx|qw)\s+([a-zA-Z0-9])(?:(?!\1)[^\\]|\\[\s\S])*\1/,greedy:!0},{pattern:/\b(?:q|qq|qx|qw)\s*\((?:[^()\\]|\\[\s\S])*\)/,greedy:!0},{pattern:/\b(?:q|qq|qx|qw)\s*\{(?:[^{}\\]|\\[\s\S])*\}/,greedy:!0},{pattern:/\b(?:q|qq|qx|qw)\s*\[(?:[^[\]\\]|\\[\s\S])*\]/,greedy:!0},{pattern:/\b(?:q|qq|qx|qw)\s*<(?:[^<>\\]|\\[\s\S])*>/,greedy:!0},{pattern:/("|`)(?:(?!\1)[^\\]|\\[\s\S])*\1/,greedy:!0},{pattern:/'(?:[^'\\\r\n]|\\.)*'/,greedy:!0}],regex:[{pattern:/\b(?:m|qr)\s*([^a-zA-Z0-9\s{(\[<])(?:(?!\1)[^\\]|\\[\s\S])*\1[msixpodualngc]*/,greedy:!0},{pattern:/\b(?:m|qr)\s+([a-zA-Z0-9])(?:(?!\1)[^\\]|\\[\s\S])*\1[msixpodualngc]*/,greedy:!0},{pattern:/\b(?:m|qr)\s*\((?:[^()\\]|\\[\s\S])*\)[msixpodualngc]*/,greedy:!0},{pattern:/\b(?:m|qr)\s*\{(?:[^{}\\]|\\[\s\S])*\}[msixpodualngc]*/,greedy:!0},{pattern:/\b(?:m|qr)\s*\[(?:[^[\]\\]|\\[\s\S])*\][msixpodualngc]*/,greedy:!0},{pattern:/\b(?:m|qr)\s*<(?:[^<>\\]|\\[\s\S])*>[msixpodualngc]*/,greedy:!0},{pattern:/(^|[^-]\b)(?:s|tr|y)\s*([^a-zA-Z0-9\s{(\[<])(?:(?!\2)[^\\]|\\[\s\S])*\2(?:(?!\2)[^\\]|\\[\s\S])*\2[msixpodualngcer]*/,lookbehind:!0,greedy:!0},{pattern:/(^|[^-]\b)(?:s|tr|y)\s+([a-zA-Z0-9])(?:(?!\2)[^\\]|\\[\s\S])*\2(?:(?!\2)[^\\]|\\[\s\S])*\2[msixpodualngcer]*/,lookbehind:!0,greedy:!0},{pattern:/(^|[^-]\b)(?:s|tr|y)\s*\((?:[^()\\]|\\[\s\S])*\)\s*\((?:[^()\\]|\\[\s\S])*\)[msixpodualngcer]*/,lookbehind:!0,greedy:!0},{pattern:/(^|[^-]\b)(?:s|tr|y)\s*\{(?:[^{}\\]|\\[\s\S])*\}\s*\{(?:[^{}\\]|\\[\s\S])*\}[msixpodualngcer]*/,lookbehind:!0,greedy:!0},{pattern:/(^|[^-]\b)(?:s|tr|y)\s*\[(?:[^[\]\\]|\\[\s\S])*\]\s*\[(?:[^[\]\\]|\\[\s\S])*\][msixpodualngcer]*/,lookbehind:!0,greedy:!0},{pattern:/(^|[^-]\b)(?:s|tr|y)\s*<(?:[^<>\\]|\\[\s\S])*>\s*<(?:[^<>\\]|\\[\s\S])*>[msixpodualngcer]*/,lookbehind:!0,greedy:!0},{pattern:/\/(?:[^\/\\\r\n]|\\.)*\/[msixpodualngc]*(?=\s*(?:$|[\r\n,.;})&|\-+*~<>!?^]|(lt|gt|le|ge|eq|ne|cmp|not|and|or|xor|x)\b))/,greedy:!0}],variable:[/[&*$@%]\{\^[A-Z]+\}/,/[&*$@%]\^[A-Z_]/,/[&*$@%]#?(?=\{)/,/[&*$@%]#?(?:(?:::)*'?(?!\d)[\w$]+)+(?:::)*/i,/[&*$@%]\d+/,/(?!%=)[$@%][!"#$%&'()*+,\-.\/:;<=>?@[\\\]^_`{|}~]/],filehandle:{pattern:/<(?![<=])\S*>|\b_\b/,alias:"symbol"},vstring:{pattern:/v\d+(?:\.\d+)*|\d+(?:\.\d+){2,}/,alias:"string"},"function":{pattern:/sub [a-z0-9_]+/i,inside:{keyword:/sub/}},keyword:/\b(?:any|break|continue|default|delete|die|do|else|elsif|eval|for|foreach|given|goto|if|last|local|my|next|our|package|print|redo|require|say|state|sub|switch|undef|unless|until|use|when|while)\b/,number:/\b-?(?:0x[\dA-Fa-f](?:_?[\dA-Fa-f])*|0b[01](?:_?[01])*|(?:\d(?:_?\d)*)?\.?\d(?:_?\d)*(?:[Ee][+-]?\d+)?)\b/,operator:/-[rwxoRWXOezsfdlpSbctugkTBMAC]\b|\+[+=]?|-[-=>]?|\*\*?=?|\/\/?=?|=[=~>]?|~[~=]?|\|\|?=?|&&?=?|<(?:=>?|<=?)?|>>?=?|![~=]?|[%^]=?|\.(?:=|\.\.?)?|[\\?]|\bx(?:=|\b)|\b(?:lt|gt|le|ge|eq|ne|cmp|not|and|or|xor)\b/,punctuation:/[{}[\];(),:]/}; +Prism.languages.python={comment:{pattern:/(^|[^\\])#.*/,lookbehind:!0},"triple-quoted-string":{pattern:/("""|''')[\s\S]+?\1/,greedy:!0,alias:"string"},string:{pattern:/("|')(?:\\.|(?!\1)[^\\\r\n])*\1/,greedy:!0},"function":{pattern:/((?:^|\s)def[ \t]+)[a-zA-Z_]\w*(?=\s*\()/g,lookbehind:!0},"class-name":{pattern:/(\bclass\s+)\w+/i,lookbehind:!0},keyword:/\b(?:as|assert|async|await|break|class|continue|def|del|elif|else|except|exec|finally|for|from|global|if|import|in|is|lambda|nonlocal|pass|print|raise|return|try|while|with|yield)\b/,builtin:/\b(?:__import__|abs|all|any|apply|ascii|basestring|bin|bool|buffer|bytearray|bytes|callable|chr|classmethod|cmp|coerce|compile|complex|delattr|dict|dir|divmod|enumerate|eval|execfile|file|filter|float|format|frozenset|getattr|globals|hasattr|hash|help|hex|id|input|int|intern|isinstance|issubclass|iter|len|list|locals|long|map|max|memoryview|min|next|object|oct|open|ord|pow|property|range|raw_input|reduce|reload|repr|reversed|round|set|setattr|slice|sorted|staticmethod|str|sum|super|tuple|type|unichr|unicode|vars|xrange|zip)\b/,"boolean":/\b(?:True|False|None)\b/,number:/\b-?(?:0[bo])?(?:(?:\d|0x[\da-f])[\da-f]*\.?\d*|\.\d+)(?:e[+-]?\d+)?j?\b/i,operator:/[-+%=]=?|!=|\*\*?=?|\/\/?=?|<[<=>]?|>[=>]?|[&|^~]|\b(?:or|and|not)\b/,punctuation:/[{}[\];(),.:]/}; +!function(a){var e=a.util.clone(a.languages.javascript);a.languages.jsx=a.languages.extend("markup",e),a.languages.jsx.tag.pattern=/<\/?[\w.:-]+\s*(?:\s+(?:[\w\.:-]+(?:=(?:("|')(?:\\[\s\S]|(?!\1)[^\\])*\1|[^\s'">=]+|(?:\{[^}]*\})))?|\{\.{3}\w+\}))*\s*\/?>/i,a.languages.jsx.tag.inside["attr-value"].pattern=/=(?!\{)(?:("|')(?:\\[\s\S]|(?!\1)[^\\])*\1|[^\s'">]+)/i,a.languages.insertBefore("inside","attr-name",{spread:{pattern:/\{\.{3}\w+\}/,inside:{punctuation:/[{}]|\.{3}/,"attr-value":/\w+/}}},a.languages.jsx.tag);var s=a.util.clone(a.languages.jsx);delete s.punctuation,s=a.languages.insertBefore("jsx","operator",{punctuation:/=(?={)|[{}[\];(),.:]/},{jsx:s}),a.languages.insertBefore("inside","attr-value",{script:{pattern:/=(\{(?:\{[^}]*\}|[^}])+\})/i,inside:s,alias:"language-javascript"}},a.languages.jsx.tag)}(Prism); +Prism.languages.scala=Prism.languages.extend("java",{keyword:/<-|=>|\b(?:abstract|case|catch|class|def|do|else|extends|final|finally|for|forSome|if|implicit|import|lazy|match|new|null|object|override|package|private|protected|return|sealed|self|super|this|throw|trait|try|type|val|var|while|with|yield)\b/,string:[{pattern:/"""[\s\S]*?"""/,greedy:!0},{pattern:/("|')(?:\\.|(?!\1)[^\\\r\n])*\1/,greedy:!0}],builtin:/\b(?:String|Int|Long|Short|Byte|Boolean|Double|Float|Char|Any|AnyRef|AnyVal|Unit|Nothing)\b/,number:/\b(?:0x[\da-f]*\.?[\da-f]+|\d*\.?\d+e?\d*[dfl]?)\b/i,symbol:/'[^\d\s\\]\w*/}),delete Prism.languages.scala["class-name"],delete Prism.languages.scala["function"]; +Prism.languages.sql={comment:{pattern:/(^|[^\\])(?:\/\*[\s\S]*?\*\/|(?:--|\/\/|#).*)/,lookbehind:!0},string:{pattern:/(^|[^@\\])("|')(?:\\[\s\S]|(?!\2)[^\\])*\2/,greedy:!0,lookbehind:!0},variable:/@[\w.$]+|@(["'`])(?:\\[\s\S]|(?!\1)[^\\])+\1/,"function":/\b(?:COUNT|SUM|AVG|MIN|MAX|FIRST|LAST|UCASE|LCASE|MID|LEN|ROUND|NOW|FORMAT)(?=\s*\()/i,keyword:/\b(?:ACTION|ADD|AFTER|ALGORITHM|ALL|ALTER|ANALYZE|ANY|APPLY|AS|ASC|AUTHORIZATION|AUTO_INCREMENT|BACKUP|BDB|BEGIN|BERKELEYDB|BIGINT|BINARY|BIT|BLOB|BOOL|BOOLEAN|BREAK|BROWSE|BTREE|BULK|BY|CALL|CASCADED?|CASE|CHAIN|CHAR VARYING|CHARACTER (?:SET|VARYING)|CHARSET|CHECK|CHECKPOINT|CLOSE|CLUSTERED|COALESCE|COLLATE|COLUMN|COLUMNS|COMMENT|COMMIT|COMMITTED|COMPUTE|CONNECT|CONSISTENT|CONSTRAINT|CONTAINS|CONTAINSTABLE|CONTINUE|CONVERT|CREATE|CROSS|CURRENT(?:_DATE|_TIME|_TIMESTAMP|_USER)?|CURSOR|DATA(?:BASES?)?|DATE(?:TIME)?|DBCC|DEALLOCATE|DEC|DECIMAL|DECLARE|DEFAULT|DEFINER|DELAYED|DELETE|DELIMITER(?:S)?|DENY|DESC|DESCRIBE|DETERMINISTIC|DISABLE|DISCARD|DISK|DISTINCT|DISTINCTROW|DISTRIBUTED|DO|DOUBLE(?: PRECISION)?|DROP|DUMMY|DUMP(?:FILE)?|DUPLICATE KEY|ELSE|ENABLE|ENCLOSED BY|END|ENGINE|ENUM|ERRLVL|ERRORS|ESCAPE(?:D BY)?|EXCEPT|EXEC(?:UTE)?|EXISTS|EXIT|EXPLAIN|EXTENDED|FETCH|FIELDS|FILE|FILLFACTOR|FIRST|FIXED|FLOAT|FOLLOWING|FOR(?: EACH ROW)?|FORCE|FOREIGN|FREETEXT(?:TABLE)?|FROM|FULL|FUNCTION|GEOMETRY(?:COLLECTION)?|GLOBAL|GOTO|GRANT|GROUP|HANDLER|HASH|HAVING|HOLDLOCK|IDENTITY(?:_INSERT|COL)?|IF|IGNORE|IMPORT|INDEX|INFILE|INNER|INNODB|INOUT|INSERT|INT|INTEGER|INTERSECT|INTO|INVOKER|ISOLATION LEVEL|JOIN|KEYS?|KILL|LANGUAGE SQL|LAST|LEFT|LIMIT|LINENO|LINES|LINESTRING|LOAD|LOCAL|LOCK|LONG(?:BLOB|TEXT)|MATCH(?:ED)?|MEDIUM(?:BLOB|INT|TEXT)|MERGE|MIDDLEINT|MODIFIES SQL DATA|MODIFY|MULTI(?:LINESTRING|POINT|POLYGON)|NATIONAL(?: CHAR VARYING| CHARACTER(?: VARYING)?| VARCHAR)?|NATURAL|NCHAR(?: VARCHAR)?|NEXT|NO(?: SQL|CHECK|CYCLE)?|NONCLUSTERED|NULLIF|NUMERIC|OFF?|OFFSETS?|ON|OPEN(?:DATASOURCE|QUERY|ROWSET)?|OPTIMIZE|OPTION(?:ALLY)?|ORDER|OUT(?:ER|FILE)?|OVER|PARTIAL|PARTITION|PERCENT|PIVOT|PLAN|POINT|POLYGON|PRECEDING|PRECISION|PREV|PRIMARY|PRINT|PRIVILEGES|PROC(?:EDURE)?|PUBLIC|PURGE|QUICK|RAISERROR|READ(?:S SQL DATA|TEXT)?|REAL|RECONFIGURE|REFERENCES|RELEASE|RENAME|REPEATABLE|REPLICATION|REQUIRE|RESTORE|RESTRICT|RETURNS?|REVOKE|RIGHT|ROLLBACK|ROUTINE|ROW(?:COUNT|GUIDCOL|S)?|RTREE|RULE|SAVE(?:POINT)?|SCHEMA|SELECT|SERIAL(?:IZABLE)?|SESSION(?:_USER)?|SET(?:USER)?|SHARE MODE|SHOW|SHUTDOWN|SIMPLE|SMALLINT|SNAPSHOT|SOME|SONAME|START(?:ING BY)?|STATISTICS|STATUS|STRIPED|SYSTEM_USER|TABLES?|TABLESPACE|TEMP(?:ORARY|TABLE)?|TERMINATED BY|TEXT(?:SIZE)?|THEN|TIMESTAMP|TINY(?:BLOB|INT|TEXT)|TOP?|TRAN(?:SACTIONS?)?|TRIGGER|TRUNCATE|TSEQUAL|TYPES?|UNBOUNDED|UNCOMMITTED|UNDEFINED|UNION|UNIQUE|UNPIVOT|UPDATE(?:TEXT)?|USAGE|USE|USER|USING|VALUES?|VAR(?:BINARY|CHAR|CHARACTER|YING)|VIEW|WAITFOR|WARNINGS|WHEN|WHERE|WHILE|WITH(?: ROLLUP|IN)?|WORK|WRITE(?:TEXT)?)\b/i,"boolean":/\b(?:TRUE|FALSE|NULL)\b/i,number:/\b-?(?:0x)?\d*\.?[\da-f]+\b/,operator:/[-+*\/=%^~]|&&?|\|\|?|!=?|<(?:=>?|<|>)?|>[>=]?|\b(?:AND|BETWEEN|IN|LIKE|NOT|OR|IS|DIV|REGEXP|RLIKE|SOUNDS LIKE|XOR)\b/i,punctuation:/[;[\]()`,.]/}; +Prism.languages.yaml={scalar:{pattern:/([\-:]\s*(?:![^\s]+)?[ \t]*[|>])[ \t]*(?:((?:\r?\n|\r)[ \t]+)[^\r\n]+(?:\2[^\r\n]+)*)/,lookbehind:!0,alias:"string"},comment:/#.*/,key:{pattern:/(\s*(?:^|[:\-,[{\r\n?])[ \t]*(?:![^\s]+)?[ \t]*)[^\r\n{[\]},#\s]+?(?=\s*:\s)/,lookbehind:!0,alias:"atrule"},directive:{pattern:/(^[ \t]*)%.+/m,lookbehind:!0,alias:"important"},datetime:{pattern:/([:\-,[{]\s*(?:![^\s]+)?[ \t]*)(?:\d{4}-\d\d?-\d\d?(?:[tT]|[ \t]+)\d\d?:\d{2}:\d{2}(?:\.\d*)?[ \t]*(?:Z|[-+]\d\d?(?::\d{2})?)?|\d{4}-\d{2}-\d{2}|\d\d?:\d{2}(?::\d{2}(?:\.\d*)?)?)(?=[ \t]*(?:$|,|]|}))/m,lookbehind:!0,alias:"number"},"boolean":{pattern:/([:\-,[{]\s*(?:![^\s]+)?[ \t]*)(?:true|false)[ \t]*(?=$|,|]|})/im,lookbehind:!0,alias:"important"},"null":{pattern:/([:\-,[{]\s*(?:![^\s]+)?[ \t]*)(?:null|~)[ \t]*(?=$|,|]|})/im,lookbehind:!0,alias:"important"},string:{pattern:/([:\-,[{]\s*(?:![^\s]+)?[ \t]*)("|')(?:(?!\2)[^\\\r\n]|\\.)*\2(?=[ \t]*(?:$|,|]|}))/m,lookbehind:!0,greedy:!0},number:{pattern:/([:\-,[{]\s*(?:![^\s]+)?[ \t]*)[+\-]?(?:0x[\da-f]+|0o[0-7]+|(?:\d+\.?\d*|\.?\d+)(?:e[+-]?\d+)?|\.inf|\.nan)[ \t]*(?=$|,|]|})/im,lookbehind:!0},tag:/![^\s]+/,important:/[&*][\w]+/,punctuation:/---|[:[\]{}\-,|>?]|\.\.\./}; +!function(){if("undefined"!=typeof self&&self.Prism&&self.document){var e="line-numbers",t=function(e){var t=n(e),r=t["white-space"];if("pre-wrap"===r||"pre-line"===r){var s=e.querySelector("code"),l=e.querySelector(".line-numbers-rows"),a=e.querySelector(".line-numbers-sizer"),i=e.textContent.split("\n");a||(a=document.createElement("span"),a.className="line-numbers-sizer",s.appendChild(a)),a.style.display="block",i.forEach(function(e,t){a.textContent=e||"\n";var n=a.getBoundingClientRect().height;l.children[t].style.height=n+"px"}),a.textContent="",a.style.display="none"}},n=function(e){return e?window.getComputedStyle?getComputedStyle(e):e.currentStyle||null:null};window.addEventListener("resize",function(){Array.prototype.forEach.call(document.querySelectorAll("pre."+e),t)}),Prism.hooks.add("complete",function(e){if(e.code){var n=e.element.parentNode,r=/\s*\bline-numbers\b\s*/;if(n&&/pre/i.test(n.nodeName)&&(r.test(n.className)||r.test(e.element.className))&&!e.element.querySelector(".line-numbers-rows")){r.test(e.element.className)&&(e.element.className=e.element.className.replace(r," ")),r.test(n.className)||(n.className+=" line-numbers");var s,l=e.code.match(/\n(?!$)/g),a=l?l.length+1:1,i=new Array(a+1);i=i.join(""),s=document.createElement("span"),s.setAttribute("aria-hidden","true"),s.className="line-numbers-rows",s.innerHTML=i,n.hasAttribute("data-start")&&(n.style.counterReset="linenumber "+(parseInt(n.getAttribute("data-start"),10)-1)),e.element.appendChild(s),t(n)}}})}}(); +!function(){if("undefined"!=typeof self&&self.Prism&&self.document){var t=[],e={},n=function(){};Prism.plugins.toolbar={};var a=Prism.plugins.toolbar.registerButton=function(n,a){var o;o="function"==typeof a?a:function(t){var e;return"function"==typeof a.onClick?(e=document.createElement("button"),e.type="button",e.addEventListener("click",function(){a.onClick.call(this,t)})):"string"==typeof a.url?(e=document.createElement("a"),e.href=a.url):e=document.createElement("span"),e.textContent=a.text,e},t.push(e[n]=o)},o=Prism.plugins.toolbar.hook=function(a){var o=a.element.parentNode;if(o&&/pre/i.test(o.nodeName)&&!o.classList.contains("code-toolbar")){o.classList.add("code-toolbar");var r=document.createElement("div");r.classList.add("toolbar"),document.body.hasAttribute("data-toolbar-order")&&(t=document.body.getAttribute("data-toolbar-order").split(",").map(function(t){return e[t]||n})),t.forEach(function(t){var e=t(a);if(e){var n=document.createElement("div");n.classList.add("toolbar-item"),n.appendChild(e),r.appendChild(n)}}),o.appendChild(r)}};a("label",function(t){var e=t.element.parentNode;if(e&&/pre/i.test(e.nodeName)&&e.hasAttribute("data-label")){var n,a,o=e.getAttribute("data-label");try{a=document.querySelector("template#"+o)}catch(r){}return a?n=a.content:(e.hasAttribute("data-url")?(n=document.createElement("a"),n.href=e.getAttribute("data-url")):n=document.createElement("span"),n.textContent=o),n}}),Prism.hooks.add("complete",o)}}(); +!function(){"undefined"!=typeof self&&!self.Prism||"undefined"!=typeof global&&!global.Prism||Prism.hooks.add("wrap",function(e){"keyword"===e.type&&e.classes.push("keyword-"+e.content)})}(); +!function(){if("undefined"!=typeof self&&self.Prism&&self.document){if(!Prism.plugins.toolbar)return console.warn("Show Languages plugin loaded before Toolbar plugin."),void 0;var e={html:"HTML",xml:"XML",svg:"SVG",mathml:"MathML",css:"CSS",clike:"C-sympathy",javascript:"JavaScript",abap:"ABAP",actionscript:"ActionScript",apacheconf:"Apache Configuration",apl:"APL",applescript:"AppleScript",asciidoc:"AsciiDoc",aspnet:"ASP.NET (C#)",autohotkey:"AutoHotkey",autoit:"AutoIt",basic:"BASIC",csharp:"C#",cpp:"C++",coffeescript:"CoffeeScript","css-extras":"CSS Extras",django:"Django/Jinja2",fsharp:"F#",glsl:"GLSL",graphql:"GraphQL",http:"HTTP",inform7:"Inform 7",json:"JSON",latex:"LaTeX",livescript:"LiveScript",lolcode:"LOLCODE",matlab:"MATLAB",mel:"MEL",n4js:"N4JS",nasm:"NASM",nginx:"nginx",nsis:"NSIS",objectivec:"Objective-C",ocaml:"OCaml",opencl:"OpenCL",parigp:"PARI/GP",php:"PHP","php-extras":"PHP Extras",powershell:"PowerShell",properties:".properties",protobuf:"Protocol Buffers",jsx:"React JSX",renpy:"Ren'py",rest:"reST (reStructuredText)",sas:"SAS",sass:"Sass (Sass)",scss:"Sass (Scss)",sql:"SQL",typescript:"TypeScript",vbnet:"VB.Net",vhdl:"VHDL",vim:"vim",wiki:"Wiki markup",xojo:"Xojo (REALbasic)",yaml:"YAML"};Prism.plugins.toolbar.registerButton("show-language",function(t){var a=t.element.parentNode;if(a&&/pre/i.test(a.nodeName)){var s=a.getAttribute("data-language")||e[t.language]||t.language.substring(0,1).toUpperCase()+t.language.substring(1),r=document.createElement("span");return r.textContent=s,r}})}}(); +!function(){if("undefined"!=typeof self&&self.Prism&&self.document){if(!Prism.plugins.toolbar)return console.warn("Copy to Clipboard plugin loaded before Toolbar plugin."),void 0;var o=window.Clipboard||void 0;/(native code)/.test(o.toString())&&(o=void 0),o||"function"!=typeof require||(o=require("clipboard"));var t=[];if(!o){var e=document.createElement("script"),n=document.querySelector("head");e.onload=function(){if(o=window.Clipboard)for(;t.length;)t.pop()()},e.src="https://cdnjs.cloudflare.com/ajax/libs/clipboard.js/1.5.8/clipboard.min.js",n.appendChild(e)}Prism.plugins.toolbar.registerButton("copy-to-clipboard",function(e){function n(){var t=new o(i,{text:function(){return e.code}});t.on("success",function(){i.textContent="Copied!",r()}),t.on("error",function(){i.textContent="Press Ctrl+C to copy",r()})}function r(){setTimeout(function(){i.textContent="Copy"},5e3)}var i=document.createElement("a");return i.textContent="Copy",o?n():t.push(n),i})}}(); diff --git a/src/main/resources/resources/vendors/pygments/github.css b/src/main/resources/resources/vendors/pygments/github.css new file mode 100644 index 0000000..dc60655 --- /dev/null +++ b/src/main/resources/resources/vendors/pygments/github.css @@ -0,0 +1,61 @@ +.hll { background-color: #ffffcc } +.c { color: #999988; font-style: italic } /* Comment */ +.err { color: #a61717; background-color: #e3d2d2 } /* Error */ +.k { color: #000000; font-weight: bold } /* Keyword */ +.o { color: #000000; font-weight: bold } /* Operator */ +.cm { color: #999988; font-style: italic } /* Comment.Multiline */ +.cp { color: #999999; font-weight: bold; font-style: italic } /* Comment.Preproc */ +.c1 { color: #999988; font-style: italic } /* Comment.Single */ +.cs { color: #999999; font-weight: bold; font-style: italic } /* Comment.Special */ +.gd { color: #000000; background-color: #ffdddd } /* Generic.Deleted */ +.ge { color: #000000; font-style: italic } /* Generic.Emph */ +.gr { color: #aa0000 } /* Generic.Error */ +.gh { color: #999999 } /* Generic.Heading */ +.gi { color: #000000; background-color: #ddffdd } /* Generic.Inserted */ +.go { color: #888888 } /* Generic.Output */ +.gp { color: #555555 } /* Generic.Prompt */ +.gs { font-weight: bold } /* Generic.Strong */ +.gu { color: #aaaaaa } /* Generic.Subheading */ +.gt { color: #aa0000 } /* Generic.Traceback */ +.kc { color: #000000; font-weight: bold } /* Keyword.Constant */ +.kd { color: #000000; font-weight: bold } /* Keyword.Declaration */ +.kn { color: #000000; font-weight: bold } /* Keyword.Namespace */ +.kp { color: #000000; font-weight: bold } /* Keyword.Pseudo */ +.kr { color: #000000; font-weight: bold } /* Keyword.Reserved */ +.kt { color: #445588; font-weight: bold } /* Keyword.Type */ +.m { color: #009999 } /* Literal.Number */ +.s { color: #d01040 } /* Literal.String */ +.na { color: #008080 } /* Name.Attribute */ +.nb { color: #0086B3 } /* Name.Builtin */ +.nc { color: #445588; font-weight: bold } /* Name.Class */ +.no { color: #008080 } /* Name.Constant */ +.nd { color: #3c5d5d; font-weight: bold } /* Name.Decorator */ +.ni { color: #800080 } /* Name.Entity */ +.ne { color: #990000; font-weight: bold } /* Name.Exception */ +.nf { color: #990000; font-weight: bold } /* Name.Function */ +.nl { color: #990000; font-weight: bold } /* Name.Label */ +.nn { color: #555555 } /* Name.Namespace */ +.nt { color: #000080 } /* Name.Tag */ +.nv { color: #008080 } /* Name.Variable */ +.ow { color: #000000; font-weight: bold } /* Operator.Word */ +.w { color: #bbbbbb } /* Text.Whitespace */ +.mf { color: #009999 } /* Literal.Number.Float */ +.mh { color: #009999 } /* Literal.Number.Hex */ +.mi { color: #009999 } /* Literal.Number.Integer */ +.mo { color: #009999 } /* Literal.Number.Oct */ +.sb { color: #d01040 } /* Literal.String.Backtick */ +.sc { color: #d01040 } /* Literal.String.Char */ +.sd { color: #d01040 } /* Literal.String.Doc */ +.s2 { color: #d01040 } /* Literal.String.Double */ +.se { color: #d01040 } /* Literal.String.Escape */ +.sh { color: #d01040 } /* Literal.String.Heredoc */ +.si { color: #d01040 } /* Literal.String.Interpol */ +.sx { color: #d01040 } /* Literal.String.Other */ +.sr { color: #009926 } /* Literal.String.Regex */ +.s1 { color: #d01040 } /* Literal.String.Single */ +.ss { color: #990073 } /* Literal.String.Symbol */ +.bp { color: #999999 } /* Name.Builtin.Pseudo */ +.vc { color: #008080 } /* Name.Variable.Class */ +.vg { color: #008080 } /* Name.Variable.Global */ +.vi { color: #008080 } /* Name.Variable.Instance */ +.il { color: #009999 } /* Literal.Number.Integer.Long */ diff --git a/src/main/resources/resources/vendors/pygments/monokai.css b/src/main/resources/resources/vendors/pygments/monokai.css new file mode 100644 index 0000000..6121071 --- /dev/null +++ b/src/main/resources/resources/vendors/pygments/monokai.css @@ -0,0 +1,64 @@ +.codehilite .hll { background-color: #49483e } +.codehilite .c { color: #75715e } /* Comment */ +.codehilite .err { color: #960050; background-color: #1e0010 } /* Error */ +.codehilite .k { color: #66d9ef } /* Keyword */ +.codehilite .l { color: #ae81ff } /* Literal */ +.codehilite .n { color: #f8f8f2 } /* Name */ +.codehilite .o { color: #f92672 } /* Operator */ +.codehilite .p { color: #f8f8f2 } /* Punctuation */ +.codehilite .cm { color: #75715e } /* Comment.Multiline */ +.codehilite .cp { color: #75715e } /* Comment.Preproc */ +.codehilite .c1 { color: #75715e } /* Comment.Single */ +.codehilite .cs { color: #75715e } /* Comment.Special */ +.codehilite .ge { font-style: italic } /* Generic.Emph */ +.codehilite .gs { font-weight: bold } /* Generic.Strong */ +.codehilite .kc { color: #66d9ef } /* Keyword.Constant */ +.codehilite .kd { color: #66d9ef } /* Keyword.Declaration */ +.codehilite .kn { color: #f92672 } /* Keyword.Namespace */ +.codehilite .kp { color: #66d9ef } /* Keyword.Pseudo */ +.codehilite .kr { color: #66d9ef } /* Keyword.Reserved */ +.codehilite .kt { color: #66d9ef } /* Keyword.Type */ +.codehilite .ld { color: #e6db74 } /* Literal.Date */ +.codehilite .m { color: #ae81ff } /* Literal.Number */ +.codehilite .s { color: #e6db74 } /* Literal.String */ +.codehilite .na { color: #a6e22e } /* Name.Attribute */ +.codehilite .nb { color: #f8f8f2 } /* Name.Builtin */ +.codehilite .nc { color: #a6e22e } /* Name.Class */ +.codehilite .no { color: #66d9ef } /* Name.Constant */ +.codehilite .nd { color: #a6e22e } /* Name.Decorator */ +.codehilite .ni { color: #f8f8f2 } /* Name.Entity */ +.codehilite .ne { color: #a6e22e } /* Name.Exception */ +.codehilite .nf { color: #a6e22e } /* Name.Function */ +.codehilite .nl { color: #f8f8f2 } /* Name.Label */ +.codehilite .nn { color: #f8f8f2 } /* Name.Namespace */ +.codehilite .nx { color: #a6e22e } /* Name.Other */ +.codehilite .py { color: #f8f8f2 } /* Name.Property */ +.codehilite .nt { color: #f92672 } /* Name.Tag */ +.codehilite .nv { color: #f8f8f2 } /* Name.Variable */ +.codehilite .ow { color: #f92672 } /* Operator.Word */ +.codehilite .w { color: #f8f8f2 } /* Text.Whitespace */ +.codehilite .mf { color: #ae81ff } /* Literal.Number.Float */ +.codehilite .mh { color: #ae81ff } /* Literal.Number.Hex */ +.codehilite .mi { color: #ae81ff } /* Literal.Number.Integer */ +.codehilite .mo { color: #ae81ff } /* Literal.Number.Oct */ +.codehilite .sb { color: #e6db74 } /* Literal.String.Backtick */ +.codehilite .sc { color: #e6db74 } /* Literal.String.Char */ +.codehilite .sd { color: #e6db74 } /* Literal.String.Doc */ +.codehilite .s2 { color: #e6db74 } /* Literal.String.Double */ +.codehilite .se { color: #ae81ff } /* Literal.String.Escape */ +.codehilite .sh { color: #e6db74 } /* Literal.String.Heredoc */ +.codehilite .si { color: #e6db74 } /* Literal.String.Interpol */ +.codehilite .sx { color: #e6db74 } /* Literal.String.Other */ +.codehilite .sr { color: #e6db74 } /* Literal.String.Regex */ +.codehilite .s1 { color: #e6db74 } /* Literal.String.Single */ +.codehilite .ss { color: #e6db74 } /* Literal.String.Symbol */ +.codehilite .bp { color: #f8f8f2 } /* Name.Builtin.Pseudo */ +.codehilite .vc { color: #f8f8f2 } /* Name.Variable.Class */ +.codehilite .vg { color: #f8f8f2 } /* Name.Variable.Global */ +.codehilite .vi { color: #f8f8f2 } /* Name.Variable.Instance */ +.codehilite .il { color: #ae81ff } /* Literal.Number.Integer.Long */ + +.codehilite .gh { } /* Generic Heading & Diff Header */ +.codehilite .gu { color: #75715e; } /* Generic.Subheading & Diff Unified/Comment? */ +.codehilite .gd { color: #f92672; } /* Generic.Deleted & Diff Deleted */ +.codehilite .gi { color: #a6e22e; } /* Generic.Inserted & Diff Inserted */ diff --git a/src/main/resources/resources/vendors/simditor-2.3.6/images/image.png b/src/main/resources/resources/vendors/simditor-2.3.6/images/image.png new file mode 100644 index 0000000000000000000000000000000000000000..2dc58f9618cec91005dff867976d358e6ccf57dd GIT binary patch literal 10706 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[b],f[b]=this.aliases[d]||d;return e=f.pop(),f.sort().push(e),f.join("_")},c.prototype.opts={el:document},c.prototype._init=function(){return this.id=++this.constructor.count,this._map={},this._delegate="string"==typeof this.opts.el?document:this.opts.el,a(this._delegate).on("keydown.simple-hotkeys-"+this.id,this.opts.el,function(a){return function(b){var c;return null!=(c=a._getHander(b))?c.call(a,b):void 0}}(this))},c.prototype._getHander=function(a){var b,c;if(b=this.constructor.keyNameMap[a.which])return c="",a.altKey&&(c+="alt_"),a.ctrlKey&&(c+="control_"),a.metaKey&&(c+="meta_"),a.shiftKey&&(c+="shift_"),c+=b.toLowerCase(),this._map[c]},c.prototype.respondTo=function(a){return"string"==typeof a?null!=this._map[this.constructor.normalize(a)]:null!=this._getHander(a)},c.prototype.add=function(a,b){return this._map[this.constructor.normalize(a)]=b,this},c.prototype.remove=function(a){return delete this._map[this.constructor.normalize(a)],this},c.prototype.destroy=function(){return a(this._delegate).off(".simple-hotkeys-"+this.id),this._map={},this},c}(b),d=function(a){return new c(a)}}); \ No newline at end of file diff --git a/src/main/resources/resources/vendors/simditor-2.3.6/scripts/jquery.min.js b/src/main/resources/resources/vendors/simditor-2.3.6/scripts/jquery.min.js new file mode 100644 index 0000000..fad9ab1 --- /dev/null +++ b/src/main/resources/resources/vendors/simditor-2.3.6/scripts/jquery.min.js @@ -0,0 +1,5 @@ +/*! jQuery v2.1.4 | (c) 2005, 2015 jQuery Foundation, Inc. | jquery.org/license */ +!function(a,b){"object"==typeof module&&"object"==typeof module.exports?module.exports=a.document?b(a,!0):function(a){if(!a.document)throw new Error("jQuery requires a window with a document");return b(a)}:b(a)}("undefined"!=typeof window?window:this,function(a,b){var c=[],d=c.slice,e=c.concat,f=c.push,g=c.indexOf,h={},i=h.toString,j=h.hasOwnProperty,k={},l=a.document,m="2.1.4",n=function(a,b){return new n.fn.init(a,b)},o=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,p=/^-ms-/,q=/-([\da-z])/gi,r=function(a,b){return b.toUpperCase()};n.fn=n.prototype={jquery:m,constructor:n,selector:"",length:0,toArray:function(){return d.call(this)},get:function(a){return null!=a?0>a?this[a+this.length]:this[a]:d.call(this)},pushStack:function(a){var b=n.merge(this.constructor(),a);return b.prevObject=this,b.context=this.context,b},each:function(a,b){return n.each(this,a,b)},map:function(a){return this.pushStack(n.map(this,function(b,c){return a.call(b,c,b)}))},slice:function(){return this.pushStack(d.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},eq:function(a){var b=this.length,c=+a+(0>a?b:0);return this.pushStack(c>=0&&b>c?[this[c]]:[])},end:function(){return this.prevObject||this.constructor(null)},push:f,sort:c.sort,splice:c.splice},n.extend=n.fn.extend=function(){var a,b,c,d,e,f,g=arguments[0]||{},h=1,i=arguments.length,j=!1;for("boolean"==typeof g&&(j=g,g=arguments[h]||{},h++),"object"==typeof g||n.isFunction(g)||(g={}),h===i&&(g=this,h--);i>h;h++)if(null!=(a=arguments[h]))for(b in a)c=g[b],d=a[b],g!==d&&(j&&d&&(n.isPlainObject(d)||(e=n.isArray(d)))?(e?(e=!1,f=c&&n.isArray(c)?c:[]):f=c&&n.isPlainObject(c)?c:{},g[b]=n.extend(j,f,d)):void 0!==d&&(g[b]=d));return g},n.extend({expando:"jQuery"+(m+Math.random()).replace(/\D/g,""),isReady:!0,error:function(a){throw new Error(a)},noop:function(){},isFunction:function(a){return"function"===n.type(a)},isArray:Array.isArray,isWindow:function(a){return null!=a&&a===a.window},isNumeric:function(a){return!n.isArray(a)&&a-parseFloat(a)+1>=0},isPlainObject:function(a){return"object"!==n.type(a)||a.nodeType||n.isWindow(a)?!1:a.constructor&&!j.call(a.constructor.prototype,"isPrototypeOf")?!1:!0},isEmptyObject:function(a){var b;for(b in a)return!1;return!0},type:function(a){return null==a?a+"":"object"==typeof a||"function"==typeof a?h[i.call(a)]||"object":typeof a},globalEval:function(a){var b,c=eval;a=n.trim(a),a&&(1===a.indexOf("use strict")?(b=l.createElement("script"),b.text=a,l.head.appendChild(b).parentNode.removeChild(b)):c(a))},camelCase:function(a){return a.replace(p,"ms-").replace(q,r)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toLowerCase()===b.toLowerCase()},each:function(a,b,c){var d,e=0,f=a.length,g=s(a);if(c){if(g){for(;f>e;e++)if(d=b.apply(a[e],c),d===!1)break}else for(e in a)if(d=b.apply(a[e],c),d===!1)break}else if(g){for(;f>e;e++)if(d=b.call(a[e],e,a[e]),d===!1)break}else for(e in a)if(d=b.call(a[e],e,a[e]),d===!1)break;return a},trim:function(a){return null==a?"":(a+"").replace(o,"")},makeArray:function(a,b){var c=b||[];return null!=a&&(s(Object(a))?n.merge(c,"string"==typeof a?[a]:a):f.call(c,a)),c},inArray:function(a,b,c){return null==b?-1:g.call(b,a,c)},merge:function(a,b){for(var c=+b.length,d=0,e=a.length;c>d;d++)a[e++]=b[d];return a.length=e,a},grep:function(a,b,c){for(var d,e=[],f=0,g=a.length,h=!c;g>f;f++)d=!b(a[f],f),d!==h&&e.push(a[f]);return e},map:function(a,b,c){var d,f=0,g=a.length,h=s(a),i=[];if(h)for(;g>f;f++)d=b(a[f],f,c),null!=d&&i.push(d);else for(f in a)d=b(a[f],f,c),null!=d&&i.push(d);return e.apply([],i)},guid:1,proxy:function(a,b){var c,e,f;return"string"==typeof b&&(c=a[b],b=a,a=c),n.isFunction(a)?(e=d.call(arguments,2),f=function(){return a.apply(b||this,e.concat(d.call(arguments)))},f.guid=a.guid=a.guid||n.guid++,f):void 0},now:Date.now,support:k}),n.each("Boolean Number String Function Array Date RegExp Object Error".split(" "),function(a,b){h["[object "+b+"]"]=b.toLowerCase()});function s(a){var b="length"in a&&a.length,c=n.type(a);return"function"===c||n.isWindow(a)?!1:1===a.nodeType&&b?!0:"array"===c||0===b||"number"==typeof b&&b>0&&b-1 in a}var t=function(a){var b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u="sizzle"+1*new Date,v=a.document,w=0,x=0,y=ha(),z=ha(),A=ha(),B=function(a,b){return a===b&&(l=!0),0},C=1<<31,D={}.hasOwnProperty,E=[],F=E.pop,G=E.push,H=E.push,I=E.slice,J=function(a,b){for(var c=0,d=a.length;d>c;c++)if(a[c]===b)return c;return-1},K="checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",L="[\\x20\\t\\r\\n\\f]",M="(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+",N=M.replace("w","w#"),O="\\["+L+"*("+M+")(?:"+L+"*([*^$|!~]?=)"+L+"*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|("+N+"))|)"+L+"*\\]",P=":("+M+")(?:\\((('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|((?:\\\\.|[^\\\\()[\\]]|"+O+")*)|.*)\\)|)",Q=new RegExp(L+"+","g"),R=new RegExp("^"+L+"+|((?:^|[^\\\\])(?:\\\\.)*)"+L+"+$","g"),S=new RegExp("^"+L+"*,"+L+"*"),T=new RegExp("^"+L+"*([>+~]|"+L+")"+L+"*"),U=new RegExp("="+L+"*([^\\]'\"]*?)"+L+"*\\]","g"),V=new RegExp(P),W=new RegExp("^"+N+"$"),X={ID:new RegExp("^#("+M+")"),CLASS:new RegExp("^\\.("+M+")"),TAG:new RegExp("^("+M.replace("w","w*")+")"),ATTR:new RegExp("^"+O),PSEUDO:new RegExp("^"+P),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+L+"*(even|odd|(([+-]|)(\\d*)n|)"+L+"*(?:([+-]|)"+L+"*(\\d+)|))"+L+"*\\)|)","i"),bool:new RegExp("^(?:"+K+")$","i"),needsContext:new RegExp("^"+L+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+L+"*((?:-\\d)?\\d*)"+L+"*\\)|)(?=[^-]|$)","i")},Y=/^(?:input|select|textarea|button)$/i,Z=/^h\d$/i,$=/^[^{]+\{\s*\[native \w/,_=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,aa=/[+~]/,ba=/'|\\/g,ca=new RegExp("\\\\([\\da-f]{1,6}"+L+"?|("+L+")|.)","ig"),da=function(a,b,c){var d="0x"+b-65536;return d!==d||c?b:0>d?String.fromCharCode(d+65536):String.fromCharCode(d>>10|55296,1023&d|56320)},ea=function(){m()};try{H.apply(E=I.call(v.childNodes),v.childNodes),E[v.childNodes.length].nodeType}catch(fa){H={apply:E.length?function(a,b){G.apply(a,I.call(b))}:function(a,b){var c=a.length,d=0;while(a[c++]=b[d++]);a.length=c-1}}}function ga(a,b,d,e){var f,h,j,k,l,o,r,s,w,x;if((b?b.ownerDocument||b:v)!==n&&m(b),b=b||n,d=d||[],k=b.nodeType,"string"!=typeof a||!a||1!==k&&9!==k&&11!==k)return d;if(!e&&p){if(11!==k&&(f=_.exec(a)))if(j=f[1]){if(9===k){if(h=b.getElementById(j),!h||!h.parentNode)return d;if(h.id===j)return d.push(h),d}else if(b.ownerDocument&&(h=b.ownerDocument.getElementById(j))&&t(b,h)&&h.id===j)return d.push(h),d}else{if(f[2])return H.apply(d,b.getElementsByTagName(a)),d;if((j=f[3])&&c.getElementsByClassName)return H.apply(d,b.getElementsByClassName(j)),d}if(c.qsa&&(!q||!q.test(a))){if(s=r=u,w=b,x=1!==k&&a,1===k&&"object"!==b.nodeName.toLowerCase()){o=g(a),(r=b.getAttribute("id"))?s=r.replace(ba,"\\$&"):b.setAttribute("id",s),s="[id='"+s+"'] ",l=o.length;while(l--)o[l]=s+ra(o[l]);w=aa.test(a)&&pa(b.parentNode)||b,x=o.join(",")}if(x)try{return H.apply(d,w.querySelectorAll(x)),d}catch(y){}finally{r||b.removeAttribute("id")}}}return i(a.replace(R,"$1"),b,d,e)}function ha(){var a=[];function b(c,e){return a.push(c+" ")>d.cacheLength&&delete b[a.shift()],b[c+" "]=e}return b}function ia(a){return a[u]=!0,a}function ja(a){var b=n.createElement("div");try{return!!a(b)}catch(c){return!1}finally{b.parentNode&&b.parentNode.removeChild(b),b=null}}function ka(a,b){var c=a.split("|"),e=a.length;while(e--)d.attrHandle[c[e]]=b}function la(a,b){var c=b&&a,d=c&&1===a.nodeType&&1===b.nodeType&&(~b.sourceIndex||C)-(~a.sourceIndex||C);if(d)return d;if(c)while(c=c.nextSibling)if(c===b)return-1;return a?1:-1}function ma(a){return function(b){var c=b.nodeName.toLowerCase();return"input"===c&&b.type===a}}function na(a){return function(b){var c=b.nodeName.toLowerCase();return("input"===c||"button"===c)&&b.type===a}}function oa(a){return ia(function(b){return b=+b,ia(function(c,d){var e,f=a([],c.length,b),g=f.length;while(g--)c[e=f[g]]&&(c[e]=!(d[e]=c[e]))})})}function pa(a){return a&&"undefined"!=typeof a.getElementsByTagName&&a}c=ga.support={},f=ga.isXML=function(a){var b=a&&(a.ownerDocument||a).documentElement;return b?"HTML"!==b.nodeName:!1},m=ga.setDocument=function(a){var b,e,g=a?a.ownerDocument||a:v;return g!==n&&9===g.nodeType&&g.documentElement?(n=g,o=g.documentElement,e=g.defaultView,e&&e!==e.top&&(e.addEventListener?e.addEventListener("unload",ea,!1):e.attachEvent&&e.attachEvent("onunload",ea)),p=!f(g),c.attributes=ja(function(a){return a.className="i",!a.getAttribute("className")}),c.getElementsByTagName=ja(function(a){return a.appendChild(g.createComment("")),!a.getElementsByTagName("*").length}),c.getElementsByClassName=$.test(g.getElementsByClassName),c.getById=ja(function(a){return o.appendChild(a).id=u,!g.getElementsByName||!g.getElementsByName(u).length}),c.getById?(d.find.ID=function(a,b){if("undefined"!=typeof b.getElementById&&p){var c=b.getElementById(a);return c&&c.parentNode?[c]:[]}},d.filter.ID=function(a){var b=a.replace(ca,da);return function(a){return a.getAttribute("id")===b}}):(delete d.find.ID,d.filter.ID=function(a){var b=a.replace(ca,da);return function(a){var c="undefined"!=typeof a.getAttributeNode&&a.getAttributeNode("id");return c&&c.value===b}}),d.find.TAG=c.getElementsByTagName?function(a,b){return"undefined"!=typeof b.getElementsByTagName?b.getElementsByTagName(a):c.qsa?b.querySelectorAll(a):void 0}:function(a,b){var c,d=[],e=0,f=b.getElementsByTagName(a);if("*"===a){while(c=f[e++])1===c.nodeType&&d.push(c);return d}return f},d.find.CLASS=c.getElementsByClassName&&function(a,b){return p?b.getElementsByClassName(a):void 0},r=[],q=[],(c.qsa=$.test(g.querySelectorAll))&&(ja(function(a){o.appendChild(a).innerHTML="",a.querySelectorAll("[msallowcapture^='']").length&&q.push("[*^$]="+L+"*(?:''|\"\")"),a.querySelectorAll("[selected]").length||q.push("\\["+L+"*(?:value|"+K+")"),a.querySelectorAll("[id~="+u+"-]").length||q.push("~="),a.querySelectorAll(":checked").length||q.push(":checked"),a.querySelectorAll("a#"+u+"+*").length||q.push(".#.+[+~]")}),ja(function(a){var b=g.createElement("input");b.setAttribute("type","hidden"),a.appendChild(b).setAttribute("name","D"),a.querySelectorAll("[name=d]").length&&q.push("name"+L+"*[*^$|!~]?="),a.querySelectorAll(":enabled").length||q.push(":enabled",":disabled"),a.querySelectorAll("*,:x"),q.push(",.*:")})),(c.matchesSelector=$.test(s=o.matches||o.webkitMatchesSelector||o.mozMatchesSelector||o.oMatchesSelector||o.msMatchesSelector))&&ja(function(a){c.disconnectedMatch=s.call(a,"div"),s.call(a,"[s!='']:x"),r.push("!=",P)}),q=q.length&&new RegExp(q.join("|")),r=r.length&&new RegExp(r.join("|")),b=$.test(o.compareDocumentPosition),t=b||$.test(o.contains)?function(a,b){var c=9===a.nodeType?a.documentElement:a,d=b&&b.parentNode;return a===d||!(!d||1!==d.nodeType||!(c.contains?c.contains(d):a.compareDocumentPosition&&16&a.compareDocumentPosition(d)))}:function(a,b){if(b)while(b=b.parentNode)if(b===a)return!0;return!1},B=b?function(a,b){if(a===b)return l=!0,0;var d=!a.compareDocumentPosition-!b.compareDocumentPosition;return d?d:(d=(a.ownerDocument||a)===(b.ownerDocument||b)?a.compareDocumentPosition(b):1,1&d||!c.sortDetached&&b.compareDocumentPosition(a)===d?a===g||a.ownerDocument===v&&t(v,a)?-1:b===g||b.ownerDocument===v&&t(v,b)?1:k?J(k,a)-J(k,b):0:4&d?-1:1)}:function(a,b){if(a===b)return l=!0,0;var c,d=0,e=a.parentNode,f=b.parentNode,h=[a],i=[b];if(!e||!f)return a===g?-1:b===g?1:e?-1:f?1:k?J(k,a)-J(k,b):0;if(e===f)return la(a,b);c=a;while(c=c.parentNode)h.unshift(c);c=b;while(c=c.parentNode)i.unshift(c);while(h[d]===i[d])d++;return d?la(h[d],i[d]):h[d]===v?-1:i[d]===v?1:0},g):n},ga.matches=function(a,b){return ga(a,null,null,b)},ga.matchesSelector=function(a,b){if((a.ownerDocument||a)!==n&&m(a),b=b.replace(U,"='$1']"),!(!c.matchesSelector||!p||r&&r.test(b)||q&&q.test(b)))try{var d=s.call(a,b);if(d||c.disconnectedMatch||a.document&&11!==a.document.nodeType)return d}catch(e){}return ga(b,n,null,[a]).length>0},ga.contains=function(a,b){return(a.ownerDocument||a)!==n&&m(a),t(a,b)},ga.attr=function(a,b){(a.ownerDocument||a)!==n&&m(a);var e=d.attrHandle[b.toLowerCase()],f=e&&D.call(d.attrHandle,b.toLowerCase())?e(a,b,!p):void 0;return void 0!==f?f:c.attributes||!p?a.getAttribute(b):(f=a.getAttributeNode(b))&&f.specified?f.value:null},ga.error=function(a){throw new Error("Syntax error, unrecognized expression: "+a)},ga.uniqueSort=function(a){var b,d=[],e=0,f=0;if(l=!c.detectDuplicates,k=!c.sortStable&&a.slice(0),a.sort(B),l){while(b=a[f++])b===a[f]&&(e=d.push(f));while(e--)a.splice(d[e],1)}return k=null,a},e=ga.getText=function(a){var b,c="",d=0,f=a.nodeType;if(f){if(1===f||9===f||11===f){if("string"==typeof a.textContent)return a.textContent;for(a=a.firstChild;a;a=a.nextSibling)c+=e(a)}else if(3===f||4===f)return a.nodeValue}else while(b=a[d++])c+=e(b);return c},d=ga.selectors={cacheLength:50,createPseudo:ia,match:X,attrHandle:{},find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(a){return a[1]=a[1].replace(ca,da),a[3]=(a[3]||a[4]||a[5]||"").replace(ca,da),"~="===a[2]&&(a[3]=" "+a[3]+" "),a.slice(0,4)},CHILD:function(a){return a[1]=a[1].toLowerCase(),"nth"===a[1].slice(0,3)?(a[3]||ga.error(a[0]),a[4]=+(a[4]?a[5]+(a[6]||1):2*("even"===a[3]||"odd"===a[3])),a[5]=+(a[7]+a[8]||"odd"===a[3])):a[3]&&ga.error(a[0]),a},PSEUDO:function(a){var b,c=!a[6]&&a[2];return X.CHILD.test(a[0])?null:(a[3]?a[2]=a[4]||a[5]||"":c&&V.test(c)&&(b=g(c,!0))&&(b=c.indexOf(")",c.length-b)-c.length)&&(a[0]=a[0].slice(0,b),a[2]=c.slice(0,b)),a.slice(0,3))}},filter:{TAG:function(a){var b=a.replace(ca,da).toLowerCase();return"*"===a?function(){return!0}:function(a){return a.nodeName&&a.nodeName.toLowerCase()===b}},CLASS:function(a){var b=y[a+" "];return b||(b=new RegExp("(^|"+L+")"+a+"("+L+"|$)"))&&y(a,function(a){return b.test("string"==typeof a.className&&a.className||"undefined"!=typeof a.getAttribute&&a.getAttribute("class")||"")})},ATTR:function(a,b,c){return function(d){var e=ga.attr(d,a);return null==e?"!="===b:b?(e+="","="===b?e===c:"!="===b?e!==c:"^="===b?c&&0===e.indexOf(c):"*="===b?c&&e.indexOf(c)>-1:"$="===b?c&&e.slice(-c.length)===c:"~="===b?(" "+e.replace(Q," ")+" ").indexOf(c)>-1:"|="===b?e===c||e.slice(0,c.length+1)===c+"-":!1):!0}},CHILD:function(a,b,c,d,e){var f="nth"!==a.slice(0,3),g="last"!==a.slice(-4),h="of-type"===b;return 1===d&&0===e?function(a){return!!a.parentNode}:function(b,c,i){var j,k,l,m,n,o,p=f!==g?"nextSibling":"previousSibling",q=b.parentNode,r=h&&b.nodeName.toLowerCase(),s=!i&&!h;if(q){if(f){while(p){l=b;while(l=l[p])if(h?l.nodeName.toLowerCase()===r:1===l.nodeType)return!1;o=p="only"===a&&!o&&"nextSibling"}return!0}if(o=[g?q.firstChild:q.lastChild],g&&s){k=q[u]||(q[u]={}),j=k[a]||[],n=j[0]===w&&j[1],m=j[0]===w&&j[2],l=n&&q.childNodes[n];while(l=++n&&l&&l[p]||(m=n=0)||o.pop())if(1===l.nodeType&&++m&&l===b){k[a]=[w,n,m];break}}else if(s&&(j=(b[u]||(b[u]={}))[a])&&j[0]===w)m=j[1];else while(l=++n&&l&&l[p]||(m=n=0)||o.pop())if((h?l.nodeName.toLowerCase()===r:1===l.nodeType)&&++m&&(s&&((l[u]||(l[u]={}))[a]=[w,m]),l===b))break;return m-=e,m===d||m%d===0&&m/d>=0}}},PSEUDO:function(a,b){var c,e=d.pseudos[a]||d.setFilters[a.toLowerCase()]||ga.error("unsupported pseudo: "+a);return e[u]?e(b):e.length>1?(c=[a,a,"",b],d.setFilters.hasOwnProperty(a.toLowerCase())?ia(function(a,c){var d,f=e(a,b),g=f.length;while(g--)d=J(a,f[g]),a[d]=!(c[d]=f[g])}):function(a){return e(a,0,c)}):e}},pseudos:{not:ia(function(a){var b=[],c=[],d=h(a.replace(R,"$1"));return d[u]?ia(function(a,b,c,e){var f,g=d(a,null,e,[]),h=a.length;while(h--)(f=g[h])&&(a[h]=!(b[h]=f))}):function(a,e,f){return b[0]=a,d(b,null,f,c),b[0]=null,!c.pop()}}),has:ia(function(a){return function(b){return ga(a,b).length>0}}),contains:ia(function(a){return a=a.replace(ca,da),function(b){return(b.textContent||b.innerText||e(b)).indexOf(a)>-1}}),lang:ia(function(a){return W.test(a||"")||ga.error("unsupported lang: "+a),a=a.replace(ca,da).toLowerCase(),function(b){var c;do if(c=p?b.lang:b.getAttribute("xml:lang")||b.getAttribute("lang"))return c=c.toLowerCase(),c===a||0===c.indexOf(a+"-");while((b=b.parentNode)&&1===b.nodeType);return!1}}),target:function(b){var c=a.location&&a.location.hash;return c&&c.slice(1)===b.id},root:function(a){return a===o},focus:function(a){return a===n.activeElement&&(!n.hasFocus||n.hasFocus())&&!!(a.type||a.href||~a.tabIndex)},enabled:function(a){return a.disabled===!1},disabled:function(a){return a.disabled===!0},checked:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&!!a.checked||"option"===b&&!!a.selected},selected:function(a){return a.parentNode&&a.parentNode.selectedIndex,a.selected===!0},empty:function(a){for(a=a.firstChild;a;a=a.nextSibling)if(a.nodeType<6)return!1;return!0},parent:function(a){return!d.pseudos.empty(a)},header:function(a){return Z.test(a.nodeName)},input:function(a){return Y.test(a.nodeName)},button:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&"button"===a.type||"button"===b},text:function(a){var b;return"input"===a.nodeName.toLowerCase()&&"text"===a.type&&(null==(b=a.getAttribute("type"))||"text"===b.toLowerCase())},first:oa(function(){return[0]}),last:oa(function(a,b){return[b-1]}),eq:oa(function(a,b,c){return[0>c?c+b:c]}),even:oa(function(a,b){for(var c=0;b>c;c+=2)a.push(c);return a}),odd:oa(function(a,b){for(var c=1;b>c;c+=2)a.push(c);return a}),lt:oa(function(a,b,c){for(var d=0>c?c+b:c;--d>=0;)a.push(d);return a}),gt:oa(function(a,b,c){for(var d=0>c?c+b:c;++db;b++)d+=a[b].value;return d}function sa(a,b,c){var d=b.dir,e=c&&"parentNode"===d,f=x++;return b.first?function(b,c,f){while(b=b[d])if(1===b.nodeType||e)return a(b,c,f)}:function(b,c,g){var h,i,j=[w,f];if(g){while(b=b[d])if((1===b.nodeType||e)&&a(b,c,g))return!0}else while(b=b[d])if(1===b.nodeType||e){if(i=b[u]||(b[u]={}),(h=i[d])&&h[0]===w&&h[1]===f)return j[2]=h[2];if(i[d]=j,j[2]=a(b,c,g))return!0}}}function ta(a){return a.length>1?function(b,c,d){var e=a.length;while(e--)if(!a[e](b,c,d))return!1;return!0}:a[0]}function ua(a,b,c){for(var d=0,e=b.length;e>d;d++)ga(a,b[d],c);return c}function va(a,b,c,d,e){for(var f,g=[],h=0,i=a.length,j=null!=b;i>h;h++)(f=a[h])&&(!c||c(f,d,e))&&(g.push(f),j&&b.push(h));return g}function wa(a,b,c,d,e,f){return d&&!d[u]&&(d=wa(d)),e&&!e[u]&&(e=wa(e,f)),ia(function(f,g,h,i){var j,k,l,m=[],n=[],o=g.length,p=f||ua(b||"*",h.nodeType?[h]:h,[]),q=!a||!f&&b?p:va(p,m,a,h,i),r=c?e||(f?a:o||d)?[]:g:q;if(c&&c(q,r,h,i),d){j=va(r,n),d(j,[],h,i),k=j.length;while(k--)(l=j[k])&&(r[n[k]]=!(q[n[k]]=l))}if(f){if(e||a){if(e){j=[],k=r.length;while(k--)(l=r[k])&&j.push(q[k]=l);e(null,r=[],j,i)}k=r.length;while(k--)(l=r[k])&&(j=e?J(f,l):m[k])>-1&&(f[j]=!(g[j]=l))}}else r=va(r===g?r.splice(o,r.length):r),e?e(null,g,r,i):H.apply(g,r)})}function xa(a){for(var b,c,e,f=a.length,g=d.relative[a[0].type],h=g||d.relative[" "],i=g?1:0,k=sa(function(a){return a===b},h,!0),l=sa(function(a){return J(b,a)>-1},h,!0),m=[function(a,c,d){var e=!g&&(d||c!==j)||((b=c).nodeType?k(a,c,d):l(a,c,d));return b=null,e}];f>i;i++)if(c=d.relative[a[i].type])m=[sa(ta(m),c)];else{if(c=d.filter[a[i].type].apply(null,a[i].matches),c[u]){for(e=++i;f>e;e++)if(d.relative[a[e].type])break;return wa(i>1&&ta(m),i>1&&ra(a.slice(0,i-1).concat({value:" "===a[i-2].type?"*":""})).replace(R,"$1"),c,e>i&&xa(a.slice(i,e)),f>e&&xa(a=a.slice(e)),f>e&&ra(a))}m.push(c)}return ta(m)}function ya(a,b){var c=b.length>0,e=a.length>0,f=function(f,g,h,i,k){var l,m,o,p=0,q="0",r=f&&[],s=[],t=j,u=f||e&&d.find.TAG("*",k),v=w+=null==t?1:Math.random()||.1,x=u.length;for(k&&(j=g!==n&&g);q!==x&&null!=(l=u[q]);q++){if(e&&l){m=0;while(o=a[m++])if(o(l,g,h)){i.push(l);break}k&&(w=v)}c&&((l=!o&&l)&&p--,f&&r.push(l))}if(p+=q,c&&q!==p){m=0;while(o=b[m++])o(r,s,g,h);if(f){if(p>0)while(q--)r[q]||s[q]||(s[q]=F.call(i));s=va(s)}H.apply(i,s),k&&!f&&s.length>0&&p+b.length>1&&ga.uniqueSort(i)}return k&&(w=v,j=t),r};return c?ia(f):f}return h=ga.compile=function(a,b){var c,d=[],e=[],f=A[a+" "];if(!f){b||(b=g(a)),c=b.length;while(c--)f=xa(b[c]),f[u]?d.push(f):e.push(f);f=A(a,ya(e,d)),f.selector=a}return f},i=ga.select=function(a,b,e,f){var i,j,k,l,m,n="function"==typeof a&&a,o=!f&&g(a=n.selector||a);if(e=e||[],1===o.length){if(j=o[0]=o[0].slice(0),j.length>2&&"ID"===(k=j[0]).type&&c.getById&&9===b.nodeType&&p&&d.relative[j[1].type]){if(b=(d.find.ID(k.matches[0].replace(ca,da),b)||[])[0],!b)return e;n&&(b=b.parentNode),a=a.slice(j.shift().value.length)}i=X.needsContext.test(a)?0:j.length;while(i--){if(k=j[i],d.relative[l=k.type])break;if((m=d.find[l])&&(f=m(k.matches[0].replace(ca,da),aa.test(j[0].type)&&pa(b.parentNode)||b))){if(j.splice(i,1),a=f.length&&ra(j),!a)return H.apply(e,f),e;break}}}return(n||h(a,o))(f,b,!p,e,aa.test(a)&&pa(b.parentNode)||b),e},c.sortStable=u.split("").sort(B).join("")===u,c.detectDuplicates=!!l,m(),c.sortDetached=ja(function(a){return 1&a.compareDocumentPosition(n.createElement("div"))}),ja(function(a){return a.innerHTML="","#"===a.firstChild.getAttribute("href")})||ka("type|href|height|width",function(a,b,c){return c?void 0:a.getAttribute(b,"type"===b.toLowerCase()?1:2)}),c.attributes&&ja(function(a){return a.innerHTML="",a.firstChild.setAttribute("value",""),""===a.firstChild.getAttribute("value")})||ka("value",function(a,b,c){return c||"input"!==a.nodeName.toLowerCase()?void 0:a.defaultValue}),ja(function(a){return null==a.getAttribute("disabled")})||ka(K,function(a,b,c){var d;return c?void 0:a[b]===!0?b.toLowerCase():(d=a.getAttributeNode(b))&&d.specified?d.value:null}),ga}(a);n.find=t,n.expr=t.selectors,n.expr[":"]=n.expr.pseudos,n.unique=t.uniqueSort,n.text=t.getText,n.isXMLDoc=t.isXML,n.contains=t.contains;var u=n.expr.match.needsContext,v=/^<(\w+)\s*\/?>(?:<\/\1>|)$/,w=/^.[^:#\[\.,]*$/;function x(a,b,c){if(n.isFunction(b))return n.grep(a,function(a,d){return!!b.call(a,d,a)!==c});if(b.nodeType)return n.grep(a,function(a){return a===b!==c});if("string"==typeof b){if(w.test(b))return n.filter(b,a,c);b=n.filter(b,a)}return n.grep(a,function(a){return g.call(b,a)>=0!==c})}n.filter=function(a,b,c){var d=b[0];return c&&(a=":not("+a+")"),1===b.length&&1===d.nodeType?n.find.matchesSelector(d,a)?[d]:[]:n.find.matches(a,n.grep(b,function(a){return 1===a.nodeType}))},n.fn.extend({find:function(a){var b,c=this.length,d=[],e=this;if("string"!=typeof a)return this.pushStack(n(a).filter(function(){for(b=0;c>b;b++)if(n.contains(e[b],this))return!0}));for(b=0;c>b;b++)n.find(a,e[b],d);return d=this.pushStack(c>1?n.unique(d):d),d.selector=this.selector?this.selector+" "+a:a,d},filter:function(a){return this.pushStack(x(this,a||[],!1))},not:function(a){return this.pushStack(x(this,a||[],!0))},is:function(a){return!!x(this,"string"==typeof a&&u.test(a)?n(a):a||[],!1).length}});var y,z=/^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/,A=n.fn.init=function(a,b){var c,d;if(!a)return this;if("string"==typeof a){if(c="<"===a[0]&&">"===a[a.length-1]&&a.length>=3?[null,a,null]:z.exec(a),!c||!c[1]&&b)return!b||b.jquery?(b||y).find(a):this.constructor(b).find(a);if(c[1]){if(b=b instanceof n?b[0]:b,n.merge(this,n.parseHTML(c[1],b&&b.nodeType?b.ownerDocument||b:l,!0)),v.test(c[1])&&n.isPlainObject(b))for(c in b)n.isFunction(this[c])?this[c](b[c]):this.attr(c,b[c]);return this}return d=l.getElementById(c[2]),d&&d.parentNode&&(this.length=1,this[0]=d),this.context=l,this.selector=a,this}return a.nodeType?(this.context=this[0]=a,this.length=1,this):n.isFunction(a)?"undefined"!=typeof y.ready?y.ready(a):a(n):(void 0!==a.selector&&(this.selector=a.selector,this.context=a.context),n.makeArray(a,this))};A.prototype=n.fn,y=n(l);var B=/^(?:parents|prev(?:Until|All))/,C={children:!0,contents:!0,next:!0,prev:!0};n.extend({dir:function(a,b,c){var d=[],e=void 0!==c;while((a=a[b])&&9!==a.nodeType)if(1===a.nodeType){if(e&&n(a).is(c))break;d.push(a)}return d},sibling:function(a,b){for(var c=[];a;a=a.nextSibling)1===a.nodeType&&a!==b&&c.push(a);return c}}),n.fn.extend({has:function(a){var b=n(a,this),c=b.length;return this.filter(function(){for(var a=0;c>a;a++)if(n.contains(this,b[a]))return!0})},closest:function(a,b){for(var c,d=0,e=this.length,f=[],g=u.test(a)||"string"!=typeof a?n(a,b||this.context):0;e>d;d++)for(c=this[d];c&&c!==b;c=c.parentNode)if(c.nodeType<11&&(g?g.index(c)>-1:1===c.nodeType&&n.find.matchesSelector(c,a))){f.push(c);break}return this.pushStack(f.length>1?n.unique(f):f)},index:function(a){return a?"string"==typeof a?g.call(n(a),this[0]):g.call(this,a.jquery?a[0]:a):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(a,b){return this.pushStack(n.unique(n.merge(this.get(),n(a,b))))},addBack:function(a){return this.add(null==a?this.prevObject:this.prevObject.filter(a))}});function D(a,b){while((a=a[b])&&1!==a.nodeType);return a}n.each({parent:function(a){var b=a.parentNode;return b&&11!==b.nodeType?b:null},parents:function(a){return n.dir(a,"parentNode")},parentsUntil:function(a,b,c){return n.dir(a,"parentNode",c)},next:function(a){return D(a,"nextSibling")},prev:function(a){return D(a,"previousSibling")},nextAll:function(a){return n.dir(a,"nextSibling")},prevAll:function(a){return n.dir(a,"previousSibling")},nextUntil:function(a,b,c){return n.dir(a,"nextSibling",c)},prevUntil:function(a,b,c){return n.dir(a,"previousSibling",c)},siblings:function(a){return n.sibling((a.parentNode||{}).firstChild,a)},children:function(a){return n.sibling(a.firstChild)},contents:function(a){return a.contentDocument||n.merge([],a.childNodes)}},function(a,b){n.fn[a]=function(c,d){var e=n.map(this,b,c);return"Until"!==a.slice(-5)&&(d=c),d&&"string"==typeof d&&(e=n.filter(d,e)),this.length>1&&(C[a]||n.unique(e),B.test(a)&&e.reverse()),this.pushStack(e)}});var E=/\S+/g,F={};function G(a){var b=F[a]={};return n.each(a.match(E)||[],function(a,c){b[c]=!0}),b}n.Callbacks=function(a){a="string"==typeof a?F[a]||G(a):n.extend({},a);var b,c,d,e,f,g,h=[],i=!a.once&&[],j=function(l){for(b=a.memory&&l,c=!0,g=e||0,e=0,f=h.length,d=!0;h&&f>g;g++)if(h[g].apply(l[0],l[1])===!1&&a.stopOnFalse){b=!1;break}d=!1,h&&(i?i.length&&j(i.shift()):b?h=[]:k.disable())},k={add:function(){if(h){var c=h.length;!function g(b){n.each(b,function(b,c){var d=n.type(c);"function"===d?a.unique&&k.has(c)||h.push(c):c&&c.length&&"string"!==d&&g(c)})}(arguments),d?f=h.length:b&&(e=c,j(b))}return this},remove:function(){return h&&n.each(arguments,function(a,b){var c;while((c=n.inArray(b,h,c))>-1)h.splice(c,1),d&&(f>=c&&f--,g>=c&&g--)}),this},has:function(a){return a?n.inArray(a,h)>-1:!(!h||!h.length)},empty:function(){return h=[],f=0,this},disable:function(){return h=i=b=void 0,this},disabled:function(){return!h},lock:function(){return i=void 0,b||k.disable(),this},locked:function(){return!i},fireWith:function(a,b){return!h||c&&!i||(b=b||[],b=[a,b.slice?b.slice():b],d?i.push(b):j(b)),this},fire:function(){return k.fireWith(this,arguments),this},fired:function(){return!!c}};return k},n.extend({Deferred:function(a){var b=[["resolve","done",n.Callbacks("once memory"),"resolved"],["reject","fail",n.Callbacks("once memory"),"rejected"],["notify","progress",n.Callbacks("memory")]],c="pending",d={state:function(){return c},always:function(){return e.done(arguments).fail(arguments),this},then:function(){var a=arguments;return n.Deferred(function(c){n.each(b,function(b,f){var g=n.isFunction(a[b])&&a[b];e[f[1]](function(){var a=g&&g.apply(this,arguments);a&&n.isFunction(a.promise)?a.promise().done(c.resolve).fail(c.reject).progress(c.notify):c[f[0]+"With"](this===d?c.promise():this,g?[a]:arguments)})}),a=null}).promise()},promise:function(a){return null!=a?n.extend(a,d):d}},e={};return d.pipe=d.then,n.each(b,function(a,f){var g=f[2],h=f[3];d[f[1]]=g.add,h&&g.add(function(){c=h},b[1^a][2].disable,b[2][2].lock),e[f[0]]=function(){return e[f[0]+"With"](this===e?d:this,arguments),this},e[f[0]+"With"]=g.fireWith}),d.promise(e),a&&a.call(e,e),e},when:function(a){var b=0,c=d.call(arguments),e=c.length,f=1!==e||a&&n.isFunction(a.promise)?e:0,g=1===f?a:n.Deferred(),h=function(a,b,c){return function(e){b[a]=this,c[a]=arguments.length>1?d.call(arguments):e,c===i?g.notifyWith(b,c):--f||g.resolveWith(b,c)}},i,j,k;if(e>1)for(i=new Array(e),j=new Array(e),k=new Array(e);e>b;b++)c[b]&&n.isFunction(c[b].promise)?c[b].promise().done(h(b,k,c)).fail(g.reject).progress(h(b,j,i)):--f;return f||g.resolveWith(k,c),g.promise()}});var H;n.fn.ready=function(a){return n.ready.promise().done(a),this},n.extend({isReady:!1,readyWait:1,holdReady:function(a){a?n.readyWait++:n.ready(!0)},ready:function(a){(a===!0?--n.readyWait:n.isReady)||(n.isReady=!0,a!==!0&&--n.readyWait>0||(H.resolveWith(l,[n]),n.fn.triggerHandler&&(n(l).triggerHandler("ready"),n(l).off("ready"))))}});function I(){l.removeEventListener("DOMContentLoaded",I,!1),a.removeEventListener("load",I,!1),n.ready()}n.ready.promise=function(b){return H||(H=n.Deferred(),"complete"===l.readyState?setTimeout(n.ready):(l.addEventListener("DOMContentLoaded",I,!1),a.addEventListener("load",I,!1))),H.promise(b)},n.ready.promise();var J=n.access=function(a,b,c,d,e,f,g){var h=0,i=a.length,j=null==c;if("object"===n.type(c)){e=!0;for(h in c)n.access(a,b,h,c[h],!0,f,g)}else if(void 0!==d&&(e=!0,n.isFunction(d)||(g=!0),j&&(g?(b.call(a,d),b=null):(j=b,b=function(a,b,c){return j.call(n(a),c)})),b))for(;i>h;h++)b(a[h],c,g?d:d.call(a[h],h,b(a[h],c)));return e?a:j?b.call(a):i?b(a[0],c):f};n.acceptData=function(a){return 1===a.nodeType||9===a.nodeType||!+a.nodeType};function K(){Object.defineProperty(this.cache={},0,{get:function(){return{}}}),this.expando=n.expando+K.uid++}K.uid=1,K.accepts=n.acceptData,K.prototype={key:function(a){if(!K.accepts(a))return 0;var b={},c=a[this.expando];if(!c){c=K.uid++;try{b[this.expando]={value:c},Object.defineProperties(a,b)}catch(d){b[this.expando]=c,n.extend(a,b)}}return this.cache[c]||(this.cache[c]={}),c},set:function(a,b,c){var d,e=this.key(a),f=this.cache[e];if("string"==typeof b)f[b]=c;else if(n.isEmptyObject(f))n.extend(this.cache[e],b);else for(d in b)f[d]=b[d];return f},get:function(a,b){var c=this.cache[this.key(a)];return void 0===b?c:c[b]},access:function(a,b,c){var d;return void 0===b||b&&"string"==typeof b&&void 0===c?(d=this.get(a,b),void 0!==d?d:this.get(a,n.camelCase(b))):(this.set(a,b,c),void 0!==c?c:b)},remove:function(a,b){var c,d,e,f=this.key(a),g=this.cache[f];if(void 0===b)this.cache[f]={};else{n.isArray(b)?d=b.concat(b.map(n.camelCase)):(e=n.camelCase(b),b in g?d=[b,e]:(d=e,d=d in g?[d]:d.match(E)||[])),c=d.length;while(c--)delete g[d[c]]}},hasData:function(a){return!n.isEmptyObject(this.cache[a[this.expando]]||{})},discard:function(a){a[this.expando]&&delete this.cache[a[this.expando]]}};var L=new K,M=new K,N=/^(?:\{[\w\W]*\}|\[[\w\W]*\])$/,O=/([A-Z])/g;function P(a,b,c){var d;if(void 0===c&&1===a.nodeType)if(d="data-"+b.replace(O,"-$1").toLowerCase(),c=a.getAttribute(d),"string"==typeof c){try{c="true"===c?!0:"false"===c?!1:"null"===c?null:+c+""===c?+c:N.test(c)?n.parseJSON(c):c}catch(e){}M.set(a,b,c)}else c=void 0;return c}n.extend({hasData:function(a){return M.hasData(a)||L.hasData(a)},data:function(a,b,c){ +return M.access(a,b,c)},removeData:function(a,b){M.remove(a,b)},_data:function(a,b,c){return L.access(a,b,c)},_removeData:function(a,b){L.remove(a,b)}}),n.fn.extend({data:function(a,b){var c,d,e,f=this[0],g=f&&f.attributes;if(void 0===a){if(this.length&&(e=M.get(f),1===f.nodeType&&!L.get(f,"hasDataAttrs"))){c=g.length;while(c--)g[c]&&(d=g[c].name,0===d.indexOf("data-")&&(d=n.camelCase(d.slice(5)),P(f,d,e[d])));L.set(f,"hasDataAttrs",!0)}return e}return"object"==typeof a?this.each(function(){M.set(this,a)}):J(this,function(b){var c,d=n.camelCase(a);if(f&&void 0===b){if(c=M.get(f,a),void 0!==c)return c;if(c=M.get(f,d),void 0!==c)return c;if(c=P(f,d,void 0),void 0!==c)return c}else this.each(function(){var c=M.get(this,d);M.set(this,d,b),-1!==a.indexOf("-")&&void 0!==c&&M.set(this,a,b)})},null,b,arguments.length>1,null,!0)},removeData:function(a){return this.each(function(){M.remove(this,a)})}}),n.extend({queue:function(a,b,c){var d;return a?(b=(b||"fx")+"queue",d=L.get(a,b),c&&(!d||n.isArray(c)?d=L.access(a,b,n.makeArray(c)):d.push(c)),d||[]):void 0},dequeue:function(a,b){b=b||"fx";var c=n.queue(a,b),d=c.length,e=c.shift(),f=n._queueHooks(a,b),g=function(){n.dequeue(a,b)};"inprogress"===e&&(e=c.shift(),d--),e&&("fx"===b&&c.unshift("inprogress"),delete f.stop,e.call(a,g,f)),!d&&f&&f.empty.fire()},_queueHooks:function(a,b){var c=b+"queueHooks";return L.get(a,c)||L.access(a,c,{empty:n.Callbacks("once memory").add(function(){L.remove(a,[b+"queue",c])})})}}),n.fn.extend({queue:function(a,b){var c=2;return"string"!=typeof a&&(b=a,a="fx",c--),arguments.lengthx",k.noCloneChecked=!!b.cloneNode(!0).lastChild.defaultValue}();var U="undefined";k.focusinBubbles="onfocusin"in a;var V=/^key/,W=/^(?:mouse|pointer|contextmenu)|click/,X=/^(?:focusinfocus|focusoutblur)$/,Y=/^([^.]*)(?:\.(.+)|)$/;function Z(){return!0}function $(){return!1}function _(){try{return l.activeElement}catch(a){}}n.event={global:{},add:function(a,b,c,d,e){var f,g,h,i,j,k,l,m,o,p,q,r=L.get(a);if(r){c.handler&&(f=c,c=f.handler,e=f.selector),c.guid||(c.guid=n.guid++),(i=r.events)||(i=r.events={}),(g=r.handle)||(g=r.handle=function(b){return typeof n!==U&&n.event.triggered!==b.type?n.event.dispatch.apply(a,arguments):void 0}),b=(b||"").match(E)||[""],j=b.length;while(j--)h=Y.exec(b[j])||[],o=q=h[1],p=(h[2]||"").split(".").sort(),o&&(l=n.event.special[o]||{},o=(e?l.delegateType:l.bindType)||o,l=n.event.special[o]||{},k=n.extend({type:o,origType:q,data:d,handler:c,guid:c.guid,selector:e,needsContext:e&&n.expr.match.needsContext.test(e),namespace:p.join(".")},f),(m=i[o])||(m=i[o]=[],m.delegateCount=0,l.setup&&l.setup.call(a,d,p,g)!==!1||a.addEventListener&&a.addEventListener(o,g,!1)),l.add&&(l.add.call(a,k),k.handler.guid||(k.handler.guid=c.guid)),e?m.splice(m.delegateCount++,0,k):m.push(k),n.event.global[o]=!0)}},remove:function(a,b,c,d,e){var f,g,h,i,j,k,l,m,o,p,q,r=L.hasData(a)&&L.get(a);if(r&&(i=r.events)){b=(b||"").match(E)||[""],j=b.length;while(j--)if(h=Y.exec(b[j])||[],o=q=h[1],p=(h[2]||"").split(".").sort(),o){l=n.event.special[o]||{},o=(d?l.delegateType:l.bindType)||o,m=i[o]||[],h=h[2]&&new RegExp("(^|\\.)"+p.join("\\.(?:.*\\.|)")+"(\\.|$)"),g=f=m.length;while(f--)k=m[f],!e&&q!==k.origType||c&&c.guid!==k.guid||h&&!h.test(k.namespace)||d&&d!==k.selector&&("**"!==d||!k.selector)||(m.splice(f,1),k.selector&&m.delegateCount--,l.remove&&l.remove.call(a,k));g&&!m.length&&(l.teardown&&l.teardown.call(a,p,r.handle)!==!1||n.removeEvent(a,o,r.handle),delete i[o])}else for(o in i)n.event.remove(a,o+b[j],c,d,!0);n.isEmptyObject(i)&&(delete r.handle,L.remove(a,"events"))}},trigger:function(b,c,d,e){var f,g,h,i,k,m,o,p=[d||l],q=j.call(b,"type")?b.type:b,r=j.call(b,"namespace")?b.namespace.split("."):[];if(g=h=d=d||l,3!==d.nodeType&&8!==d.nodeType&&!X.test(q+n.event.triggered)&&(q.indexOf(".")>=0&&(r=q.split("."),q=r.shift(),r.sort()),k=q.indexOf(":")<0&&"on"+q,b=b[n.expando]?b:new n.Event(q,"object"==typeof b&&b),b.isTrigger=e?2:3,b.namespace=r.join("."),b.namespace_re=b.namespace?new RegExp("(^|\\.)"+r.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,b.result=void 0,b.target||(b.target=d),c=null==c?[b]:n.makeArray(c,[b]),o=n.event.special[q]||{},e||!o.trigger||o.trigger.apply(d,c)!==!1)){if(!e&&!o.noBubble&&!n.isWindow(d)){for(i=o.delegateType||q,X.test(i+q)||(g=g.parentNode);g;g=g.parentNode)p.push(g),h=g;h===(d.ownerDocument||l)&&p.push(h.defaultView||h.parentWindow||a)}f=0;while((g=p[f++])&&!b.isPropagationStopped())b.type=f>1?i:o.bindType||q,m=(L.get(g,"events")||{})[b.type]&&L.get(g,"handle"),m&&m.apply(g,c),m=k&&g[k],m&&m.apply&&n.acceptData(g)&&(b.result=m.apply(g,c),b.result===!1&&b.preventDefault());return b.type=q,e||b.isDefaultPrevented()||o._default&&o._default.apply(p.pop(),c)!==!1||!n.acceptData(d)||k&&n.isFunction(d[q])&&!n.isWindow(d)&&(h=d[k],h&&(d[k]=null),n.event.triggered=q,d[q](),n.event.triggered=void 0,h&&(d[k]=h)),b.result}},dispatch:function(a){a=n.event.fix(a);var b,c,e,f,g,h=[],i=d.call(arguments),j=(L.get(this,"events")||{})[a.type]||[],k=n.event.special[a.type]||{};if(i[0]=a,a.delegateTarget=this,!k.preDispatch||k.preDispatch.call(this,a)!==!1){h=n.event.handlers.call(this,a,j),b=0;while((f=h[b++])&&!a.isPropagationStopped()){a.currentTarget=f.elem,c=0;while((g=f.handlers[c++])&&!a.isImmediatePropagationStopped())(!a.namespace_re||a.namespace_re.test(g.namespace))&&(a.handleObj=g,a.data=g.data,e=((n.event.special[g.origType]||{}).handle||g.handler).apply(f.elem,i),void 0!==e&&(a.result=e)===!1&&(a.preventDefault(),a.stopPropagation()))}return k.postDispatch&&k.postDispatch.call(this,a),a.result}},handlers:function(a,b){var c,d,e,f,g=[],h=b.delegateCount,i=a.target;if(h&&i.nodeType&&(!a.button||"click"!==a.type))for(;i!==this;i=i.parentNode||this)if(i.disabled!==!0||"click"!==a.type){for(d=[],c=0;h>c;c++)f=b[c],e=f.selector+" ",void 0===d[e]&&(d[e]=f.needsContext?n(e,this).index(i)>=0:n.find(e,this,null,[i]).length),d[e]&&d.push(f);d.length&&g.push({elem:i,handlers:d})}return h]*)\/>/gi,ba=/<([\w:]+)/,ca=/<|&#?\w+;/,da=/<(?:script|style|link)/i,ea=/checked\s*(?:[^=]|=\s*.checked.)/i,fa=/^$|\/(?:java|ecma)script/i,ga=/^true\/(.*)/,ha=/^\s*\s*$/g,ia={option:[1,""],thead:[1,"","
    "],col:[2,"","
    "],tr:[2,"","
    "],td:[3,"","
    "],_default:[0,"",""]};ia.optgroup=ia.option,ia.tbody=ia.tfoot=ia.colgroup=ia.caption=ia.thead,ia.th=ia.td;function ja(a,b){return n.nodeName(a,"table")&&n.nodeName(11!==b.nodeType?b:b.firstChild,"tr")?a.getElementsByTagName("tbody")[0]||a.appendChild(a.ownerDocument.createElement("tbody")):a}function ka(a){return a.type=(null!==a.getAttribute("type"))+"/"+a.type,a}function la(a){var b=ga.exec(a.type);return b?a.type=b[1]:a.removeAttribute("type"),a}function ma(a,b){for(var c=0,d=a.length;d>c;c++)L.set(a[c],"globalEval",!b||L.get(b[c],"globalEval"))}function na(a,b){var c,d,e,f,g,h,i,j;if(1===b.nodeType){if(L.hasData(a)&&(f=L.access(a),g=L.set(b,f),j=f.events)){delete g.handle,g.events={};for(e in j)for(c=0,d=j[e].length;d>c;c++)n.event.add(b,e,j[e][c])}M.hasData(a)&&(h=M.access(a),i=n.extend({},h),M.set(b,i))}}function oa(a,b){var c=a.getElementsByTagName?a.getElementsByTagName(b||"*"):a.querySelectorAll?a.querySelectorAll(b||"*"):[];return void 0===b||b&&n.nodeName(a,b)?n.merge([a],c):c}function pa(a,b){var c=b.nodeName.toLowerCase();"input"===c&&T.test(a.type)?b.checked=a.checked:("input"===c||"textarea"===c)&&(b.defaultValue=a.defaultValue)}n.extend({clone:function(a,b,c){var d,e,f,g,h=a.cloneNode(!0),i=n.contains(a.ownerDocument,a);if(!(k.noCloneChecked||1!==a.nodeType&&11!==a.nodeType||n.isXMLDoc(a)))for(g=oa(h),f=oa(a),d=0,e=f.length;e>d;d++)pa(f[d],g[d]);if(b)if(c)for(f=f||oa(a),g=g||oa(h),d=0,e=f.length;e>d;d++)na(f[d],g[d]);else na(a,h);return g=oa(h,"script"),g.length>0&&ma(g,!i&&oa(a,"script")),h},buildFragment:function(a,b,c,d){for(var e,f,g,h,i,j,k=b.createDocumentFragment(),l=[],m=0,o=a.length;o>m;m++)if(e=a[m],e||0===e)if("object"===n.type(e))n.merge(l,e.nodeType?[e]:e);else if(ca.test(e)){f=f||k.appendChild(b.createElement("div")),g=(ba.exec(e)||["",""])[1].toLowerCase(),h=ia[g]||ia._default,f.innerHTML=h[1]+e.replace(aa,"<$1>")+h[2],j=h[0];while(j--)f=f.lastChild;n.merge(l,f.childNodes),f=k.firstChild,f.textContent=""}else l.push(b.createTextNode(e));k.textContent="",m=0;while(e=l[m++])if((!d||-1===n.inArray(e,d))&&(i=n.contains(e.ownerDocument,e),f=oa(k.appendChild(e),"script"),i&&ma(f),c)){j=0;while(e=f[j++])fa.test(e.type||"")&&c.push(e)}return k},cleanData:function(a){for(var b,c,d,e,f=n.event.special,g=0;void 0!==(c=a[g]);g++){if(n.acceptData(c)&&(e=c[L.expando],e&&(b=L.cache[e]))){if(b.events)for(d in b.events)f[d]?n.event.remove(c,d):n.removeEvent(c,d,b.handle);L.cache[e]&&delete L.cache[e]}delete M.cache[c[M.expando]]}}}),n.fn.extend({text:function(a){return J(this,function(a){return void 0===a?n.text(this):this.empty().each(function(){(1===this.nodeType||11===this.nodeType||9===this.nodeType)&&(this.textContent=a)})},null,a,arguments.length)},append:function(){return this.domManip(arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=ja(this,a);b.appendChild(a)}})},prepend:function(){return this.domManip(arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=ja(this,a);b.insertBefore(a,b.firstChild)}})},before:function(){return this.domManip(arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this)})},after:function(){return this.domManip(arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this.nextSibling)})},remove:function(a,b){for(var c,d=a?n.filter(a,this):this,e=0;null!=(c=d[e]);e++)b||1!==c.nodeType||n.cleanData(oa(c)),c.parentNode&&(b&&n.contains(c.ownerDocument,c)&&ma(oa(c,"script")),c.parentNode.removeChild(c));return this},empty:function(){for(var a,b=0;null!=(a=this[b]);b++)1===a.nodeType&&(n.cleanData(oa(a,!1)),a.textContent="");return this},clone:function(a,b){return a=null==a?!1:a,b=null==b?a:b,this.map(function(){return n.clone(this,a,b)})},html:function(a){return J(this,function(a){var b=this[0]||{},c=0,d=this.length;if(void 0===a&&1===b.nodeType)return b.innerHTML;if("string"==typeof a&&!da.test(a)&&!ia[(ba.exec(a)||["",""])[1].toLowerCase()]){a=a.replace(aa,"<$1>");try{for(;d>c;c++)b=this[c]||{},1===b.nodeType&&(n.cleanData(oa(b,!1)),b.innerHTML=a);b=0}catch(e){}}b&&this.empty().append(a)},null,a,arguments.length)},replaceWith:function(){var a=arguments[0];return this.domManip(arguments,function(b){a=this.parentNode,n.cleanData(oa(this)),a&&a.replaceChild(b,this)}),a&&(a.length||a.nodeType)?this:this.remove()},detach:function(a){return this.remove(a,!0)},domManip:function(a,b){a=e.apply([],a);var c,d,f,g,h,i,j=0,l=this.length,m=this,o=l-1,p=a[0],q=n.isFunction(p);if(q||l>1&&"string"==typeof p&&!k.checkClone&&ea.test(p))return this.each(function(c){var d=m.eq(c);q&&(a[0]=p.call(this,c,d.html())),d.domManip(a,b)});if(l&&(c=n.buildFragment(a,this[0].ownerDocument,!1,this),d=c.firstChild,1===c.childNodes.length&&(c=d),d)){for(f=n.map(oa(c,"script"),ka),g=f.length;l>j;j++)h=c,j!==o&&(h=n.clone(h,!0,!0),g&&n.merge(f,oa(h,"script"))),b.call(this[j],h,j);if(g)for(i=f[f.length-1].ownerDocument,n.map(f,la),j=0;g>j;j++)h=f[j],fa.test(h.type||"")&&!L.access(h,"globalEval")&&n.contains(i,h)&&(h.src?n._evalUrl&&n._evalUrl(h.src):n.globalEval(h.textContent.replace(ha,"")))}return this}}),n.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){n.fn[a]=function(a){for(var c,d=[],e=n(a),g=e.length-1,h=0;g>=h;h++)c=h===g?this:this.clone(!0),n(e[h])[b](c),f.apply(d,c.get());return this.pushStack(d)}});var qa,ra={};function sa(b,c){var d,e=n(c.createElement(b)).appendTo(c.body),f=a.getDefaultComputedStyle&&(d=a.getDefaultComputedStyle(e[0]))?d.display:n.css(e[0],"display");return e.detach(),f}function ta(a){var b=l,c=ra[a];return c||(c=sa(a,b),"none"!==c&&c||(qa=(qa||n(" + +

    + +
    + +

    中文网页重设与排版:Typo.css


    + +

    一致化浏览器排版效果,构建最适合中文阅读的网页排版

    + +
      +
    1. 关于 Typo.css
    2. +
    3. 排版实例 + +
    4. +
    5. 附录 + +
    6. +
    + +

    一、关于 Typo.css

    + +

    Typo.css 的目的是,在一致化浏览器排版效果的同时,构建最适合中文阅读的网页排版。

    +

    现状和如何去做:

    + +

    排版是一个麻烦的问题 # 附录一,需要精心设计,而这个设计却是常被视觉设计师所忽略的。前端工程师更常看到这样的问题,但不便变更。因为在多个 OS 中的不同浏览器渲染不同,改动需要多的时间做回归测试,所以改变变得更困难。而像我们一般使用的 + Yahoo、Eric Meyer 和 Alice base.css 中采用的 Reset 都没有很好地考虑中文排版。Typo.css 要做的就是解决中文排版的问题。

    + +

    Typo.css 测试于如下平台:

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    OS/浏览器FirefoxChromeSafariOperaIE9IE8IE7IE6
    OS X----
    Win 7-
    Win XP-
    Ubuntu-----
    + +

    中文排版的重点和难点

    + +

    在中文排版中,HTML4 的很多标准在语义在都有照顾到。但从视觉效果上,却很难利用单独的 CSS 来实现,像着重号(例:这里强调一下)。在 HTML4 中,专名号标签(<u>)已经被放弃,而 + HTML5 被重新提起Typo.css 也根据实际情况提供相应的方案。我们重要要注意的两点是:

    +
      +
    1. 语义:语义对应的用法和样式是否与中文排版一致
    2. +
    3. 表现:在各浏览器中的字体、大小和缩放是否如排版预期
    4. +
    +

    对于这些,Typo.css 排版项目的中文偏重注意点,都添加在附录中,详见:

    +
    + 附录一Typo.css 排版偏重点 +
    + +

    目前已有像百姓网等全面使用 Typo.css 的项目,测试平台的覆盖,特别是在移动端上还没有覆盖完主流平台,希望有能力的同学能加入测试行列,或者加入到 Typo.css + 的开发。加入方法:参与 Typo.css 开发。如有批评、建议和意见,也随时欢迎给在 Github 直接提 issues,或给邮件

    + + +

    二、排版实例:

    + +

    提供2个排版实例,第一个中文实例来自于来自于张燕婴的《论语》,由于古文排版涉及到的元素比较多,所以采用《论语》中《学而》的第一篇作为排版实例介绍;第2个来自到经典的 + Lorem Ipsum,并加入了一些代码和列表等比较具有代表性的排版元素。

    + +

    例1:论语学而篇第一

    + +

    + 作者:孔子( + + ) + +

    + +

    本篇引语

    + +

    + 《学而》是《论语》第一篇的篇名。《论语》中各篇一般都是以第一章的前二三个字作为该篇的篇名。《学而》一篇包括16章,内容涉及诸多方面。其中重点是「吾日三省吾身」;「节用而爱人,使民以时」;「礼之用,和为贵」以及仁、孝、信等道德范畴。

    + +

    原文

    + +

    子曰:「学而时习之,不亦说乎?有朋自远方来,不亦乐乎?人不知,而不愠,不亦君子乎?」

    + +

    译文

    + +

    孔子说:「学了又时常温习和练习,不是很愉快吗?有志同道合的人从远方来,不是很令人高兴的吗?人家不了解我,我也不怨恨、恼怒,不也是一个有德的君子吗?」

    + +

    评析

    + +

    宋代著名学者朱熹对此章评价极高,说它是「入道之门,积德之基」。本章这三句话是人们非常熟悉的。历来的解释都是:学了以后,又时常温习和练习,不也高兴吗等等。三句话,一句一个意思,前后句子也没有什么连贯性。但也有人认为这样解释不符合原义,指出这里的「学」不是指学习,而是指学说或主张;「时」不能解为时常,而是时代或社会的意思,「习」不是温习,而是使用,引申为采用。而且,这三句话不是孤立的,而是前后相互连贯的。这三句的意思是:自己的学说,要是被社会采用了,那就太高兴了;退一步说,要是没有被社会所采用,可是很多朋友赞同的学说,纷纷到我这里来讨论问题,我也感到快乐;再退一步说,即使社会不采用,人们也不理解我,我也不怨恨,这样做,不也就是君子吗?(见《齐鲁学刊》1986年第6期文)这种解释可以自圆其说,而且也有一定的道理,供读者在理解本章内容时参考。 +

    + +

    此外,在对「人不知,而不愠」一句的解释中,也有人认为,「人不知」的后面没有宾语,人家不知道什么呢?当时因为孔子有说话的特定环境,他不需要说出知道什么,别人就可以理解了,却给后人留下一个谜。有人说,这一句是接上一句说的,从远方来的朋友向我求教,我告诉他,他还不懂,我却不怨恨。这样,「人不知」就是「人家不知道我所讲述的」了。这样的解释似乎有些牵强。

    + +

    总之,本章提出以学习为乐事,做到人不知而不愠,反映出孔子学而不厌、诲人不倦、注重修养、严格要求自己的主张。这些思想主张在《论语》书中多处可见,有助于对第一章内容的深入了解。

    + +

    例2:英文排版

    + +

    Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's + standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a + type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining + essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum + passages, and more recently with desktop publishing software sympathy Aldus PageMaker including versions of Lorem + Ipsum.

    +
    + Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna + aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. +
    + +

    The standard Lorem Ipsum passage, used since the 1500s

    + +

    "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna + aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. + Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint + occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."

    + +

    Section 1.10.32 of "de Finibus Bonorum et Malorum", written by Cicero in 45 BC

    + +

    "Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, + eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo. Nemo enim ipsam + voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione + voluptatem sequi nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci + velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem. Ut enim + ad minima veniam, quis nostrum exercitationem ullam corporis suscipit laboriosam, nisi ut aliquid ex ea commodi + consequatur? Quis autem vel eum iure reprehenderit qui in ea voluptate velit esse quam nihil molestiae consequatur, + vel illum qui dolorem eum fugiat quo voluptas nulla pariatur?"

    + +

    List style in action

    +
      +
    • If you wish to succeed, you should use persistence as your good friend, experience as your reference, prudence as + your brother and hope as your sentry. +

      如果你希望成功,当以恒心为良友,以经验为参谋,以谨慎为兄弟,以希望为哨兵。

      +
    • +
    • Sometimes one pays most for the things one gets for nothing. +

      有时候一个人为不花钱得到的东西付出的代价最高。

      +
    • +
    • Only those who have the patience to do simple things perfectly ever acquire the skill to do difficult things + easily. +

      只有有耐心圆满完成简单工作的人,才能够轻而易举的完成困难的事。

      +
    • +
    + +

    You may want to create a perfect <hr /> line, despite the fact that there will never have one +

    +
    +

    La Racheforcauld said: + "Few things are impossible in themselves; and it is often for want of will, rather than of means, that man fails + to succeed". + + You just need to follow the browser's behavior, and set a right margin to it。it will works nice as the + demo you're watching now. The following code is the best way to render typo in Chinese: +

    +
    +/* 标题应该更贴紧内容,并与其他块区分,margin 值要相应做优化 */
    +h1,h2,h3,h4,h5,h6 {
    +    line-height:1;font-family:Arial,sans-serif;margin:1.4em 0 0.8em;
    +}
    +h1{font-size:1.8em;}
    +h2{font-size:1.6em;}
    +h3{font-size:1.4em;}
    +h4{font-size:1.2em;}
    +h5,h6{font-size:1em;}
    +
    +/* 现代排版:保证块/段落之间的空白隔行 */
    +.typo p, .typo pre, .typo ul, .typo ol, .typo dl, .typo form, .typo hr {
    +    margin:1em 0 0.6em;
    +}
    +
    + +

    三、附录

    + +
    1、Typo.css 排版偏重点
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    类型语义标签注意点
    基础标签标题h1h6全局不强制大小,.typo 中标题与其对应的内容应紧贴,并且有相应的大小设置
    上、下标sup/sub保持与 MicroSoft Office Word 等程序的日常排版一致
    引用blockquote显示/嵌套样式
    缩写abbr是否都有下划线,鼠标 hover 是否为帮助手势
    分割线hr显示的 paddingmargin正确
    列表ul/ol/dl在全局没有 list-style,在 .typo 中对齐正确
    定义列表dl全局 paddingmargin为0, .typo 中对齐正确
    选项input[type=radio[, checkbox]]与其他 form 元素排版时是否居中
    斜体i只设置一种斜体,让 emcite 显示为正体
    强调em在全局显示正体,在 .typo 中显示与 bstrong 的样式一致,为粗体
    加强strong/b显示为粗体
    标记mark类似荧光笔
    印刷small保持为正确字体的 80% 大小,颜色设置为浅灰色
    表格table全局不显示线条,在 table 中显示表格外框,并且表头有浅灰背景
    代码pre/code字体使用 courier 系字体,保持与 serif 有比较一致的显示效果
    特殊符号着重号在文字下加点在支持 :after:before 的浏览器可以做渐进增强实现
    专名号林建锋专名号,有下划线,使用 u 或都 .typo-u
    破折号——保持一划,而非两划
    人民币¥使用两平等线的符号,或者 HTML 实体符号 &yen;
    删除符 + 已删除(deleted) + 一致化各浏览器显示,中英混排正确
    加强类专名号.typo-u由于 u 被 HTML4 放弃,在向后兼容上推荐使用 .typo-u
    着重符.typo-em利用 :after:before 实现着重符
    清除浮动.clearfix与一般 CSS Reset 保持一对致 API
    注意点(1)中英文混排行高/行距
    (2)上下标在 IE 中显示效果
    (3)块/段落分割空白是否符合设计原则
    (4)input 多余空间问题
    (5)默认字体色彩,目前采用 #333 在各种浏览显示比较好
    + +
    2、开源许可
    + +

    Typo.css 基于 MIT License 开源,使用代码只需说明来源,或者引用 license.txt 即可。

    +
    + + + Fork me on GitHub + + + + diff --git a/src/main/resources/resources/vendors/typo.css-2.1.2/typo.min.css b/src/main/resources/resources/vendors/typo.css-2.1.2/typo.min.css new file mode 100644 index 0000000..9a83587 --- /dev/null +++ b/src/main/resources/resources/vendors/typo.css-2.1.2/typo.min.css @@ -0,0 +1 @@ +@charset "utf-8";html{color: #333;background: #fff;-webkit-text-size-adjust: 100%;-ms-text-size-adjust: 100%;text-rendering: optimizelegibility}html.borderbox *, html.borderbox *:before, html.borderbox *:after{-moz-box-sizing: border-box;-webkit-box-sizing: border-box;box-sizing: border-box}body, dl, dt, dd, ul, ol, li, h1, h2, h3, h4, h5, h6, pre, code, form, fieldset, legend, input, textarea, p, blockquote, th, td, hr, button, article, aside, details, figcaption, figure, footer, header, menu, nav, section{margin: 0;padding: 0}article, aside, details, figcaption, figure, footer, header, menu, nav, section{display: block}audio, canvas, video{display: inline-block}body, button, input, select, textarea{font: 300 1em/1.8 PingFang SC, Lantinghei SC, Microsoft Yahei, Hiragino Sans GB, Microsoft Sans Serif, WenQuanYi Micro Hei, sans}button::-moz-focus-inner,input::-moz-focus-inner{padding: 0;border: 0}table{border-collapse: collapse;border-spacing: 0}fieldset, img{border: 0}blockquote{position: relative;color: #999;font-weight: 400;border-left: 1px solid #1abc9c;padding-left: 1em;margin: 1em 3em 1em 2em}@media only screen and ( max-width: 640px ){blockquote{margin: 1em 0}}acronym, abbr{border-bottom: 1px dotted;font-variant: normal}abbr{cursor: help}del{text-decoration: line-through}address, caption, cite, code, dfn, em, th, var{font-style: normal;font-weight: 400}ul, ol{list-style: none}caption, th{text-align: left}q:before, q:after{content: ''}sub, sup{font-size: 75%;line-height: 0;position: relative}:root sub, :root sup{vertical-align: baseline}sup{top: -0.5em}sub{bottom: -0.25em}a{color: #1abc9c}a:hover{text-decoration: underline}.typo a:hover{color: #555;text-decoration: none}ins, a{text-decoration: none}u, .typo-u{text-decoration: underline}mark{background: #fffdd1;border-bottom: 1px solid #ffedce;padding: 2px;margin: 0 5px}pre, code, pre tt{font-family: Courier, 'Courier New', monospace}pre{background: #f8f8f8;border: 1px solid #ddd;padding: 1em 1.5em;display: block;-webkit-overflow-scrolling: touch}hr{border: none;border-bottom: 1px solid #cfcfcf;margin-bottom: 0.8em;height: 10px}small, .typo-small,figcaption{font-size: 0.9em;color: #888}strong, b{font-weight: bold;color: #000}[draggable]{cursor: move}.clearfix:before, .clearfix:after{content: "";display: table}.clearfix:after{clear: both}.clearfix{zoom: 1}.textwrap, .textwrap td, .textwrap th{word-wrap: break-word;word-break: break-all}.textwrap-table{table-layout: fixed}.serif{font-family: Palatino, Optima, Georgia, serif}.typo p, .typo pre, .typo ul, .typo ol, .typo dl, .typo form, .typo hr, .typo table,.typo-p, .typo-pre, .typo-ul, .typo-ol, .typo-dl, .typo-form, .typo-hr, .typo-table, blockquote{margin-bottom: 1.2em}h1, h2, h3, h4, h5, h6{font-family: PingFang SC, Verdana, Helvetica Neue, Microsoft Yahei, Hiragino Sans GB, Microsoft Sans Serif, WenQuanYi Micro Hei, sans-serif;font-weight: 100;color: #000;line-height: 1.35}.typo h1, .typo h2, .typo h3, .typo h4, .typo h5, .typo h6,.typo-h1, .typo-h2, .typo-h3, .typo-h4, .typo-h5, .typo-h6{margin-top: 1.2em;margin-bottom: 0.6em;line-height: 1.35}.typo h1, .typo-h1{font-size: 2em}.typo h2, .typo-h2{font-size: 1.8em}.typo h3, .typo-h3{font-size: 1.6em}.typo h4, .typo-h4{font-size: 1.4em}.typo h5, .typo h6, .typo-h5, .typo-h6{font-size: 1.2em}.typo ul, .typo-ul{margin-left: 1.3em;list-style: disc}.typo ol, .typo-ol{list-style: decimal;margin-left: 1.9em}.typo li ul, .typo li ol, .typo-ul ul, .typo-ul ol, .typo-ol ul, .typo-ol ol{margin-bottom: 0.8em;margin-left: 2em}.typo li ul, .typo-ul ul, .typo-ol ul{list-style: circle}.typo table th, .typo table td, .typo-table th, .typo-table td, .typo table caption{border: 1px solid #ddd;padding: 0.5em 1em;color: #666}.typo table th, .typo-table th{background: #fbfbfb}.typo table thead th, .typo-table thead th{background: #f1f1f1}.typo table caption{border-bottom: none}.typo-input, .typo-textarea{-webkit-appearance: none;border-radius: 0}.typo-em, .typo em, legend, caption{color: #000;font-weight: inherit}.typo-em{position: relative}.typo-em:after{position: absolute;top: 0.65em;left: 0;width: 100%;overflow: hidden;white-space: nowrap;content: "・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・"}.typo img{max-width: 100%} diff --git a/src/main/resources/static/favicon-16x16.png b/src/main/resources/static/favicon-16x16.png new file mode 100644 index 0000000000000000000000000000000000000000..802037e26107393b768dd1e0942c6a15d9a431ca GIT binary patch literal 1065 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!63?wyl`GbKJOS+@4BLl<6e(pbstU$g(vPY0F z14ES>14Ba#1H&(%P{RubhEf9thF1v;3|2E37{m+a>U*n@)NEtmkah6k(6Nj_13z+QjU?4;pnQ|{_J7H@2{-iJ+cHEV>0*FYlT^yJdd)gwgZ~DytT1ESswVluApK03x84-uKNDk`u97VKkse6Jh%Gs+WONo ztG5pn=YQ4$tTR&S`V`zxng+u8;rE z2l~QW{{EQH&UauVd*G*O9Dc9PiWL3*7|A>N-%0+!pMQ!N`sfLmmz>bvCQk{NF&Ky`CLQP9~ zeRb8?G!m{|yLk2VHFJZMMy?G~lCx9NXV03s+40948L?@WJ1c*NU7Hh=z?df;y}Rkq zqNHkecexD=>n9g`W=2-J&g|Bfk7$TLaCYySHAc%%9S#=IQBZmFG&XidbnxrPr+Ebh zK7L-mdc}Eu4iVAj2xU1DnM(mTB&5_Bi)W@(xC9rcglrM8f};Gi%$!t(lFEWqh0KDIWCn(cIgdZ_a1@4VXq@stea7=?5CgL^w_Y;0u(GiC zWD#az1(ybs!zs+ln?n>%-?(z($eANDN7zp{cr5VJV|XPlSn|oqbSlsa22WQ%mvv4F FO#sdFn}q-X literal 0 HcmV?d00001 diff --git a/src/main/resources/static/favicon-32x32.png b/src/main/resources/static/favicon-32x32.png new file mode 100644 index 0000000000000000000000000000000000000000..62b7c406ec52f0fccde47c5d4f81a1aca13f5852 GIT binary patch literal 1834 zcmbVNX;f3!7QRU!2}2+dNEjppC_<26AOo3X3=0rN8l#|v5Fh~&ERlvHwxradE#TCL z)jp(_LPaW~1=@--RBKuhPy|tiGAVNskU>x&aC`jKU+>R5>)yN9xn~dG{=R+J&5w!< z#TnZfLlA@u4-<-jrM$bbDDV{iSnwAx1}T9%10ks9tcgCs@ZDijm}n;i9o-B;c_$!f z6}-xuf}kuq1ZkuY#QPS4NQ#m>?+YLZITf`-90D8=2nd5lMs6p-uoQ`e65~iXQ&iLr z!Uxer818^!`21;?;ioKfGXtudaZfvAugIFi!ohIN{1`VP)N(7${P|JG3uoRdD|V~D>3R1zuaRdgKfXDgW&#TR zeAVO5&z|x7NuUdme@B>QZKX$JEv>TDeWKs@We@wOQuk|R)RQWTEZ(N;fe&yK2H=lm zIvkYQf^B0R4U0ua@3!_An1d4ikD23rzOScv-4A_Qn&_>+(=Qddf)KFkZ+KS!NUbWP z4m@FIrrUq<8D(aKQ&Z^yjtG{9C=}xCSI!MJo^xYd&;V zX>zH}xqN4k2h=^3Vh1{kjUfUl0pZC~n*&L$2D>^=)ePdp*IwP3;+jn(_58#dV zuz`FtFSv7~-04AIKs(@V=qYQwkNs+tyD=wNp5_D0OVhlS8UA1w>#dIecL!5D#F-!G z0=kwp{JzJ`=WUGFlRO|OnBkQ4d^fgL!z+sQ)g+?2(PI1T z@L6-mMzZU})iU(9#cogIlCdCCg}&V4hhNgxpT}YAkL-H3u9J`tv~2VpV^dnkc)4FE z$f7?GOZOZ|R46}N#9Y>b9uSEUp+XbK9`#+Y!6?IbhG1TpVu@~O-pPzL@QLHXg@IyD zTW*(JK?t-#kKpjv>l+NSvuRNSgS!U?;|dzU;)i}%6tS3lF~Z*KqQuDxdGY1)C4J(= ziBDi%yQ)Li%&$A4FFeW2=&aqNW!D^H;P1=Qd;D$$KZyLULHS6=GWc&pR*HmYgR$>% zDZIx?>yR|9MO`f{pKV@WHE*dv^jO~NS4duom5vnM+Q?N?Pl+ht zY0XHN+~z`&TG1c650S7^5Y!)SCAq!*R7-(#okf6C!cwubCZ{tot;dk^ooYdK=7MRa zk+!fZFdt{{8xrx7BoQhW+9znP&q}+WABuhbdFiKyV%eKzhbt`WR^7m#^9d(1$flhm zv)klZ@nr);xoceN;G@o0HXP}#X@B9$@h_c?weuCi2=bZgQp|4!p=S#GRU63Hj{HcE z>A-P@S9_V8YJ_tsr) z?cw7h2<2kpm1IJ2Aw(2ep$HUV9`n8o)R?xsu+r^bkcMQTTnJ)) Q14=;QA(6rxLDFOY03F!)?*IS* literal 0 HcmV?d00001 diff --git a/src/main/resources/static/favicon.ico b/src/main/resources/static/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..70fb5a9e8e9452a643677283114dafac84870c53 GIT binary patch literal 15086 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 Le!gSOQ